设想你们几个朋友合用一个共享网盘文件夹来写《AI 产品方案》。你在地铁上改了标题,同事在咖啡馆也改了标题,两个人各自保存到本地,谁也没通知谁。等你们连上网络,云盘开始同步,两台电脑上出现过两套不同的标题,过了十几秒,又神奇地变成同一个。这就是分布式系统里的“最终一致性”:各写各的没问题,系统稍后会自动对齐。但如果两个人改的是同一句话呢?这就叫“冲突”,需要一套“解决冲突”的规矩:谁赢?还是拼在一起?还是找仲裁人?这篇文章就用这个网盘文件夹的故事,带你走一遍最终一致性的前世今生:它从哪来、会撞出哪些冲突、系统怎么自动化解,以及什么时候该用它、什么时候坚决别用。

岗位关联

对 AI 从业者而言,理解最终一致是设计分布式训练、特征存储、多智能体协作系统的基本功。面试中它常与 CAP 一起出现,是判断你能否胜任大规模系统的分水岭。

目录
  1. 可视化演示
  2. 基本概念:先认识“最终一致”
  3. 产生原因:为什么副本会分道扬镳
  4. 冲突类型:三条最容易撞车的岔路
  5. 解决策略:四种化解矛盾的办法
  6. 核心算法:让系统自己会仲裁
  7. 工程实践:大厂工具是怎么做的
  8. 权衡取舍:什么时候选最终一致
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

演示副本最终收敛、写冲突解决与CRDT合并机制,理解BASE模型下多副本最终一致的收敛路径与冲突处理策略。

本节配有交互动效(进入视口后自动加载,约 3KB)。

副本收敛:最终一致 多副本同步 收敛到一致 R→V 随时间最终一致

基本概念:先认识“最终一致”

新网盘刚上线那会儿,文文发现一个怪现象:她在手机端改完方案标题,阿辉在电脑端要过十几秒才看到。老周微微一笑:“别慌,这是最终一致性,BASE 里的 E,最终会一致。”文文很不解:我明明保存成功了,为什么别人不能立刻看到?老周打了个比方:这就好比你们把同一份文件下载到了各自的电脑、手机、平板上,你改你的,他改他的,云盘在背后慢慢把改动广播给所有设备。广播完成前,大家看到的不一样;广播完成后,只要没人再改,大家迟早看到同一个版本。

在专业术语里,这个“广播”叫异步复制。一个写请求先被某个副本接受,立刻给用户返回成功,再在后台把改动传播给其他副本。这个设计有两个好处:写入不用等所有副本确认,响应快;某个副本暂时不可用也不影响写入。代价就是,在一段时间窗口内,不同副本上读到的值可能不同。这种“允许短时间不一致,但保证没有新写入时最终收敛到同一个值”的模型,就是最终一致性,它是 BASE 理论中 E(Eventually consistent)的含义。

按一致性从强到弱,可以排成一条光谱:强一致 > 顺序一致 > 因果一致 > 最终一致。强一致像银行转账,钱一扣,所有柜台立刻看到新余额;最终一致像朋友圈点赞数,过一会儿才全部同步。日常系统里,90% 的数据根本不需要强一致。社交动态的点赞数、电商购物车合并、用户昵称、缓存刷新,都属于“晚几分钟看到也完全能接受”的数据。老周补了一句:“记住,一致性强弱不是道德问题,是成本问题。越强的一致性,背后要付出的协调代价越高。”

产生原因:为什么副本会分道扬镳

文文还是不放心:“为什么非要让副本各写各的?大家老老实实走同一个数据库不行吗?”老周画了一张图:网盘把文件同步到手机、平板、电脑多个设备,每个设备都是一个副本。如果全天下只能用一个设备,那当然不会不一致;但那样的话,这台设备一坏,所有人都没法工作。分布式系统为了扛住海量用户和机房故障,必须把数据复制到多个地方。多副本复制是第一层原因——有副本,就有副本之间变得不同的可能。

