云镇有一个社区图书馆网络:总馆里存着一本全城唯一的“母本”藏书,为了防火、防震、防小偷,它把母本复印了三套,分别放在东城、西城、南城三个分馆。从此,麻烦来了——总馆改一个错别字、加一条新书目,分馆的读者什么时候才能看到最新版本?有的分馆要求总馆打电话实时确认(准确但慢,每次登记都要等最远的分馆回话);有的分馆觉得没必要,每天晚上统一送一批更新即可(快但读者会看到旧目录)。“多久能看到最新信息、看到的信息是否可信”,就是分布式系统的一致性问题。从“实时同步”到“明天再说”,这中间有一条从强到弱的谱系:最严格的一端是线性一致性,最松散的一端是最终一致性。本文用云镇图书馆的七种馆规,把这张一致性地图讲清楚,并告诉你在什么业务场景下该选哪条路。
一致性模型是分布式系统设计的“宪法”:它决定你的系统正确性上限、延迟下限和可用性边界。无论做数据库内核、中间件还是业务架构,读懂它都是绕不开的必修课。
目录
可视化演示
展示一致性模型谱系(线性→顺序→因果→最终)、CAP定理CP/AP权衡、Google Spanner TrueTime+Multi-Paxos外部一致性实现。
本节配有交互动效(进入视口后自动加载,约 3KB)。
'+captions.spectrum+'
一致性基石:副本从哪来
云镇总馆决定复制母本,原因很朴素:一场大火就能烧掉全部藏书。复制三套到三个分馆,防火能力一下子提升三倍。可代价立刻浮现——总馆改错别字时,得让三套复印件保持一致,否则读者在东城看到《三体》在架,到西城却被告知“已借出”。副本(Replica) 就是同一份数据在多个物理位置存的拷贝,它是分布式系统冗余的根本手段,也是一致性问题的根源。
副本有了,下一个问题是读写流程。云镇的规矩是“写总馆、读分馆”:所有借阅登记只能到总馆办,办完总馆再把更新“通知”到分馆。这在数据库里叫单主复制(Single-Leader Replication)。通知方式也有讲究:总馆可以等所有分馆回电话确认后才告诉读者“办好了”,这叫全量同步;也可以只等多数分馆确认,叫过半确认;还有更偷懒的——通知发出去就不管了,叫异步复制。同步范围越广,读者越不容易看到旧目录,但每次登记的等待时间就越长。
副本书越多,图书馆防灾能力越强,但每次登记的 $T_{\text{prop}}$ 也越难压小。副本是图书馆的安全垫,也是分布式系统所有“不一致烦恼”的起点——后面所有馆规,都是在回答怎么对付这个 $T_{\text{prop}}$。
- $T_{\text{read}}$ 读可见时刻读者在某个分馆翻到“这本书已被借走”标记的最早时刻。
- $T_{\text{write}}$ 写提交时刻总馆在母本目录上完成登记、并告诉读者“登记好了”的时刻。
- $T_{\text{prop}}$ 传播开销总馆把变更送往分馆在路上花费的时间,例如从发通知到分馆挂出公告的间隔。
线性一致性:实时电话方案
总馆曾经试过一种最严格的馆规:每次登记完毕,必须立刻打电话通知三个分馆,分馆必须在电话里复述确认,读者在任何一个分馆看到的目录都跟总馆一模一样。这套方案下,整个图书馆网络表现得像只有一个总馆在运转——你根本感觉不到副本的存在。这就是 线性一致性(Linearizability),别名强一致或原子一致性。
线性一致性的要求非常苛刻:它要求系统存在一个与真实时间对齐的全局顺序。任意两次操作,只要真实世界里先发生,那么在全局顺序里它也必须排在前面,所有读者看到的先后顺序必须一致。换句话说,“先发生”就是“先生效”,没有任何回旋余地。实现它通常需要共识算法(如 Raft 或 Paxos),或者全量同步复制——写请求要等所有副本或至少一个 quorum 确认后才算成功。
实时电话方案的正确性无可挑剔,代价是总馆每次登记都要等最远的分馆回话——写延迟被“最慢的副本”绑架。在分布式世界里,这就是线性一致性的宿命:它用延迟换来了“假装只有一个副本”的完美假象,适合元数据、分布式锁、账户余额这类绝不容错的关键数据。
- $t(o_1) < t(o_2)$ 真实时间先后用墙钟或原子钟记录的两次操作完成时刻,先完成的就是先发生。
- $o_1 \prec o_2$ 全局可见顺序在系统对外表现出的唯一顺序里,$o_1$ 排在 $o_2$ 前面,任何读者都只能看到这个顺序。
- $\implies$ 推导关系只要真实时间上先发生,就强制要求全局顺序也如此,不允许“先发生却后生效”。
顺序一致性:编号信件方案
电话方案太费人力,总馆改用了「邮政公告」:每次登记不再是实时电话,而是把变更编上信件序号,按顺序寄往分馆。分馆收到几封信就公布几封,有的分馆邮差跑得快、一口气收到三封,有的还只收到一封——但信件的编号顺序绝不会乱。读者可能看到旧公告,但只要看到的公告序列,编号一定是递增的。这就是 顺序一致性(Sequential Consistency)。
顺序一致性的核心是“进程内有序”:同一个客户端(读者)自己发起的操作,在所有副本上呈现的顺序必须与它发起时一致;但不同客户端的并发操作,谁先谁后,系统可以自由编排,不需要与真实时间对齐。换句话说,它放弃了“绝对实时”,保留了“相对有序”。它比线性一致性更容易实现,因为不需要全局时钟,只要给每个进程的操作按序编号即可。
编号信件方案比电话便宜得多,总馆发完信就不用等回执。读者偶尔看到旧公告,但绝不会看到“先借续集后借第一部”这种逻辑颠倒。顺序一致性适合那些“顺序不错乱即可”的场景——比如日志流水、操作审计导出的快照。
- $\forall p$ 任意进程泛指系统中的任何一个客户端或应用程序进程。
- $\operatorname{order}_p$ 进程自己的顺序进程 $p$ 发出操作的先后次序,这是程序逻辑约定的。
- $\operatorname{order}_S(p)$ 全局序列中的顺序把 $p$ 的操作摆进全局序列 $S$ 之后,它们保持的先后关系。
- $=$ 两者相等要求这两个顺序一致——进程内的先后不允许在全局里被颠倒。
因果与读己之写:两条人性化规定
云镇的馆规继续演化,新增两条人性化规定。第一条:读者借《射雕》第三册之前,必须先能看到馆藏里有第二册。如果两条登记之间存在“依赖关系”(第二册的入库依赖第一册已有),那么所有分馆公布这两条信息的顺序必须一致——这叫因果一致性(Causal Consistency)。第二条:读者小明上午在总馆还了一本书,下午到南城分馆想再借同一本,南城分馆必须先知道“小明已还书”,否则会闹出“你自己还的书自己都借不到”的笑话,这叫读己之写(Read-your-writes)。
因果一致性只对“有因果关系”的操作强约束顺序,对并发无依赖的操作网开一面;读己之写则把“自己写自己读”绑定为最小承诺,是会话一致性(Session Consistency) 的一部分——同一个会话内,读必须看到之前的写。工程实现上常用版本向量(Version Vector)或客户端携带“上次看到的水位”来达成。
因果一致性比顺序一致性更宽松,比最终一致性更严谨——它不管并发操作谁先谁后,只管“有因才有果”。读己之写则是所有社交产品、内容平台的隐形地基:发帖者永远第一个看到自己的帖子。这两条馆规合在一起,构成了大多数“轻强一致”应用的默认选择。
- $W_A \to W_B$ 因果依赖写 $B$ 的业务逻辑依赖写 $A$ 的存在,比如“先建文件夹再存文件”。
- $W_A \prec_{vis} W_B$ 可见顺序一致任何副本展示给用户的顺序里,$A$ 必须在 $B$ 之前,不能出现“文件在了文件夹还没建”。
- $W_i \to R_i$ 同一客户端的写先于读例如你刚发布一条动态,紧接着刷新个人主页。
- $R_i \text{ sees } W_i$ 读包含写你的这次读取结果必须包含你刚才写入的数据——自己写的东西对自己可见是底线。
CAP权衡:洪水断桥的抉择
云镇遇上百年一遇的洪水,总馆到东城分馆的桥被冲断(网络分区)。这时东城读者来问:“最新目录里有这本书吗?”东城管理员只有两个选择:如实说“我这边跟总馆失联,无法确认,不能借”,这保住了“任何分馆对外说法必须一致”的规矩;或者“凭我手头这份旧目录先借给你,等桥修好了再补登记”,这保住了“读者任何时候都能借到书”。两条路必选其一,没有第三条。
这就是 CAP 定理 的核心:$P$(网络分区)是分布式系统的物理现实,不是可以勾掉的设计选项——P 是前提,分区发生后,$C$(强一致性)和 $A$(可用性)只能二选一。选择 $C$ 的系统(如 etcd、ZooKeeper)在分区时拒绝写入,宁可暂停服务也要保证读到的都是权威数据;选择 $A$ 的系统(如 Cassandra、Dynamo)在分区时继续服务,接受返回旧数据、等恢复后慢慢补对账。此外还有 Quorum 折中:让读副本数 $R$ 与写副本数 $W$ 满足 $R + W > N$,读写集合必相交,可以在不强求全量同步的情况下降低延迟。
洪水期间,东城分馆选择“先借出去,回头再补账”就是 AP 派;总馆选择“查不到就是没有”就是 CP 派。CAP 没有善恶,只有业务取舍:银行转账怕错不怕慢,选 CP;抢购秒杀怕等不怕旧,选 AP。
- $P$ 网络分区发生集群被切断成多个孤岛,彼此无法通信——这不是“可能不会发生”,而是“迟早会发生”。
- $C$ 一致性(此处指线性一致)每个请求都能拿到最新数据,所有副本对外口径完全统一。
- $A$ 可用性每个请求都能得到非错误的响应,即使数据可能是旧的。
- $\neg(C \land A)$ 不可兼得在分区这个条件下,C 和 A 的“且”关系被否定,只能保留其中一个。
延迟与可用性:馆规的成本账本
东城分馆在桥修好后复盘发现:馆规越严格,读者等待时间越长;馆规越宽松,借书成功率越高。于是它按书品类定了阶梯馆规——新出版的畅销书执行实时电话确认(线性一致),普通小说半小时同步一次(读己之写),十年以上的旧书每天晚上批量同步(最终一致)。这个阶梯背后,是一条清晰的成本光谱。
从线性到最终,一致性强度递减,写延迟通常从“等待全部副本确认”降到“本地写完即返回”,可用性则从“分区时直接拒绝”升到“分区时继续服务”。这个交换关系可以形式化:可用性等于 1 减去“需要跨分区协调的操作比例”,跨分区协调越频繁,可用性越低,延迟越高。而最终一致性模型的独特魅力在于,在没有新写入的静默期,副本状态最终会收敛到一致:
没有免费的馆规:越严格,读者等待越久、分区时越容易吃闭门羹;越宽松,借书越快但越容易借到过期信息。现代系统的一个重要实践是混合模型——同一套数据库里,热数据走强一致,冷数据走弱一致,把这条光谱变成按行或按表配置的“可调一致性”。
- $A$ 可用性读者走进任意分馆能成功完成借书/还书的概率,拒绝服务就扣可用性。
- $P(\text{需要跨分区协调})$ 协调概率一次操作需要联系多个分区才能确认的比例,协调越多,失败率越高。
- $\lim_{t \to \infty}$ 无穷时间极限时间足够长,且期间没有新的干扰写入。
- $V_i(t) = V_j(t)$ 副本状态相同分馆 $i$ 和分馆 $j$ 的目录在时刻 $t$ 完全一致。
主流数据库选型:各家馆规一览
云镇图书馆的七种馆规,最终沉淀为每家分馆门前的门牌。这些门牌,就是现实中主流数据库的一致性选择。读懂门牌,才能给业务配上合适的馆。
总馆挂的牌子写着“实时电话方案”——etcd 与 ZooKeeper 采用共识算法(Raft/Paxos)提供线性一致性,是分布式锁、Leader 选举、配置中心的标准选择,宁可分区时停止服务,也绝不让两个节点同时当主。东城分馆挂的牌子是“主馆登记、分馆异步公布”——PostgreSQL 主从复制 默认异步,从库可能滞后,想要读己之写就得把“自己刚写的数据”的读请求路由到主库,或开启同步提交。南城分馆挂的是“周末大同步”——Cassandra 默认最终一致,但提供可调一致性级别:把读写级别都调到 QUORUM 就能获得较强一致,调到 ALL 则接近线性一致。而新建的云山分馆用“卫星对时 + 过半确认”——TiDB 与 Spanner 通过 Raft/Paxos 多副本 + 精确时钟(Spanner 用 TrueTime),实现了跨数据中心的分布式线性一致。
各家馆规没有对错,只有“适不适合自己的读者”。给元数据选 Cassandra 默认级别会出乱子,给排行榜选 etcd 的线性一致则纯属杀鸡用牛刀。选型的关键,是看清业务到底怕“旧”还是怕“等”。
- $\text{Cost}(m)$ 模型总代价采用某种一致性模型给业务带来的综合成本,数值越小越好。
- $L_m$ 延迟该模型下平均读写耗时,线性一致模型往往会数值较大。
- $\alpha$ 延迟敏感权重业务对等待时间的敏感度,如在线支付很在意秒级延迟。
- $A_m$ 可用性该模型下请求成功的概率;$1 - A_m$ 就是失败概率,$\beta$ 是业务对失败的容忍权重。
AI 应用场景
电商扣库存:读写强一致保护钱包
阶段:在线交易系统的数据一致性保障
解决的问题:用户下单时库存数据分存在主库和多个从库,异步复制使从库读到旧库存,导致超卖、负数库存、资金对不上账。传统方案是全部读写都压主库,性能又扛不住大促。
具体案例:双十一大促中,商品服务先通过 Redis 做本地预扣(最终一致),成功后跳转订单页必须从主库读取确认结果(读己之写),库存扣减流水则写入采用多副本强一致的表,保证对账时绝不出现“扣了两次”或“扣了看不见”。支付回调后用户刷新页面,永远能看到自己的支付结果——哪怕延迟 50ms 也不能漏。
社交 Feed 流:因果与读己之写的协同
阶段:内容分发管道与缓存同步
解决的问题:用户发帖后自己刷新看不到(违反读己之写),或者好友的评论比原帖还早出现(违反因果一致性),严重伤害体验。若全部强一致,热门大 V 的千万粉丝 Feed 生成会拖垮系统。
具体案例:某社交平台发帖流程分两路:写路径先把帖子写入作者自己的主页缓存(立即对自己可见,满足读己之写),再异步 Fanout 到粉丝的 Feed 队列,用版本向量保证“先有帖子后有评论”的因果顺序,粉丝端最终一致即可。微博热搜榜则完全用最终一致,允许各节点有几十秒偏差。
分布式锁与 Leader 选举:节点间的唯一权威
阶段:分布式协调与容灾选主
解决的问题:多个服务实例同时抢占“谁是主节点”,如果锁不够强,网络抖动时两个实例同时认为自己持有锁,造成双主写冲突,直接引发数据错乱。
具体案例:Kubernetes 控制平面用 etcd 选主,候选节点通过写入同一个 key 抢锁,etcd 的线性一致性保证“只有一个节点成功”。AI 训练平台的容灾调度也类似:两个 Worker 同时提交同一任务的检查点,必须只有一个被接受,否则模型参数被互相覆盖。
Python 演示
import random class Replica: """单个副本:保存数据字典和版本号""" def __init__(self, name): self.name = name self.data = {} self.version = 0 class Cluster: """模拟多副本数据库集群,支持三种同步模式""" def __init__(self, mode, replica_count=5): self.replicas = [Replica("r%d" % i) for i in range(replica_count)] self.leader = self.replicas[0] self.mode = mode self.write_count = 0 self.quorum = replica_count // 2 + 1 def write(self, key, value): self.write_count += 1 self.leader.data[key] = value self.leader.version = self.write_count if self.mode == "sync": for rep in self.replicas[1:]: rep.data[key] = value rep.version = self.write_count elif self.mode == "quorum": for rep in self.replicas[1:self.quorum]: rep.data[key] = value rep.version = self.write_count def propagate(self): """异步模式下,把 leader 最新数据随机传给一个落后副本""" laggards = [r for r in self.replicas[1:] if r.version < self.leader.version] if laggards: rep = random.choice(laggards) rep.data = dict(self.leader.data) rep.version = self.leader.version def read(self, replica_index, key): rep = self.replicas[replica_index] return rep.data.get(key), rep.version def simulate(mode, rounds=2000): cluster = Cluster(mode) stale = 0 for i in range(rounds): cluster.write("k", i) if mode == "async" and random.random() < 0.3: cluster.propagate() _, version = cluster.read(random.randrange(len(cluster.replicas)), "k") if version < cluster.write_count: stale += 1 return 1.0 * stale / rounds if __name__ == "__main__": for mode in ("sync", "quorum", "async"): print("%-8s 读到旧值比例: %.2f%%" % (mode, simulate(mode) * 100))
self.replicas = [Replica("r%d" % i) for i in range(replica_count)]创建 5 个副本节点,replica 0 充当主副本(leader)cluster.write("k", i)每轮模拟一次写请求,主副本版本号递增并写入新值if self.mode == "sync":全同步模式:写请求必须立刻复制到所有副本,读者永远不会读到旧值elif self.mode == "quorum":过半模式:只复制到前 3 个副本(5 个副本的多数派),未覆盖的副本存在旧数据if version < cluster.write_count:读者拿到的版本落后于主副本最新版本,即视为一次“不一致读”random.random() < 0.3异步模式每秒只随机补一次传播,模拟网络传播速度跟不上写入速度的现实
常见误区
误区“CAP 就是说一致性、可用性、分区容忍三者只能选两个,我看它们都能正常运行,所以我要选 CA,把 P 丢掉。”很多入门同学把 CAP 当成一个菜单,天真地以为可以先选两个、第三个以后再说。
正解P(网络分区容忍)不是可选项,而是分布式系统的物理前提——机器会宕、网络会断,分区必然发生。CAP 定理真正说的是:在发生分区这段时间里,C 和 A 二选一;没有分区时,C 和 A 可以同时满足。所以不存在“丢掉 P”的 CA 系统,只能选择“分区时保 C 还是保 A”。
为何常见:CAP 画成三角形让许多人误以为是三个顶点任选两个,忽略了“P 是环境而不是属性”这一关键事实。
误区“最终一致性嘛,等个几分钟所有副本肯定就同步了,数据不会丢,只是慢一点而已。”初学者常把“最终一致”理解成“系统会自动修复所有不一致”。
正解最终一致性只在没有新写入的静默期才会收敛。如果系统持续高速写入,传播速度永远赶不上写入速度,副本可能长期处于不一致状态。而且传播机制(如反熵、读修复)设计不当,甚至可能永不收敛。它保证的是“停止写入后趋于一致”,不是“边写边自动一致”。
为何常见:“最终”这个字眼给了人很强的安全感,让人误以为它会主动追平,实则它只是描述了收敛方向,没有承诺收敛时间。
误区“既然用了强一致的数据库,那任何时刻任何客户端读到的都是最新数据,不可能读到旧值。”这是对线性一致性最经典的误解。
正解线性一致性要求的是:每个读操作在它发生的时间点上,存在一个与真实时间一致的全局顺序。如果读操作与写操作是并发的(读发生在写提交之前)——比如客户端在副本收到新数据前已经发出了读请求——读到旧值是合法的。更常见的是客户端本地缓存:缓存了旧值没失效,读的是本地缓存,这不算数据库违背线性一致。
为何常见:把“强一致”想象成“全知全能”,忽略了并发操作的时间窗口和客户端侧缓存的存在。
误区“顺序一致性要求所有操作按同一个时间戳排序,那就是线性一致性啊,两个名字有什么区别?”许多同学把“顺序”直接理解成“全局时间顺序”。
正解顺序一致性只要求每个进程自己发起的操作在全局序列中保持原序,不同进程之间的并发操作可以任意排序,不要求与墙钟(真实时间)对齐。线性一致性 = 顺序一致性 + 与真实时间对齐。所以线性比顺序更严格,实现成本也更高。
为何常见:名字里的“顺序”让人联想到全局时钟,实际上它说的是“进程内的相对顺序”而非“真实时间顺序”。
误区“我的 MySQL 主从架构做主从同步,从库延迟一两百毫秒,这不就是强一致吗?”很多后端同学因此把主从复制与强一致画等号。
正解异步复制下,主库写入成功但从库尚未收到更新时,读从库会读到旧值,系统无法保证“读发生在写完成之后就能看到新值”,这直接违反线性一致性定义。这是典型的最终一致性。要让主从系统达到读己之写,必须把“自己刚写的数据”的读路由到主库,或用同步复制/半同步复制增强。
为何常见:“主从同步”四个字里带的“同步”二字,让人误以为它是同步延迟、同步确认的语义,其实它只是描述了复制拓扑。
面试题
Q1. 线性一致性最直观的含义是什么?
- A.所有副本数据最终都相同
- B.系统表现得像只有一份数据在运转← 正确答案
- C.每个进程操作按自己的顺序执行
- D.并发写入时以时间戳大小排序
答案:B。线性一致性的核心是“对外表现得像只有一个副本”,存在与真实时间对齐的全局顺序。A 是最终一致性;C 只是顺序一致性的一部分;D 描述的是顺序一致性而非线性一致性,因为线性还要求与墙钟对齐。
Q2. CAP 定理中字母 P 指的是什么?
- A.系统要达到的高性能指标
- B.数据写入后的持久性保证
- C.网络分区在分布式系统中必然会发生← 正确答案
- D.主从复制的数据同步协议
答案:C。P 是 Partition tolerance(分区容忍),指网络分区是分布式系统迟早会发生的环境事实,而不是一种可取舍的能力。它提醒工程师:设计时就要考虑分区发生时的行为,而不是假设网络永远可靠。
Q3. 网络分区发生时,选择 CP 的系统会怎么做?
- A.继续对外服务并返回本地旧数据
- B.拒绝读写请求直到分区恢复为止← 正确答案
- C.把写请求重定向给其他分区的副本
- D.自动降低一致性级别来保持服务
答案:B。CP 系统的哲学是“宁可不可用,不可给错答案”。分区发生后,它无法确认数据是否最新,于是拒绝读写。A 是 AP 的行为;C 在分区后网络不可达,无法转发;D 属于混合策略,不是 CP 的典型选项。
Q4. 读己之写(Read-your-writes)保护的最典型场景是?
- A.大数据平台的日志离线分析
- B.用户提交后刷新页面看到结果← 正确答案
- C.后台任务批量更新产品库存
- D.推荐系统的离线特征计算
答案:B。读己之写要求“自己的写,自己的读必须看得见”,最典型的就是用户提交表单/发帖后立刻刷新,必须看到刚提交的内容。A、D 是离线后台场景,用户不直接感知;C 的库存更新通常由系统批量执行,不涉及单用户会话。
Q5. 系统持续高速写入时,最终一致性会怎样?
- A.副本仍然会不断趋向一致收敛
- B.副本必然出现永久不可调和的分叉
- C.副本可能长期处于不一致状态← 正确答案
- D.系统会自动停止写入等待同步
答案:C。最终一致性只在静默期收敛——没有新写入、传播机制有时间追平旧账。持续高速写入时,新变更不断覆盖旧变更,传播永远追不上,副本可能长期不一致。A 过于理想;B 的“必然”太绝对;D 不是最终一致系统的行为。
Q6. 下列一致性模型中,哪些比线性一致性弱?
- A.顺序一致性← 正确答案
- B.因果一致性← 正确答案
- C.最终一致性← 正确答案
- D.强一致性
答案:ABC。一致性强度谱系大致为:线性一致性 > 顺序一致性 > 因果一致性 > 最终一致性。D 的强一致性通常就是线性一致性的别名或等价说法,不比线性弱。A、B、C 都放宽了某些约束,因此比线性一致性弱。
Q7. 顺序一致性与线性一致性的关键区别是什么?
- A.顺序一致性不需要保证与真实时间对齐← 正确答案
- B.顺序一致性不允许出现并发写操作
- C.线性一致性不考虑进程内部的操作顺序
- D.线性一致性允许操作顺序在时间上颠倒
答案:A。核心区别在于线性一致性要求全局顺序与真实时间(墙钟)对齐——先发生的操作必须先被看到;顺序一致性只要求每个进程自己的操作在全局序列里保持原序,并发操作可以随意摆放,不必对表。B、C、D 都是错误描述。
Q8. 关于 Quorum 机制(读 W 个、写 R 个副本)的说法正确的有?
- A.R + W > N 时读写集合必有交集← 正确答案
- B.Quorum 可以在不强求全量同步下降延迟← 正确答案
- C.Quorum 机制必然提供线性一致性
- D.Quorum 永远比全量同步有更高的可用性
答案:AB。当读副本数和写副本数之和大于总副本数 N 时,读写集合必有交叠,这是多数派读写的数学基础,也让它避免全量同步、降低延迟。但它本身不保证线性一致——还需要版本号、时钟或共识协议配合;D 过于绝对,quorum 的可用性提升有边界,且协调多节点仍有额外开销。
Q9. 下列哪种业务场景最需要线性一致性?
- A.排行榜的分数实时计算
- B.分布式锁与 Leader 选举← 正确答案
- C.社交 Feed 流的动态推荐
- D.监控指标的聚合展示
答案:B。分布式锁和 Leader 选举要求“同一时刻只能有一个成功者”,对操作顺序有严格的一致性要求,否则会出现双主、双写。排行榜、Feed、监控指标都可以容忍短暂不一致,用最终一致性或因果一致性即可。
Q10. 想让 Cassandra 在默认最终一致的基础上增强一致性,可行手段有?
- A.设置读一致性级别为 ALL← 正确答案
- B.设置写一致性级别为 QUORUM← 正确答案
- C.让所有读写都强制访问某一个副本
- D.使用轻量级事务 LWT 做条件更新← 正确答案
答案:ABD。Cassandra 支持可调一致性:读 ALL 表示等所有副本响应,写 QUORUM 表示多数派确认后再返回,都能显著增强一致性;LWT 基于 Paxos 提供线性化的条件写。C 不是官方推荐方式——强制单副本会破坏可用性和容灾能力,且分布式集群无法保证“某一副本”始终可访问。