写在前面
本文是分布式系列收官篇,讲数据复制(多副本如何同步)和 Gossip 协议(最终一致的传播机制),顺带讲分布式 ID 和限流。这些是 Cassandra、Redis Cluster、Consul、比特币网络背后的技术。
一、为什么要复制
1
2
3
4
5
6
7
8
9
10
11
12
| 数据复制 = 在多个节点存副本
目的:
✓ 高可用(一个挂了,其他还能服务)
✓ 读扩展(多副本分担读压力)
✓ 就近访问(副本部署在不同地域,降低延迟)
✓ 容灾(异地备份)
代价:
✗ 一致性问题(副本间可能不一致)
✗ 写入开销(要同步到多个副本)
✗ 冲突(多副本同时改)
|
二、三种复制架构
2.1 主从复制(Single-Leader)
1
2
3
4
5
6
7
8
9
10
11
12
| 一个主(Leader)负责写,多个从(Follower)复制
客户端 → Leader(写)→ 复制 → Follower1, Follower2
客户端 ← Follower(读)
特点:
✓ 写入无冲突(只有 Leader 写)
✓ 简单
✗ Leader 是写瓶颈和单点
✗ 主从延迟(异步复制时从节点数据滞后)
代表:MySQL 主从、Redis 主从、PostgreSQL 流复制、Kafka 分区
|
2.2 多主复制(Multi-Leader)
1
2
3
4
5
6
7
8
9
10
11
12
13
| 多个 Leader 都能写,互相复制
Leader1 ←→ Leader2
↓ ↓
副本 副本
特点:
✓ 写可用性高(一个 Leader 挂了,另一个还能写)
✓ 适合多数据中心
✗ 写冲突(两个 Leader 同时改同一数据)
✗ 冲突解决复杂
代表:CouchDB、多数据中心部署的 MySQL(双主)
|
2.3 无主复制(Leaderless)
1
2
3
4
5
6
7
8
9
| 没有 Leader,客户端写多个节点,读多个节点比对
客户端 → 写 N 个节点(W 个成功即算成功)
客户端 ← 读 N 个节点(R 个返回一致即最新)
W + R > N 保证强一致(Quorum)
典型:W=R=多数
代表:Cassandra、DynamoDB、Riak(Dynamo 风格)
|
三、同步 vs 异步复制
1
2
3
4
5
6
7
8
9
10
11
12
13
| 同步复制:
Leader 写后,等所有 Follower 确认才返回客户端
✓ 强一致 ✗ 慢、一个 Follower 慢全拖慢
异步复制:
Leader 写后立即返回,Follower 异步追赶
✓ 快 ✗ 数据可能滞后、Leader 挂了可能丢未同步数据
半同步复制:
至少一个 Follower 同步确认,其他异步
折中(MySQL 半同步复制)
Redis 主从、MySQL 默认都是异步(性能优先)
|
四、复制日志格式
1
2
3
4
5
6
7
8
| 基于语句:复制 SQL 语句(now()、rand() 等有问题)
基于行(Row):复制数据行的变更(最常用,准确)
混合模式:语句 + 行
逻辑日志:复制逻辑变更(跨数据库兼容)
MySQL binlog 支持 STATEMENT/ROW/MIXED
Kafka 用消息本身做日志
Redis 用命令/字节流
|
五、冲突解决
多主/无主复制下,并发写同一数据会产生冲突:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| 1. 最后写入获胜(LWW)
用时间戳,新的覆盖旧的
✗ 时钟漂移导致丢数据
✗ 简单但会丢更新(适合可容忍的场景)
2. 向量时钟(Vector Clock)
记录每个写操作的逻辑时钟
能检测并发冲突,交给应用解决
✓ 不依赖物理时钟 ✗ 复杂
3. 应用层解决
冲突版本都返回,应用合并(如购物车合并)
代表:Riak、CouchDB
4. CRDT(Conflict-free Replicated Data Type)
无冲突复制数据类型,自动可合并
✓ 自动解决冲突 ✗ 数据类型受限(计数器、集合等)
代表:Redis(部分)、Automerge、Yjs(协同编辑)
|
六、Gossip 协议(流言协议)
最终一致系统的数据传播机制,像病毒扩散/流言传播。
1
2
3
4
5
6
7
8
| Gossip 核心思路:
每个节点周期性随机挑几个节点,交换状态信息
经过多轮,信息扩散到全网
一轮 Gossip:
Node A 随机选 B → 交换彼此知道的所有节点状态
B 又选 C 交换 → ...
O(log N) 轮后,全网收敛
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| Gossip 的特点:
✓ 极高可扩展性(节点数再多也 O(log N) 收敛)
✓ 容错(节点挂了不影响传播)
✓ 去中心化(无主节点)
✓ 最终一致
✗ 不是强一致(有传播延迟)
✗ 可能传播过时信息(靠版本号解决)
代表:
Cassandra — 节点状态、集群拓扑用 Gossip
Consul — 成员管理、故障检测用 Gossip
Redis Cluster — 节点发现用 Gossip
比特币 — 区块/交易传播
HashiCorp Serf — Gossip 库
|
Gossip 与故障检测
1
2
3
4
5
6
| Gossip 还用于故障检测(Phi Accrual Failure Detector):
节点间互相发心跳(Gossip 带心跳)
一段时间收不到某节点心跳 → 标记 suspect → 确认 down
多个节点独立判断,避免单点误判
比单纯超时更鲁棒(自适应、分布式)
|
七、分布式 ID
分布式系统需要全局唯一 ID:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| 方案:
1. UUID
✓ 无中心、全局唯一 ✗ 长(128位)、无序、索引差
2. 雪花算法(Snowflake)
64位 = 时间戳(41) + 机器ID(10) + 序列号(12)
✓ 趋势递增、高性能、无中心
✗ 依赖时钟(时钟回拨问题)
3. 数据库自增(分段)
各节点分配不同 ID 段
✓ 简单 ✗ 依赖 DB
4. Redis INCR
✓ 简单、递增 ✗ 依赖 Redis、单点
5. 号段模式(Leaf、Tinyid)
预分配 ID 段,本地消费,用完再取
✓ 高性能 ✗ 实现稍复杂
通用推荐:雪花算法 / 号段模式
|
八、分布式限流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| 单机限流(内存)管不到多机,需要分布式限流:
1. Redis + Lua(集中式)
所有请求到 Redis 计数,Lua 保证原子
✓ 准确 ✗ Redis 单点/性能瓶颈
2. 令牌桶(Redis 实现)
按速率生成令牌,请求消耗令牌
3. 本地限流 + 中心同步
各节点本地限流(配额的 1/N),定期同步
✓ 性能好 ✗ 不精确
.NET 8 内置限流 + Redis 可做分布式
|
九、小结
- 复制架构:主从(单Leader)、多主(多Leader)、无主(Leaderless + Quorum)
- 复制方式:同步(强一致慢)、异步(快有延迟)、半同步(折中)
- 冲突解决:LWW(简单丢数据)、向量时钟、应用层、CRDT(自动)
- Gossip:流言式传播,O(log N) 收敛,最终一致,高可扩展
- 分布式 ID:雪花算法(趋势递增无中心)、号段模式
- 分布式限流:Redis + Lua 集中式、本地+中心同步
系列总结
分布式系统五篇完结:
- CAP 与一致性:CP vs AP,BASE,一致性模型
- Raft 共识:Leader 选举 + 日志复制 + Quorum,现代 CP 系统标配
- 分布式锁:Redis(AP 快)/ ZK·etcd(CP 可靠)
- 分布式事务:2PC/TCC/Saga/本地消息表,优先最终一致
- 复制与 Gossip:主从/多主/无主,Gossip 最终一致传播
核心心法:分布式系统的本质是"在不可靠的网络和节点上,构建可靠的协同"。CAP、共识、复制、一致性,都是在回答"如何取舍"的问题。没有完美方案,只有适合场景的方案。