第二层原因是网络分区。地铁隧道里手机没信号,飞机上开飞行模式,咖啡馆 Wi-Fi 断断续续——这就是活生生的网络分区。CAP 定理告诉我们:网络分区(P)是常态,永远可能发生;一旦发生分区,你只能在“保证所有副本数据一致(C)”和“保证任何副本都能继续读写(A)”之间选一个。为了保证网盘 7×24 小时可用,大家几乎都选 A + P,暂时放弃 C,也就是放弃强一致。这就像合租的冰箱:你没法保证每次放酸奶都通知所有人,那就约定“谁看到就谁拿,最后总数对得上就行”。

第三层原因是并发写入和延迟传播。文文和阿辉同时改标题,两个请求几乎同时到达不同副本。副本之间同步消息还有网络排队、重传,于是“我改的版本”和“你改的版本”在云端相遇时,因为传播顺序不同,可能你覆盖我,我覆盖你,形成各种意想不到的结果。老周总结道:多副本是土壤,网络分区是导火索,并发写入是火药,延迟传播是让火药延时的引信。四者叠加,最终一致系统里几乎必然出现冲突。

冲突类型:三条最容易撞车的岔路

既然冲突必然发生,就得先知道它长什么样。老周把冲突分成三类,像三个容易出事故的十字路口。

第一类是写写冲突:两个人同时改同一个键,各自生成了新版本。比如文文把标题改成《AI 方案 v2》,阿辉在同一秒把标题改成《AI 产品白皮书》,两个版本都声称自己是“最新”。云盘一同步,发现同一个键上有两个互相不服的版本。这就像两个人都往同一把椅子上贴了“我的”标签,谁该坐?

第二类是删除更新冲突:一个人删除了某个键,另一个人却还在旧值上做修改。文文觉得“背景介绍”整段写得不好,直接删掉;阿辉没刷新,还在“背景介绍”里加了一段最新数据。同步时,阿辉的修改基于一个已经被删掉的旧版本,到底该把删除撤销、保留阿辉的新段,还是坚持删除、丢掉阿辉的修改?

第三类是乱序到达:同步消息走的网络路径不同,晚发出的修改可能先到,早发出的修改可能后到。就像两个快递员,小张先出发但路上堵车,小李后出发却一路顺畅,先到了。云端如果机械地按到达顺序覆盖,“先到”的版本可能把其实更新的内容冲掉。第三种冲突最隐蔽,因为它不靠人眼检查根本发现不了——光靠到达时间判断谁新,在分布式系统里是不可靠的。

解决策略:四种化解矛盾的办法

面对这些冲突,老周说:“解决冲突本质上只有四种思路,就像处理两个人意见不合:听时间、看历史、自动拼、找人裁。”

第一种是 LWW(Last-Write-Wins,最后写入者胜):每个写操作附一个时间戳,谁的写入时间戳大,谁的版本胜出。简单高效,DynamoDB、Cassandra 等系统默认用它。但它的隐患也明显:依赖各节点本地时钟,如果手机和服务器的时间没对齐,可能误杀真正的新版本。它的判定可写成公式:

第二种是版本向量:不靠墙上的时钟,而是给每个节点发一个“编辑次数计数器”。判断两个版本时,看谁的计数包含谁的历史,就能判断出谁先谁后、还是并发。如果互相都不包含,说明是并发修改,那就需要下一种方法。

第三种是 CRDT(无冲突复制数据类型):设计一种神奇的合并运算,让任何两个版本按任意顺序合并,结果都一样。就像 Git 自动合并两处不同文件的修改,或者计数器合并时直接把数值相加、集合合并时直接取并集。CRDT 的合并运算满足交换律、结合律、幂等律,天然免疫乱序和重复。

