当前位置: 首页 > news >正文

Kafka设计与原理详解

RocketMQ 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。同时,广泛应用于多个领域,包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即时通信、移动应用、手游、视频、物联网、车联网等。

「RocketMQ本质上的设计思路和Kafka类似」,但是和Kafka不同的是其使用Java进行开发,由于在国内的Java受众群体远远多于Scala、Erlang,所以RocketMQ是很多以Java语言为主的公司的首选。同样的RocketMQ和Kafka都是Apache基金会中的顶级项目,他们社区的活跃度都非常高,项目更新迭代也非常快。

RocketMQ是阿里review kafka的java版,如果消息性能要求高,用 RocketMQ 与 Kafka 可以更优

消息队列在实际应用中常用的使用场景,包含「应用解耦、异步处理、流量削锋、消息通讯、日志处理」等。

RocketMQ运行原理

 

上面是RocketMQ运行的一个大致流程图。

在对Apache RocketMQ进行深入探索的过程中,我们首先需要理解其核心组件的作用:

NameServer:充当注册中心的角色,主要任务是管理Broker节点.

Broker:它是RocketMQ系统的核心部分,主要负责消息的存储。

Producer:这是消息的生成者,它创建消息并将其写入Broker。

Consumer:作为消息的接收者,负责从Broker读取消息并进行处理。

下面,让我们一起深入了解RocketMQ的运行流程:

1. 首先,Broker在启动后会向根据其配置向NameServer注册。

2. NameServer作为注册中心,管理着我们的Broker集群信息以及Topic路由信息。例如,一个特定的Topic具有哪些Broker主机以及队列信息。

3. 接着,由特定的业务系统中的生产者(Producer)生成消息,并发送到Broker的主节点。

4. 在Broker节点中,这些消息将被保存到本地磁盘的CommitLog中,以确保消息不会丢失。

5. 接下来,主节点Broker将这些消息同步到从节点Broker,这样可以实现负载均衡并增强系统的鲁棒性。

6. 最后,业务系统中的消费者(Consumer)会从Broker中取出消息并进行处理,这就完成了数据的完整生命周期。

我们的Producer写入消息前需要先选择Broker,那Producer是如何选择Broker的呢?

上面提到,NameServer 在 RocketMQ 架构中起到了注册中心的作用,它负责管理所有的 Broker 节点。每当 Broker 启动后,它就会自动的注册到 NameServer 中,并且会每隔30秒向 NameServer 发送一次心跳,以证明它依然在运行。NameServer 则会每隔10秒检查一次各个 Broker 节点是否还在线,如果有 Broker 在120秒内未发送心跳,那么 NameServer 就会判断该 Broker 已经宕机,进而将其从注册列表中移除。

在业务系统中,Producer 在发送消息之前,会先从 NameServer 中拉取需要的 topic 路由信息,这些信息将包含目标 topic 各个 queue 的详细信息,以及各 queue 分别存储在哪个 Broker 节点上。Producer 会将这些信息缓存到本地,并依此信息,通过一种负载均衡算法,选择从哪个 queue 中读取数据,以及找到该 queue 对应的 Broker 节点。

那么,如果某个 Broker 在 Producer 准备写入数据的时候突然宕机了,又该如何处理呢?

RocketMQ 设计了一套故障探测与处理机制。如果某个 Broker 宕机了,那么 Producer 进行写入操作时将会失败,此时,它会发起重试操作,并从可用的 Broker 列表中重新选择一个进行写入。并且,为避免持续向故障节点写入数据,Producer 会采取一种称为"故障退避"的策略,即在一段时间内停止向该 Broker 发送数据。值得注意的是,Broker 的故障并不会立即被 Producer 和 NameServer 感知,这样做是为了降低 NameServer 处理逻辑的复杂性。当 Broker 宕机后,由于本地的 topic 路由缓存并未更新,Producer 仍可能尝试向故障的 Broker 发送数据,然后备受失败并重试。只有当 NameServer 在检查心跳时发现该 Broker 已宕机,并从注册列表中移除后,Producer 在刷新本地缓存时,才会真正地感知到该 Broker 的宕机。

当我们的Producer基于负载均衡选择了Broker节点,它的消息是如何写入的呢?

 

