分布式与一致性协议之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 三个参数直接控制一致性、可用性、延迟三角平衡

评论已关闭

推荐阅读

AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日
python之plot()和subplot()画图
2024年11月26日
理解 DALL·E 2、Stable Diffusion 和 Midjourney 工作原理
2024年12月01日