第四种是应用层裁决:把冲突的几个版本都交给业务代码,让产品语义来定。购物车冲突就把两个商品都加进去;Git 合并不了就弹出一个冲突标记,让开发者人工逐行选择。老周说:“自动裁决是理想,人工仲裁是底线。越重要的数据,越值得花人工。”

winner=arg⁡max⁡v∈{v1,v2} tv\displaystyle \text{winner} = \mathop{\arg\max}_{v \in \{v_1, v_2\}} \ t_v
意思是:从冲突的两个版本里,挑出写入时间戳更大的那个作为最终结果。代价是另一个版本被直接丢弃。
  1. 候选版本集合$v \in \{v_1, v_2\}$ 表示冲突的两个版本都在候选池里,系统只能在两者中选一或合一。
  2. 版本时间戳$t_v$ 是版本 $v$ 携带的写入时间戳,来自节点本地时钟,是能直接比较大小的标量。
  3. 最大者胜出$\arg\max$ 返回使 $t_v$ 最大的那个 $v$,也就是“时间戳更大的版本胜出”。

核心算法:让系统自己会仲裁

自动仲裁不是魔法,背后是一套精巧的算法。老周把网盘同步的底层逻辑拆开,讲了三件核心武器:向量时钟、Gossip 传播、Quorum 机制。

先说向量时钟。它是版本向量的进阶版:每个节点维护一个长度为 N 的数组,数组第 i 位记录“我所知道的节点 i 的写入次数”。本地每写一次,自己那位加 1;收到其他节点的状态时,逐位取最大值。当两个版本相遇,比较它们的向量:如果所有位都小于等于对方、且至少有一位严格小,说明一个发生在另一个之前;如果各有大小,说明两者并发。这套机制可表示为:

接着说 Gossip 传播。它像办公室八卦:每个节点不必广播给所有人,只需要定期随机挑几个邻居,把最新的版本信息“咬耳朵”传过去。被传到的节点再传给别人,信息以指数速度扩散,用不了多久,所有副本就都知道了最新消息。Gossip 的优点是去中心化、不怕单点故障、对网络抖动容忍度高;缺点是传播有延迟,而且短时间内可能重复传播——所以刚才说 CRDT 要满足幂等律,就是为这种重复传播兜底。

最后是 Quorum 机制。它用“多数派”来保证读写的可靠交汇:写操作要写 W 个副本,读操作要读 R 个副本,只要满足 R + W > N(N 是副本总数),读到的副本集合与写到的副本集合必有交集,因此至少能读到一个最新写入的版本。老周强调:Quorum 保证的是“读得够新”,并不保证“没有写写冲突”——Quorum 解决的是看不见旧数据,向量时钟解决的是判不清谁新,两者互补,经常搭配使用。

Ci[i]←Ci[i]+1(本地写入时)Cj[k]←max⁡(Cj[k], Ci[k])(收到消息时)Va≺Vb  ⟺  Va≠Vb 且 ∀k: Va[k]≤Vb[k]\displaystyle\begin{aligned}C_i[i] &\gets C_i[i] + 1 &&\text{(本地写入时)} \\C_j[k] &\gets \max(C_j[k],\ C_i[k]) &&\text{(收到消息时)} \\V_a \prec V_b &\iff V_a \ne V_b \ \text{且}\ \forall k:\ V_a[k] \le V_b[k]\end{aligned}
向量时钟就是“每个节点都记一本账,谁改过多少次一目了然”。它不需要全局时钟,就能严谨地判断因果与并发。
  1. 本地计数$C_i[i] \gets C_i[i] + 1$ 表示节点 $i$ 产生一次本地写入事件时,把自己的计数器加 1,记录“我又多写了一次”。
  2. 消息合并$C_j[k] \gets \max(C_j[k],\ C_i[k])$ 表示节点 $j$ 收到节点 $i$ 的状态时,每个分量取两者较大值,意思是“你经历过的所有事情,我现在也都知道了”。
  3. 因果判定$V_a \prec V_b$ 表示向量 $V_a$ 严格发生在 $V_b$ 之前:所有分量都不超过对方,且至少有一个分量严格更小。若既不满足 $V_a \prec V_b$ 也不满足 $V_b \prec V_a$,则两个版本并发,需要进入冲突处理流程。