在深入理解 RocketMQ 的存储机制时,我们需要知道,Producer 在写入消息时,默认会优先写到操作系统管理的 pageCache,这个过程是异步的,只要消息被写入 pageCache,写入操作就被认为是成功的。这种异步的处理方式极大地提高了 RocketMQ 的写入效率。

当消息被写入 pageCache 后,将有一个后台线程异步地将这些消息从 pageCache 刷入到磁盘文件 CommitLog 中,CommitLog 是消息的实际存储位置。同时,还会有一个专门的线程负责将 CommitLog 中的消息位置(物理偏移量)写入到 ConsumeQueue 中。

那么客户端如何读取存储在 CommitLog 中的消息呢?

当 Consumer 端的消费者需要读取消息时,它会先到ConsumeQueue,然后根据在 ConsumeQueue 中存储的 offset 信息找到 CommitLog 中的实际数据进行读取。

这样的存储方法是否可以支持高并发模式的写入呢?

当系统面临大量同时写入和读取的请求时,可能会遇到一种情况,即大量的读取请求通过 ConsumeQueue 去找 CommitLog 中的数据,但是此时数据可能还在 pageCache 中并未完成异步写入。这时,系统会通过 CommitLog 和 PageCache 的映射,找到 pageCache 中的消息进行读取。也就是说,大量的读取和写入请求都对 pageCache 进行操作。但是当并发量过高时,可能会出现 "Broker busy" 的异常,这是因为在极高的并发场景下,持续大量的读写操作可能会对系统性能造成影响。

简而言之,RocketMQ 的存储机制旨在为高并发高效的读写提供支持,但是在一些极端情况下,仍然需要额外的优化措施以提高稳定性和性能。

当并发量非常高时,出现Broker busy异常了,如何解决?

RocketMQ 在面对高并发场景时,为了改善 "Broker busy" 异常和提高吞吐量,可以启用 transientStorePool 机制。这种机制的实现方式是,Broker 在写入消息时,将消息直接写入由 JVM 管理的 offheap 堆外内存,这样的设计能有效提升并发性能。

那么,为什么启用 transientStorePool 可以提高并发处理能力呢?

当开启该机制后,消息首先写入 JVM 的 offheap内存,然后异步刷新到 pageCache,最终由 pageCache 异步刷新到 CommitLog。大量的写请求将向 JVM 的 heap 内存进行,而大量的读请求仍然从 pageCache 进行,这种读写分离的机制极大地提高了 RocketMQ 的并发性能。

但是为什么 transientStorePool 机制不作为默认机制呢?

虽然 transientStorePool 能显著提升并发性能,但其也存在风险。当消息写入到 JVM 管理的 offheap 堆外内存后,如果 JVM 进程重启或者宕机,那些尚未被及时落盘的消息就会丢失。但如果采用默认的写入方法,即先写入操作系统管理的 pageCache,那么在 JVM 进程重启后,那些保存在 pageCache 中的信息不会丢失,只有当整个服务器宕机重启时,pageCache 中的消息才有可能丢失。因此,数据最安全的处理方式是,将其直接写入到 CommitLog。

总结:开启 transientStorePool 机制可以极大地提高 RocketMQ 的并发处理能力,然而这可能会带来数据的丢失。因此,它更适合那些并发处理能力要求高、且可以接受部分数据丢失的场景。

如果我们想要写入数据不丢失,应该怎么处理?

在设计与金融场景以及其他要求数据不能丢失的环境中,我们会采用同步方式将数据写入CommitLog。成功执行写入操作后才返回,确保了数据的完整性和安全性。只有在broker的物理存储设备出现故障的情况下,才有可能导致数据丢失。为了提供进一步提高数据的安全性,也可以通过多台服务器进行数据备份。

但值得注意的是, 尽管实现了对数据的安全性提升, 使用同步写入CommitLog方式会降低系统的性能到几个数量级。

Rocketmq如何支持分布式事务消息

 场景

A(存在DB操作)、B(存在DB操作)两方需要保证分布式事务一致性,通过引入中间层MQ,

A和MQ保持事务一致性(异常情况下通过MQ反查A接口实现check),

B和MQ保证事务一致(通过重试),从而达到最终事务一致性。

「原理:大事务 = 小事务 + 异步」

「1.MQ与DB一致性原理(两方事务)」

流程图

