From 3131d095c2385738d728d34849d4750f92054652 Mon Sep 17 00:00:00 2001 From: Guide Date: Fri, 23 Feb 2024 16:44:05 +0800 Subject: [PATCH] =?UTF-8?q?[docs=20update]zookeeper=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E5=AE=8C=E5=96=84&=E9=83=A8=E5=88=86markdown=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/database/mongodb/mongodb-questions-01.md | 4 +-- .../zookeeper/zookeeper-intro.md | 32 +++++++++++++++++-- .../deep-pagination-optimization.md | 3 +- .../message-queue/disruptor-questions.md | 2 +- docs/java/jvm/jvm-garbage-collection.md | 2 +- pnpm-lock.yaml | 2 +- 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/docs/database/mongodb/mongodb-questions-01.md b/docs/database/mongodb/mongodb-questions-01.md index 0d862c27..860b1f2b 100644 --- a/docs/database/mongodb/mongodb-questions-01.md +++ b/docs/database/mongodb/mongodb-questions-01.md @@ -274,7 +274,7 @@ MongoDB 单文档原生支持原子性,也具备事务的特性。当谈论 Mo WiredTiger 日志也会被压缩,默认使用的也是 Snappy 压缩算法。如果日志记录小于或等于 128 字节,WiredTiger 不会压缩该记录。 -## Amazon Document与MongoDB 的差异 +## Amazon Document 与 MongoDB 的差异 Amazon DocumentDB(与 MongoDB 兼容) 是一种快速、可靠、完全托管的数据库服务。Amazon DocumentDB 可在云中轻松设置、操作和扩展与 MongoDB 兼容的数据库。 @@ -331,8 +331,6 @@ WriteResult({ }) ``` - - ## 参考 - MongoDB 官方文档(主要参考资料,以官方文档为准): diff --git a/docs/distributed-system/distributed-process-coordination/zookeeper/zookeeper-intro.md b/docs/distributed-system/distributed-process-coordination/zookeeper/zookeeper-intro.md index da7e0bff..293a2ae1 100644 --- a/docs/distributed-system/distributed-process-coordination/zookeeper/zookeeper-intro.md +++ b/docs/distributed-system/distributed-process-coordination/zookeeper/zookeeper-intro.md @@ -57,7 +57,9 @@ ZooKeeper 将数据保存在内存中,性能是不错的。 在“读”多于 - **原子性:** 所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,也就是说,要么整个集群中所有的机器都成功应用了某一个事务,要么都没有应用。 - **单一系统映像:** 无论客户端连到哪一个 ZooKeeper 服务器上,其看到的服务端数据模型都是一致的。 - **可靠性:** 一旦一次更改请求被应用,更改的结果就会被持久化,直到被下一次更改覆盖。 -- **实时性:** 每个客户端的系统视图都是最新的。 +- **实时性:** 一旦数据发生变更,其他节点会实时感知到。每个客户端的系统视图都是最新的。 +- **集群部署**:3~5 台(最好奇数台)机器就可以组成一个集群,每台机器都在内存保存了 ZooKeeper 的全部数据,机器之间互相通信同步数据,客户端连接任何一台机器都可以。 +- **高可用:**如果某台机器宕机,会保证数据不丢失。集群中挂掉不超过一半的机器,都能保证集群可用。比如 3 台机器可以挂 1 台,5 台机器可以挂 2 台。 ### ZooKeeper 应用场景 @@ -253,7 +255,7 @@ Paxos 算法应该可以说是 ZooKeeper 的灵魂了。但是,ZooKeeper 并 ### ZAB 协议介绍 -ZAB(ZooKeeper Atomic Broadcast 原子广播) 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。 在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。 +ZAB(ZooKeeper Atomic Broadcast,原子广播) 协议是为分布式协调服务 ZooKeeper 专门设计的一种支持崩溃恢复的原子广播协议。 在 ZooKeeper 中,主要依赖 ZAB 协议来实现分布式数据一致性,基于该协议,ZooKeeper 实现了一种主备模式的系统架构来保持集群中各个副本之间的数据一致性。 ### ZAB 协议两种基本的模式:崩溃恢复和消息广播 @@ -262,12 +264,38 @@ ZAB 协议包括两种基本的模式,分别是 - **崩溃恢复**:当整个服务框架在启动过程中,或是当 Leader 服务器出现网络中断、崩溃退出与重启等异常情况时,ZAB 协议就会进入恢复模式并选举产生新的 Leader 服务器。当选举产生了新的 Leader 服务器,同时集群中已经有过半的机器与该 Leader 服务器完成了状态同步之后,ZAB 协议就会退出恢复模式。其中,**所谓的状态同步是指数据同步,用来保证集群中存在过半的机器能够和 Leader 服务器的数据状态保持一致**。 - **消息广播**:**当集群中已经有过半的 Follower 服务器完成了和 Leader 服务器的状态同步,那么整个服务框架就可以进入消息广播模式了。** 当一台同样遵守 ZAB 协议的服务器启动后加入到集群中时,如果此时集群中已经存在一个 Leader 服务器在负责进行消息广播,那么新加入的服务器就会自觉地进入数据恢复模式:找到 Leader 所在的服务器,并与其进行数据同步,然后一起参与到消息广播流程中去。 +### ZAB 协议&Paxos 算法文章推荐 + 关于 **ZAB 协议&Paxos 算法** 需要讲和理解的东西太多了,具体可以看下面这几篇文章: - [Paxos 算法详解](https://javaguide.cn/distributed-system/protocol/paxos-algorithm.html) - [ZooKeeper 与 Zab 协议 · Analyze](https://wingsxdu.com/posts/database/zookeeper/) - [Raft 算法详解](https://javaguide.cn/distributed-system/protocol/raft-algorithm.html) +## ZooKeeper VS Etcd + +[Etcd](https://etcd.io/) 是一种强一致性的分布式键值存储,它提供了一种可靠的方式来存储需要由分布式系统或机器集群访问的数据。Etcd 内部采用 [Raft 算法](https://javaguide.cn/distributed-system/protocol/raft-algorithm.html)作为一致性算法,基于 Go 语言实现。 + +与 ZooKeeper 类似,Etcd 也可用于数据发布/订阅、负载均衡、命名服务、分布式协调/通知、分布式锁等场景。那二者如何选择呢? + +得物技术的[浅析如何基于 ZooKeeper 实现高可用架构](https://mp.weixin.qq.com/s/pBI3rjv5NdS1124Z7HQ-JA)这篇文章给出了如下的对比表格,可以作为参考: + +| | ZooKeeper | Etcd | +| -------------- | --------------------------------------------------------------------- | ------------------------------------------------------ | +| **语言** | Java | Go | +| **协议** | TCP | Grpc | +| **接口调用** | 必须要使用自己的 client 进行调用 | 可通过 HTTP 传输,即可通过 CURL 等命令实现调用 | +| **一致性算法** | Zab 协议 | Raft 算法 | +| **Watch 功能** | 较局限,一次性触发器 | 一次 Watch 可以监听所有的事件 | +| **数据模型** | 基于目录的层次模式 | 参考了 zk 的数据模型,是个扁平的 kv 模型 | +| **存储** | kv 存储,使用的是 ConcurrentHashMap,内存存储,一般不建议存储较多数据 | kv 存储,使用 bbolt 存储引擎,可以处理几个 GB 的数据。 | +| **支持 MVCC** | 不支持 | 支持,通过两个 B+ Tree 进行版本控制 | +| **权限校验** | 实现的 ACL | 实现了 RBAC | +| **事务能力** | 提供了简易的事务能力 | 只提供了版本号的检查能力 | +| 部署维护 | 复杂 | 简单 | + +实际选用哪个要根据实际业务场景和需求来定,Etcd 相对来说更适合云原生领域,并且提供了更稳定的高负载稳定读写能力以及更高的可用性。 + ## 总结 1. ZooKeeper 本身就是一个分布式程序(只要半数以上节点存活,ZooKeeper 就能正常服务)。 diff --git a/docs/high-performance/deep-pagination-optimization.md b/docs/high-performance/deep-pagination-optimization.md index b495c6d7..8a419dad 100644 --- a/docs/high-performance/deep-pagination-optimization.md +++ b/docs/high-performance/deep-pagination-optimization.md @@ -62,8 +62,7 @@ SELECT * FROM t_order WHERE id >= (SELECT id FROM t_order limit 1000000, 1) LIMI ```sql SELECT t1.* FROM t_order t1 INNER JOIN (SELECT id FROM t_order limit 1000000, 10) t2 -ON t1.id = t2.id -LIMIT 10; +ON t1.id = t2.id; ``` 除了使用 INNER JOIN 之外,还可以使用逗号连接子查询。 diff --git a/docs/high-performance/message-queue/disruptor-questions.md b/docs/high-performance/message-queue/disruptor-questions.md index 01d70d56..1881f6c2 100644 --- a/docs/high-performance/message-queue/disruptor-questions.md +++ b/docs/high-performance/message-queue/disruptor-questions.md @@ -115,7 +115,7 @@ Disruptor 真的很快,关于它为什么这么快这个问题,会在后文 ## Disruptor 为什么这么快? - **RingBuffer(环形数组)** : Disruptor 内部的 RingBuffer 是通过数组实现的。由于这个数组中的所有元素在初始化时一次性全部创建,因此这些元素的内存地址一般来说是连续的。这样做的好处是,当生产者不断往 RingBuffer 中插入新的事件对象时,这些事件对象的内存地址就能够保持连续,从而利用 CPU 缓存的局部性原理,将相邻的事件对象一起加载到缓存中,提高程序的性能。这类似于 MySQL 的预读机制,将连续的几个页预读到内存里。除此之外,RingBuffer 基于数组还支持批量操作(一次处理多个元素)、还可以避免频繁的内存分配和垃圾回收(RingBuffer 是一个固定大小的数组,当向数组中添加新元素时,如果数组已满,则新元素将覆盖掉最旧的元素)。 -- **避免了伪共享问题**:CPU 缓存内部是按照 Cache Line(缓存行)管理的,一般的 Cache Line 大小在 64 字节左右。Disruptor 为了确保目标字段独占一个 Cache Line,会在目标字段前后增加字节填充(前 56 个字节和后 56 个字节),这样可以避免 Cache Line 的伪共享(False Sharing)问题。同时,为了让 RingBuffer 存放数据的数组独占缓存行,数组的设计为 无效填充(128字节)+ 有效数据。 +- **避免了伪共享问题**:CPU 缓存内部是按照 Cache Line(缓存行)管理的,一般的 Cache Line 大小在 64 字节左右。Disruptor 为了确保目标字段独占一个 Cache Line,会在目标字段前后增加字节填充(前 56 个字节和后 56 个字节),这样可以避免 Cache Line 的伪共享(False Sharing)问题。同时,为了让 RingBuffer 存放数据的数组独占缓存行,数组的设计为 无效填充(128 字节)+ 有效数据。 - **无锁设计**:Disruptor 采用无锁设计,避免了传统锁机制带来的竞争和延迟。Disruptor 的无锁实现起来比较复杂,主要是基于 CAS、内存屏障(Memory Barrier)、RingBuffer 等技术实现的。 综上所述,Disruptor 之所以能够如此快,是基于一系列优化策略的综合作用,既充分利用了现代 CPU 缓存结构的特点,又避免了常见的并发问题和性能瓶颈。 diff --git a/docs/java/jvm/jvm-garbage-collection.md b/docs/java/jvm/jvm-garbage-collection.md index eacddcce..61e14515 100644 --- a/docs/java/jvm/jvm-garbage-collection.md +++ b/docs/java/jvm/jvm-garbage-collection.md @@ -504,7 +504,7 @@ ZGC 在 Java11 中引入,处于试验阶段。经过多个版本的迭代, java -XX:+UseZGC className ``` -在 Java21 中,引入了分代 ZGC,暂停时间可以缩短到1毫秒以内。 +在 Java21 中,引入了分代 ZGC,暂停时间可以缩短到 1 毫秒以内。 你可以通过下面的参数启用分代 ZGC: diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ae950d4f..09e028d1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,4 +1,4 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' settings: autoInstallPeers: true