工程实践:大厂工具是怎么做的

讲完理论,老周带大家看了一圈身边的工具,发现最终一致性无处不在。

DynamoDB:亚马逊的招牌 NoSQL,默认用 LWW 解决冲突,同时提供“条件更新”和自定义冲突解决插件。如果你觉得时间戳不可靠,可以把自己写的合并逻辑挂上去,让 DynamoDB 在冲突时回调你的代码。Cassandra 也类似,ROW 级别存储多个冲突版本,由读时协调(read repair)机制慢慢收敛。

Git 是分布式系统里最像“人肉最终一致”的工具。每个人本地都是一个完整仓库(副本),提交(写入)先发生在本地,push 时再传播到远端。两个人同时改了同一文件的同一行,Git 合并时发现冲突,就把两个版本都留下来,标上 >>>>>>> 和 <<<<<<<,由开发者人工裁决。这正好对应我们说的“应用层裁决”——Git 很聪明地知道什么时候该自动合、什么时候必须请人。

协同编辑产品(腾讯文档、Figma、飞书)则大量使用 CRDT。多人同时拖拽同一个图形组件、同时编辑同一段文字,CRDT 能让角色自然地合并,不弹冲突框。Google Docs 早期用的是 OT(操作转换),本质目标相同:让并发编辑最终收敛且不丢失任何人的修改。老周说:“自动合并做得好,用户根本感觉不到冲突存在,这是最终一致性的最高境界。”

AI 工程领域同样如此。分布式训练的参数服务器允许各 worker 异步拉取/推送梯度,模型参数短暂不一致没关系,只要最终收敛;特征存储在多个区域做异步复制,某个区域刚写入的特征在其他区域晚几秒可见,对模型在线推理影响很小;多智能体系统里多个 agent 共享会话状态,同步冲突时也要靠版本号或合并策略保持一致。

权衡取舍:什么时候选最终一致

文文问出了最关键的问题:“那到底什么时候该用最终一致?”老周说,判断标准可以浓缩成一句话:这个数据丢了/protected了,后果有多严重?

先看一致性延迟。最终一致系统的收敛时间从几十毫秒到几分钟不等,取决于传播频率、网络状况、冲突多少。做架构时要问:业务能不能容忍这段时间内读到旧值?如果可以,最终一致就够用;如果不行(比如要立刻看到刚下的订单状态),就要考虑更强的一致性。

再看性能成本。强一致需要锁、事务协调器、多阶段提交,节点越多越慢,数据不可用的风险也越高。最终一致几乎总是更快、更便宜、更可用,但需要为冲突解决预留计算和存储资源。这是一场交易:用一点点“旧数据”的代价,换更高的吞吐量和可用性。

选型时可以用“冰箱食物”打比方:酸奶、零食是最终一致,晚一会儿同步无所谓,过期扔了甚至更好;婚戒、房产证必须强一致,必须当面交接、签收,任何延迟都不可接受。具体到工程:社交点赞数、浏览计数、用户昵称、收藏夹、购物车合并、推荐缓存,全部适合最终一致;银行余额、库存扣减、订单支付、权限白名单、分布式锁,必须强一致。老周最后总结:“先想清楚数据的'婚戒指数',再决定要不要追最终一致。 绝大多数场景,'晚一点看见'远比'看不见'好得多。”

---

AI 应用场景

跨区域特征存储的异步同步

阶段:特征平台 / 数据链路