上图是RocketMQ提供的保证MQ消息、DB事务一致性的方案。

「MQ消息、DB操作一致性方案:」

1)发送消息到MQ服务器,此时消息状态为SEND_OK。此消息为consumer不可见。

2)执行DB操作;DB执行成功Commit DB操作,DB执行失败Rollback DB操作。

3)如果DB执行成功,回复MQ服务器,将状态为COMMIT_MESSAGE;如果DB执行失败,回复MQ服务器,将状态改为ROLLBACK_MESSAGE。注意此过程有可能失败。

4)MQ内部提供一个名为“事务状态服务”的服务,此服务会检查事务消息的状态,如果发现消息未COMMIT,则通过Producer启动时注册的TransactionCheckListener来回调业务系统,业务系统在checkLocalTransactionState方法中检查DB事务状态,如果成功,则回复COMMIT_MESSAGE,否则回复ROLLBACK_MESSAGE。

「说明:」

上面以DB为例,其实此处可以是任何业务或者数据源。

以上SEND_OK、COMMIT_MESSAGE、ROLLBACK_MESSAGE 均是client jar提供的状态,在MQ服务器内部是一个数字。

TransactionCheckListener 是在消息的commit或者rollback消息丢失的情况下才会回调(上图中灰色部分)。这种消息丢失只存在于断网或者RocketMQ集群挂了的情况下。当RocketMQ集群挂了,如果采用异步刷盘,存在1s内数据丢失风险,异步刷盘场景下保障事务没有意义。所以如果要核心业务用RocketMQ解决分布式事务问题,建议选择同步刷盘模式。

「2.多系统之间数据一致性(多方事务)」

当需要保证多方(超过2方)的分布式一致性,上面的两方事务一致性(通过RocketMQ的事务性消息解决)已经无法支持。这个时候需要引入TCC模式思想(Try-Confirm-Cancel,不清楚的自行百度)。

「以上图交易系统为例:」

1)交易系统创建订单(往DB插入一条记录),同时发送订单创建消息。通过RocketMQ事务性消息保证一致性

2)接着执行完成订单所需的同步核心RPC服务(非核心的系统通过监听MQ消息自行处理,处理结果不会影响交易状态)。执行成功更改订单状态,同时发送MQ消息。

3)交易系统接受自己发送的订单创建消息,通过定时调度系统创建延时回滚任务(或者使用RocketMQ的重试功能,设置第二次发送时间为定时任务的延迟创建时间。在非消息堵塞的情况下,消息第一次到达延迟为1ms左右,这时可能RPC还未执行完,订单状态还未设置为完成,第二次消费时间可以指定)。延迟任务先通过查询订单状态判断订单是否完成,完成则不创建回滚任务,否则创建。PS:多个RPC可以创建一个回滚任务,通过一个消费组接受一次消息就可以;也可以通过创建多个消费组,一个消息消费多次,每次消费创建一个RPC的回滚任务。回滚任务失败,通过MQ的重发来重试。

以上是交易系统和其他系统之间保持最终一致性的解决方案。

「3.案例分析」

「1) 单机环境下的事务示意图」

如下为A给B转账的例子。如下为A给B转账的例子。

以上过程在代码层面,甚至可以简化到在一个事物中,执行两条sql语句。

「2) 分布式环境下事务」

和单机事务不同,A、B账户可能不在同一个DB中,此时无法像在单机情况下使用事务来实现。

此时可以通过以下方式实现,将转账操作分成两个操作。

a) A账户

b) MQ消息

A账户数据发生变化时,发送MQ消息,MQ服务器将消息推送给转账系统,转账系统来给B账号加钱。

c) B账户

 

顺序消息 

RocketMq有3种消息类型

  1. 普通消费

  2. 顺序消费

  3. 事务消费

顺序消费场景:在网购的时候,我们需要下单,那么下单需要假如有三个顺序:

第一:创建订单 第二:订单付款 第三:订单完成

也就是这三个环节要有顺序,这个订单才有意义,RocketMQ可以保证顺序消费。

「RocketMQ 实现顺序消费的原理」:produce在发送消息的时候,把消息发到同一个队列(queue)中,消费者注册消息监听器为MessageListenerOrderly,这样就可以保证消费端只有一个线程去消费消息

