分布式与一致性协议之Quorum NWR算法
一、什么是 Quorum NWR 算法
在分布式存储系统中,同一份数据通常会保存多个副本:
- N(Number of Replicas):副本总数
- W(Write Quorum):写成功所需确认副本数
- R(Read Quorum):读成功所需返回副本数
Quorum 的核心目标是在:
- 一致性(Consistency)
- 可用性(Availability)
- 延迟(Latency)
之间取得平衡。
其核心公式:
R + W > N满足该条件时,任意一次读操作与最近一次成功写操作一定至少命中一个共同副本。(systemoverflow.com)
二、NWR 的数学本质
假设:
N = 3
W = 2
R = 2那么:
R + W = 4 > 3说明:
- 写入至少进入 2 个副本
- 读取至少读取 2 个副本
- 任意两组大小分别为 2 的集合,在 3 个节点内必然相交
这就是 Quorum Intersection(法定人数交集)。
三、Python 从零实现 Quorum 存储模型
下面我们直接用 Python 构建一个最小可运行的 Quorum KV。
from dataclasses import dataclass, field
from typing import Dict, List, Tuple
import time
import random
@dataclass
class Replica:
node_id: int
store: Dict[str, Tuple[int, str]] = field(default_factory=dict)
def write(self, key: str, version: int, value: str):
self.store[key] = (version, value)
return True
def read(self, key: str):
return self.store.get(key, (0, None))
class QuorumKV:
def __init__(self, n: int, w: int, r: int):
self.n = n
self.w = w
self.r = r
self.version = 0
self.replicas = [Replica(i) for i in range(n)]
def put(self, key: str, value: str):
self.version += 1
ack = 0
selected = random.sample(self.replicas, self.n)
for replica in selected:
replica.write(key, self.version, value)
ack += 1
if ack >= self.w:
return True
return False
def get(self, key: str):
selected = random.sample(self.replicas, self.r)
versions = [replica.read(key) for replica in selected]
return max(versions, key=lambda x: x[0])四、验证 R+W>N 的强一致读取
cluster = QuorumKV(n=3, w=2, r=2)
cluster.put("name", "alice")
print(cluster.get("name"))
cluster.put("name", "bob")
print(cluster.get("name"))输出:
(1, 'alice')
(2, 'bob')说明读取到了最新版本。
五、为什么 Python 仿真最适合理解 Quorum
我们继续用 Monte Carlo 做随机一致性实验。
def simulate(n, w, r, rounds=10000):
success = 0
for _ in range(rounds):
write_set = set(random.sample(range(n), w))
read_set = set(random.sample(range(n), r))
if write_set & read_set:
success += 1
return success / rounds
print(simulate(3, 2, 2))
print(simulate(5, 3, 3))
print(simulate(5, 2, 2))预期:
1.0
1.0
0.7x当 R+W<=N 时,交集概率下降,不再保证强一致。
六、深入分析:不同参数组合的系统特性
1)高可用读优化
N=3, W=2, R=1特点:
- 读非常快
- 写保证多数派
- 可能读旧数据
典型系统:Dynamo 风格系统。(arxiv.org)
2)强一致推荐组合
N=3, W=2, R=2特点:
- 工程上最常见
- 可容忍 1 节点故障
- 读写都具备较强一致性
3)写优先系统
N=5, W=4, R=2适合:
- 金融账本
- 订单系统
- 元数据管理
七、Python 模拟节点故障场景
class FaultyReplica(Replica):
def __init__(self, node_id, fail_rate=0.2):
super().__init__(node_id)
self.fail_rate = fail_rate
def write(self, key, version, value):
if random.random() < self.fail_rate:
return False
return super().write(key, version, value)扩展故障集群:
class FaultyQuorumKV(QuorumKV):
def __init__(self, n, w, r, fail_rate=0.2):
self.n = n
self.w = w
self.r = r
self.version = 0
self.replicas = [FaultyReplica(i, fail_rate) for i in range(n)]
def put(self, key, value):
self.version += 1
ack = 0
for replica in self.replicas:
if replica.write(key, self.version, value):
ack += 1
return ack >= self.w测试:
cluster = FaultyQuorumKV(5, 3, 3, fail_rate=0.3)
ok = sum(cluster.put("k", str(i)) for i in range(1000))
print(ok / 1000)这可以直接用于分析:
- 节点故障率
- quorum 成功率
- SLA 可用性
八、Quorum 与 Paxos / Raft 的区别
很多人容易混淆:
Quorum
- 副本读写策略
- 偏向存储层
- 解决副本一致性
Paxos / Raft
- 分布式共识
- 偏向日志复制
- 保证全局顺序一致
多数派提交本质也是一种特殊 Quorum。(geeksforgeeks.org)
九、生产级 Python:加入 Version + Read Repair
def read_repair(cluster: QuorumKV, key: str):
selected = random.sample(cluster.replicas, cluster.r)
versions = [r.read(key) for r in selected]
latest = max(versions, key=lambda x: x[0])
for replica in selected:
version, _ = replica.read(key)
if version < latest[0]:
replica.write(key, latest[0], latest[1])
return latest这就是 Cassandra / Dynamo 常见的:
- Read Repair
- Hinted Handoff
- Anti Entropy
思想基础。
十、面试级总结(高频)
核心公式
R + W > N常见推荐
N=3, W=2, R=2核心收益
- 高可用
- 可容错
- 延迟可控
- 一致性可调
核心代价
- 存在脑裂窗口
- 非线性一致性
- 时钟/version依赖
- repair 成本
十一、Python 性能压测脚本(进阶)
import time
cluster = QuorumKV(5, 3, 3)
start = time.time()
for i in range(100000):
cluster.put("counter", str(i))
cluster.get("counter")
print("QPS:", 100000 / (time.time() - start))十二、结语
Quorum NWR 的价值不在于“背公式”,而在于:
用 N/W/R 三个参数直接控制一致性、可用性、延迟三角平衡。
评论已关闭