解决的问题:传统方案要求特征库在多个 Region 之间同步,一旦网络抖动就拒绝写入,导致在线推理链路不可用。改用最终一致后,每个 Region 的本地副本先行写入,后台通过消息队列异步复制到其他 Region,短暂的特征延迟不影响整体推荐效果。

具体案例:某内容平台的用户实时行为特征(点击、停留时长)写入上海 Region,而北京 Region 的模型服务需要读取该特征做个性化推荐。允许 1-2 秒的收敛延迟,配合 LWW 策略解决同一用户特征的并发更新,最终两边特征库收敛一致。

分布式模型训练的异步参数同步

阶段:模型训练 / 分布式训练

解决的问题:同步训练需要所有 worker 完成梯度交换才能进入下一步,遇到慢节点就整体拖慢。异步参数服务器采用最终一致:每个 worker 从参数服务器拉取稍旧的参数,算完梯度推回去,参数被更新后其他 worker 晚一点才看到。

具体案例:某大模型训练任务使用 32 个 GPU worker,参数服务器端采用“版本号 + 新版本胜出”的规则,容忍参数短暂不一致。最终小幅增加训练步数,但整体吞吐量提升约 40%。

多智能体协作的会话状态合并

阶段:LLM 应用 / Agent 编排

解决的问题:多个 AI Agent 并行处理同一用户任务时,各自维护的会话上下文副本可能不同。借助版本向量判断并发冲突,把不同分支的对话摘要合并成统一上下文,避免用户看到互相矛盾的回答。

具体案例:某客服机器人同时调用“订单查询 Agent”和“退款政策 Agent”,两个 Agent 各自更新会话状态。系统用版本号追踪状态,合并时采用“先到先得、冲突走应用层策略”,保证最终会话上下文一致。

Python 演示

python53 行
import time  class LWWNode:    """基于 LWW 的键值副本,演示最终一致性与冲突解决"""     def __init__(self, name):        self.name = name        self.data = {}  # key -> (value, timestamp)     def put(self, key, value, ts=None):        ts = ts if ts is not None else time.time()        self.data[key] = (value, ts)        print(f"[{self.name}] put {key} = {value} @ {ts:.1f}")     def sync(self, other):        """把对方的数据合并到本节点,时间戳新者胜出"""        for key, (value, ts) in other.data.items():            if key not in self.data or ts > self.data[key][1]:                self.data[key] = (value, ts)                print(f"[{self.name}] 接受 {key} = {value}(LWW)")            elif ts < self.data[key][1]:                print(f"[{self.name}] 保留 {key} 的本地新值")            else:                print(f"[{self.name}] {key} 时间戳相同 -> 冲突,交给应用层处理")  def main():    a = LWWNode("节点A")    b = LWWNode("节点B")     # 网络分区期间,两副本各自并发写入    a.put("title", "文文的标题A", 10.0)    b.put("title", "阿辉的标题B", 20.0)     # 分区恢复,互相同步    print("--- 同步开始 ---")    a.sync(b)    b.sync(a)     # 再演示一个时间戳完全相同的冲突    a.put("greeting", "你好", 30.0)    b.put("greeting", "Hello", 30.0)    print("--- 同步开始(时间戳相同) ---")    a.sync(b)     print("--- 最终收敛结果 ---")    print("A:", a.data)    print("B:", b.data)  if __name__ == "__main__":    main()
目的:用两个带本地时钟的节点模拟网络分区后的并发写入,并演示 LWW 策略如何让最终一致性收敛;当时间戳完全相同时,系统会主动识别冲突并交给应用层处理。
  1. self.data = {}每个副本用自己的字典保存所有键值,键是数据名称,值是“值 + 时间戳”的元组。
  2. ts = ts if ts is not None else time.time()不传时间戳时取本地时钟,模拟各节点独立计时。
  3. if key not in self.data or ts > self.data[key][1]:LWW 核心判断:以前没见过这个键,或者对方时间戳更新,就接受对方。
  4. elif ts < self.data[key][1]:对方版本更旧,保留本地值,不覆盖。
  5. else:时间戳恰好相同,无法用 LWW 判定,于是显式报出冲突,留给应用层裁决。
  6. for key, (value, ts) in other.data.items():遍历对方全部键,对每个键独立做合并,这是最终一致系统典型的逐键同步方式。