「注意:是把把消息发到同一个队列(queue),不是同一个topic,默认情况下一个topic包括4个queue」

「1. 顺序消息缺陷」

发送顺序消息,无法利用集群Fail Over特性,消费顺序消息的并行度依赖于队列数量队列热点问题,个别队列由于哈希不均导致消息过多,消费速度跟不上,产生消息堆积问题遇到消息失败的消息,无法跳过,当前队列消费暂停。

「2. 原理」

produce在发送消息的时候,把消息发到同一个队列(queue)中,消费者注册消息监听器为MessageListenerOrderly,这样就可以保证消费端只有一个线程去消费消息。

「3. 扩展」

可以通过实现发送消息的队列选择器方法,实现部分顺序消息。

举例:比如一个数据库通过MQ来同步,只需要保证每个表的数据是同步的就可以。解析binlog,将表名作为队列选择器的参数,这样就可以保证每个表的数据到同一个对列里面,从而保证表数据的顺序消费

 

 

 

 

相关文章:

Kafka设计与原理详解

RocketMQ 是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。同时,广泛应用于多个领域,包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即…...

IPV6公网暴露下的OPENWRT防火墙安全设置(只允许访问局域网中指定服务器指定端口其余拒绝)

首先是防火墙的常规配置和区域配置 标的有点乱但是选项含义都做了解释,看不懂可以直接按图抄作业。 其次是对需要访问的端口做访问放通 情况1 DDNS位于openwrt网关上,外网访问openwrt,通过端口转发访问内部服务器。此情况需要设置端口转发。 …...

单调栈② | Java | LeetCode 接雨水 最大的矩形

42. 接雨水 暴力法 for循环遍历每一个柱子,内层for循环找到左边和右边比它高的柱子 时间复杂度 n^2 优化:添加一个预处理 定义一个数组,存放该柱子右边比他高的柱子是哪一个 再用一个数组,存放该柱子左边比他高的柱子是哪一个 …...

2024年全国青少年信息素养大赛总决赛日赛程表

2024全国青少年信息素养大赛赛程表分赛场(浙江传媒学院桐乡校区、桐乡技师学院)日期地点时间赛项16日传媒学院8:00-9:00检录 9:00-10:30开赛图形化编程挑战赛(小学1-3年级)A组12:00-13:00检录 13:00-14:30开赛图形化编程挑战赛&am…...

PHP:连接钉钉接口-钉钉回调事件,本地测试数据