常见误区

误区很多人以为最终一致就是“数据随便不一致,系统根本不管”。反正迟早会一致,现在不一致也无所谓。

正解最终一致性承诺的是“在没有新写入的前提下,经过足够长时间,所有副本一定会收敛到同一个值”。它不是放任自流,而是把“立即一致”放宽为“最终一致”。就像快递承诺“三天内必达”,不是说包裹会丢,只是不保证当天到。

为何常见:把“最终”理解成了“未知”或“不管”,忽略了分布式系统对收敛性的底层保证机制。

误区LWW 简单好用,时间戳大的覆盖小的,那只要保证时间戳,冲突就能完美解决,永远正确。

正解LWW 依赖各节点本地时钟,而时钟在分布式系统里经常不同步。两个设备时间偏差几秒,就可能让真正的新写入被旧写入覆盖,造成数据丢失。这也是为什么有些系统改用逻辑时钟(Lamport 时钟 / 向量时钟)替代物理时间戳。

为何常见:单机世界里时间就是全局唯一的,人都习惯“新盖旧”的自然直觉,很难立刻意识到分布式世界里没有全局时钟。

误区认为只要在同步的最后阶段把冲突版本都列出来,人工看一看就能解决,不需要提前设计冲突检测机制。

正解要做到“冲突时能列出所有版本”,系统必须提前记录版本之间的因果关系(如向量时钟)。如果没做版本追踪,两个版本混在一起,连“谁基于谁”都说不清,人工也无法裁决。冲突解决的准备工作必须前置,发生在写入之前,而不是冲突之后。

为何常见:人们习惯用“事后补救”思维处理问题,但分布式系统的信息一旦丢失就再也找不回,必须靠机制保证可见性。

误区既然允许短暂不一致,那所有并发写都不用管了,随便写,反正最终会一致。

正解最终一致只放宽了“读到的时效性”,并没有消除写写冲突。两个并发写同一键时,系统仍然需要 LWW、版本向量或 CRDT 来决定合并结果。完全没有并发控制的分布式存储会丢失大量更新,收敛到哪个值都不可预期。

为何常见:把“读的宽松”误解成“写的随便”,混淆了一致性模型和并发控制两个维度。

误区只要 R + W > N,读写的多数派有交集,系统就不会出现冲突了。

正解Quorum 保证的是“读操作至少能碰到一个最新写入的副本”,避免读到过期值;它并不阻止两个客户端并发写同一个键。写写冲突依然存在,仍然需要版本向量 + 合并策略来处理。

为何常见:把“读取新鲜度”和“写入冲突消除”混为一谈,忽略了两者是完全不同层次的问题。

面试题

Q1. 在 BASE 理论中,最终一致性对应哪个字母?

单选题 · easy

  • A.B 里的 Basically Available
  • B.S 里的 Soft State
  • C.E 里的 Eventually← 正确答案
  • D.A 里的 Available

答案:C。BASE 由 Basically Available、Soft State、Eventually consistent 三部分组成,最终一致性对应 E(Eventually)。B 和 A 描述的是可用性与软状态,不是一致性本身。

Q2. 网络分区出现时,为了保持可用,系统通常会放弃哪种保证?

单选题 · easy

  • A.分区容忍性 P
  • B.强一致性 C← 正确答案
  • C.基础可用性 A
  • D.数据持久性 D

答案:B。CAP 定理中 P 是必须面对的现实,无法放弃;通常的取舍是在 C 和 A 之间选择。为了保证继续可用(A),系统选择暂时放弃强一致(C),改用最终一致。

Q3. 两个人同时修改同一键并各自生成了新版本,这属于哪类冲突?

单选题 · mid

  • A.写写冲突← 正确答案
  • B.读写冲突
  • C.乱序到达
  • D.删除更新冲突

答案:A。两个副本同时写同一个键、各自产生新版本,是最典型的写写冲突。乱序到达属于传播顺序问题,删除更新冲突涉及删除与修改的对抗,都不符合题意。

Q4. LWW 策略核心依据是哪个要素?

单选题 · mid

  • A.写入节点的权重
  • B.写入操作的时间戳← 正确答案
  • C.数据内容的哈希值
  • D.写入请求的字节数

答案:B。LWW(Last-Write-Wins)比拼的是写入时间戳,时间戳更大的版本胜出。它不关心节点权重、内容哈希或请求大小。关键局限是依赖本地时钟,时钟偏移会导致误判。

Q5. 向量时钟中,两个向量互为并发时,比较关系是怎样的?

单选题 · mid

  • A.两者向量完全相等
  • B.一方严格大于另一方
  • C.一方某分量大于对方
  • D.互不包含且各有大小← 正确答案

答案:D。并发意味着两个向量既不满足 $V_a \prec V_b$,也不满足 $V_b \prec V_a$。它们互不包含:某个分量 a 大、另一个分量 b 大。完全相等是同一版本,一方严格大于则说明有先后关系。

Q6. 关于 Quorum 机制,R + W > N 的直接作用是什么?

单选题 · hard

  • A.消除所有写写冲突
  • B.保证读到最新已提交值← 正确答案
  • C.提升写入的吞吐量
  • D.让副本数量动态伸缩

答案:B。R + W > N 保证读集合与写集合必然有交集,因此读操作至少能遇到一个包含最新写入的副本,避免读到过期值。它不消除写写冲突,也不直接提升吞吐量或动态伸缩副本。

Q7. 分布式训练中参数服务器的模型参数同步,最适合哪种策略?

单选题 · hard

  • A.强一致串行更新
  • B.最终一致异步更新← 正确答案
  • C.完全放弃一致性
  • D.单一副本强同步

答案:B。参数服务器允许各 worker 异步拉取参数,短暂的不一致换来更高吞吐。梯度本身带有噪声,轻微的参数过期不影响收敛。强一致串行更新会拖慢训练,完全放弃一致性则可能让训练发散。

Q8. 下列哪些场景适合使用最终一致性?

多选题 · easy

  • A.电商购物车合并← 正确答案
  • B.银行账户余额
  • C.社交动态点赞数← 正确答案
  • D.系统权限白名单

答案:AC。购物车合并和点赞数允许短暂延迟,天然适合最终一致。银行余额和权限白名单要求强一致——余额错了会造成资损,权限错了会造成安全漏洞,都不能接受旧值。

Q9. 关于 CRDT 的合并运算,需要满足哪些性质?

多选题 · mid

  • A.交换律← 正确答案
  • B.结合律← 正确答案
  • C.幂等律← 正确答案
  • D.分配律

答案:ABC。CRDT 的合并运算必须满足交换律(谁先谁后结果一样)、结合律(任意分组合并结果相同)、幂等律(重复合并不产生副作用)。分配律不是 CRDT 合并运算的必要条件。

Q10. 在 Dynamo 风格存储中,同步时发现两个版本互为并发,以下哪些处理手段符合工程设计?

多选题 · extreme

  • A.保留两个版本待客户端合并← 正确答案
  • B.用向量时钟辅助判定并发← 正确答案
  • C.业务代码注册冲突回调← 正确答案
  • D.丢弃并发产生的全部版本

答案:ABC。并发冲突的工程处理包括:同时保留多个版本(Dynamo 的 sibling)、用向量时钟精确判定并发、以及注册业务回调自定义合并逻辑。D 直接丢弃全部并发版本会丢失用户更新,属于错误做法。