前置数据参考 数据说明:参见官方文档回调事件消息体加解密 - 钉钉开放平台 (dingtalk.com) URL后面带的参数: signature5a65ceeef9aab2d149439f82dc191dd6c5cbe2c0&timestamp1445827045067&noncenEXhMP4r Post参数: { &quo…...

【C++标准模版库】vector的介绍及使用

vector 一.vector的介绍二.vector的使用1.vector 构造函数2.vector 空间增长3.vector 增删查改4.vector 迭代器的使用1.正向迭代器2.反向迭代器 5.victor 迭代器失效问题(重点) 三.vector不支持 流提取与流插入四.vector存储自定义类型1.存储string2.存储…...

数说故事|引爆社媒的森贝儿IP,品牌如何实现流量变现?

以可爱、雅痞、贱萌......的外表加魔性舞姿出圈的可爱小狗——森贝儿贵宾犬Milo,用“可爱微怒”的表情演绎着当代打工人的“疯态”,并迅速晋升成不少打工人高频使用的表情包。 最近几年,“萌系”爆款IP频出,用小动物的形象、可爱…...

使用openpyxl库对Excel条件格式的深度探索

哈喽,大家好,我是木头左! openpyxl中的条件格式 在openpyxl中,可以使用ConditionalFormatting类来创建和管理条件格式。这个类有两个主要的方法:add_conditional_formatting()和remove_conditional_formatting(),分别用于添加和删除条件格式。 add_conditional_formatt…...

原生javascript中的ajax通信技术

AJAX(Asynchronous JavaScript and XML)是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。也就是实现前后端交互的功能。以下是使用AJAX的基本步骤和代码演示: 1.创建一个XMLHttpRequest对象: var xhr…...

SpringBoot Vue用自签名证书SSL配置https,http转发到https(整理文章)

要配置https地址访问,需要向服务器商申请和使用SSL证书。由于是测试阶段,我们自己创建SSL证书,叫作自签名证书。 1.创建自签名证书 Vue前端生成自签名证书我们用openssl 参考文章一 参考文章二SpringBoot后端生成自签名证书用JDK自带的keyt…...

嵌入式人工智能(41-基于树莓派4B的串口蓝牙模块AT09-cc2541)

1、串口蓝牙模块AT-09 AT-09是一种串口蓝牙模块,可实现串口与蓝牙之间的数据传输。AT-09模块基于蓝牙4.0技术,具有低功耗、高传输速率和广泛的应用范围。 AT-09模块支持AT指令,通过串口与外部设备进行通信。用户可以使用AT指令对模块进行配…...

C++ 动态规划

子序列子串相关 单个指一个数组或字符串,两个指两个数组或字符串。 最长上升子序列-单个 dp[i]:以下标i为结尾的递增的最长子序列长度。 位置i的最长升序子序列等于j从0到i-1各个位置的最长升序子序列 1 的最大值。 class Solution { public:int l…...

回溯问题总结

一、子集问题 模板问题 给定一个序列[1,n],求这个序列的所有子集 输入描述&#xff1a; 一个正整数n(1 < n < 12) 输出描述&#xff1a; 每个子集一行&#xff0c;输出所有子集。 输出顺序为&#xff1a; &#xff08;1&#xff09;元素个数少的子集优先输出&#xff1b;…...

GraphRAG如何使用ollama提供的llm model 和Embedding model服务构建本地知识库

使用GraphRAG踩坑无数 在GraphRAG的使用过程中将需要踩的坑都踩了一遍&#xff08;不得不吐槽下&#xff0c;官方代码有很多遗留问题&#xff0c;他们自己也承认工作重心在算法的优化而不是各种模型和框架的兼容性适配性上&#xff09;&#xff0c;经过了大量的查阅各种资料以…...

.net # 检查 带有pdf xss

1.解决pdf含javasprct脚本动作&#xff0c;这里是验证pdf内部事件。相关pdf文件下载&#xff1a; 测试pdf文件 相关包 iTextSharp 5.5.13.4 iTextSharp using iTextSharp.text.pdf; using iTextSharp.text.pdf.parser;private Boolean IsPdfSafe(Stream stream){// PdfReader…...

【React】探讨className的正确使用方式

文章目录 一、className的正确用法二、常见错误解析三、实例解析四、错误分析与解决五、注意事项六、总结 在React开发中&#xff0c;正确使用className属性对组件进行样式设置至关重要。然而&#xff0c;由于JavaScript和JSX的特殊性&#xff0c;开发者常常会犯一些小错误&…...

打靶记录5——靶机hard_socnet2

靶机&#xff1a; https://download.vulnhub.com/boredhackerblog/hard_socnet2.ova目标&#xff1a; 取得root权限 涉及攻击方法 主机发现端口扫描SQL注入文件上传蚁剑上线XMLRPC命令执行逆向工程动态调试漏洞利用代码编写 方法 CVE-2021-3493缓冲器溢出漏洞 学习目标 …...

独立站+TikTok达人:自主营销与创意内容的完美结合

在全球电商市场迅猛发展的今天&#xff0c;独立站和TikTok达人的结合正在创造一种全新的电商营销模式。独立站作为电商平台&#xff0c;其自主性和灵活性为商家提供了广阔的发展空间&#xff1b;而TikTok达人凭借其独特的内容创作能力和庞大的粉丝基础&#xff0c;成为推动销售…...

【启明智显分享】适用于多功能养生壶、茶吧机的2.8寸触摸彩屏解决方案

健康生活理念不断深入人心&#xff0c;多功能养生壶、茶吧机等智能产品成为现代家庭的热门小家电。为推动智能家居个性化、多样化发展&#xff0c;启明智显推出了基于SC05 Plus 2.8寸触摸彩屏的多功能养生壶、茶吧机的解决方案&#xff0c;旨在提升养生壶与茶吧机的用户体验与操…...

WAF绕过技术(PKAV团队)

目录 主流WAF的绕过技术 Web容器的特性 1. IIS+ASP的神奇% 2. IIS的Unicode编码字符 3. HPP(HTTP Parameter Pollution): HTTP参数污染 4. 畸形HTTP请求 Web应用层的问题 1. 多重编码问题 2. 多数据来源的问题 WAF自身的问题 1. 白名单机制 2. 数据获取方式存在缺陷…...

『 Linux 』POSIX 信号量与基于环形队列的生产者消费者模型

文章目录 信号量概念POSIX 信号量基于环形队列的生产者消费者模型基于环形队列的生产者消费者模型编码实现基于环形队列的生产者消费者模型发送任务测试 信号量概念 信号量是一种用于多线程或多进程间同步的机制; 其定义是一个整形变量,本质上信号量可以看成是一个计数器,用来描…...

python中的字符串方法

python中的字符串 举个例子先 name = 貂蝉开大 #声明了一个字符串 print(name) # 打印了一个字符串 print(name[0:1] #输出貂蝉 print(name[2:3] #输出开大 扩展方法 find() # 查找字符串中某个字符的索引 index_ = name.find("貂") print(index_) # 输出 …...

python实现consul的服务注册与注销

我在使用consul的时候主要用于prometheus的consul服务发现&#xff0c;把数据库、虚拟机信息发布到consul&#xff0c;prometheus通过consul拿到数据库、虚拟机信息去采集指标信息。 此篇文章前提是已经安装好consul服务以后&#xff0c;安装consul请参考二进制方式部署consul…...

校园选课助手【2】-重要的登录模块

用户登录模块技术要点&#xff1a; 密码通过MD5加密传输分布式session存储用户登录信息自定义注解进行字段校验自定义拦截器完成登录验证 下面依次给出代码和详细解释&#xff1a; 1.使用 MD5 二次加密用户登录信息&#xff0c;前端先通过密码加上盐进行MD5加密交给服务器&a…...

4章2节:从排序到分组和筛选,通过 R 的 dplyr 扩展包来操作

dplyr是R语言中一个强大且高效的数据处理包,专门设计用于处理数据框(data frames)。它的语法简洁明了,操作高效,尤其适用于大数据集。dplyr提供了一系列函数,使得数据的筛选、变换、聚合和排序等操作变得简单直观。本文将详细介绍dplyr扩展包如何进行数据的排序到分组和筛…...

C语言实现 -- 单链表

C语言实现 -- 单链表 1.顺序表经典算法1.1 移除元素1.2 合并两个有序数组 2.顺序表的问题及思考3.链表3.1 链表的概念及结构3.2 单链表的实现 4.链表的分类 讲链表之前&#xff0c;我们先看两个顺序表经典算法。 1.顺序表经典算法 1.1 移除元素 经典算法OJ题1&#xff1a;移除…...

WSL和Windows建立TCP通信协议

1.windows配置 首先是windows端&#xff0c;启动TCP服务端&#xff0c;用来监听指定的端口号&#xff0c;其中IP地址可以设置为任意&#xff0c;否则服务器可能无法正常打开。 addrSer.sin_addr.S_un.S_addr INADDR_ANY; recv函数用来接收客户端传输的数据&#xff0c;其中…...

Android Gradle开发与应用(一):Gradle基础

文章目录 引言一、Gradle简介二、Gradle基础语法1. 项目结构2. 插件应用3. 仓库与依赖4. 任务&#xff08;Tasks&#xff09; 三、Gradle在Android项目中的深入应用1. 构建变体&#xff08;Build Variants&#xff09;2. 依赖管理3. 自定义构建逻辑 四、Gradle WrapperGradle W…...

Linux多线程服务器编程-1-线程安全的对象生命期管理

对象的生与死不能由对象自身拥有的mutex&#xff08;互斥器&#xff09;来保护. 如何避免对象析构时可能存在的race condi​t​ion&#xff08;竞态条件&#xff09;是C多线程编程面临的基本问题。 对象的销毁可能出现多种竞态条件(race condi​t​ion)&#xff1a; 在即将析构…...

Couchbase 技术详解

文章目录 Couchbase 原理数据模型数据分布数据访问与同步官网链接 基础使用安装与配置数据操作 高级使用数据分片与负载均衡数据索引与查询安全性与权限管理 优点高性能可扩展性高可用性灵活性 总结 Couchbase 是一个高性能、分布式、可扩展的 NoSQL 数据库系统&#xff0c;基于…...