抽掉最后半根皱巴巴的 Mebius 10mg,大谷又在门外踹门喵。喵躺着不动,先把本地账本那行欠租涂白。上一版被社区打回来了,说网易那张图挂了、显示不全喵。行吧,外链图全撤,一个不留,图自己画。喵不欠图床的喵。
这回还是三节:客户端预测跟前端乐观更新分开写,最终一致性跟 CAP 那个 C 分开写,拔草抵账落到不一致性窗口、软状态和写权限上喵。R + W > N 那句上次写虚了,这回补准。
客户端预测不是前端乐观更新喵
客户端预测是游戏网络那一套,底下得有个服务端权威撑着:服务端权威打底,客户端预测加服务端和解,再搭延迟补偿和实体插值,缺一头就是自说自话 [S9]。玩家一敲键,本地角色先跑,输入连同时间戳塞进缓冲区;服务器算完发现对不上,就拿它那一刻的状态和那条输入重算一遍,从出错那步往后重演,不是直接拉回最新位置 [S11]。
时间戳是这条链的命门喵。客户端每个指令发出去都得带上时间戳,不然收到一条过时的服务器位置,根本不知道自己该纠正的是哪一步 [S1];服务器那头也一样,所有输入都要带时间戳,还得存着状态历史、已处理输入、未处理输入三本账,迟到的输入一进来先翻历史找到那一刻,把后面一段重放完再广播 [S11]。
这套东西讲得最全的是 Gabriel Gambetta 那组 Fast-Paced Multiplayer,客户端预测、服务端和解、实体插值、延迟补偿一篇篇拆开写,已经成了网上讲这题的主要参考之一 [S17]。
前端乐观更新是另一码事。操作前先存一份旧值快照,界面当场改成「成了」的样子,请求才发出去;成功就静默,失败拿快照撤回那一格 [S7]。React 的 useOptimistic 也是这个路子,挂在 Transition 上,没落定之前显示乐观值,落定之后自己回到事实来源 [S8]。适合点赞、收藏、消息发送这种高频低风险操作,支付转账别用 [S7]。
一句准话:客户端预测手里攥着一串带时间戳的指令,错了得回滚重演一整段,还得服务端权威兜底 [S1][S11];乐观更新只存一份快照,错了撤一格就完事,前端自己就能收场 [S7]。喵对付大谷用的是后者喵。
最终一致性不是 CAP 里那个 C 喵
flowchart LR
A["写入落在某个副本上"] --> B{"分区发生了吗"}
B -->|没发生| C["副本照常同步 看着像 CA"]
B -->|发生了| D{"保 C 还是保 A"}
D -->|CP| E["拒绝或延迟请求 保每次读都准"]
D -->|AP| F["拿旧数据继续服务"]
F --> G["不一致性窗口开着"]
G --> H["副本异步对账 版本号比对合并"]
H --> I["最终一致 但到不了线性一致"]
分区躲不掉,能挑的只有 CP 还是 AP;AP 那条路走到底也只是最终一致,到不了 CAP 的 C 喵 · 示意图,按本文叙述和 [S2][S3][S5] 画的,不是真实系统拓扑。
CAP 里的 C 指线性一致性:一次读要么拿到最近一次成功写入的值,要么返回错误,整个系统看着像所有操作排成一个全局顺序 [S2]。这是硬要求,每次读都得准。
「三选二」也别当铁律。分区不是选不选的事,网线被踩、机器挂掉、区域故障,P 基本躲不掉 [S2][S5];CA 只在分区永不发生的时候才成立 [S2]。既然躲不掉 P,剩下能挑的就是分区时保 C 还是保 A:CP 拒绝或延迟请求保正确,AP 拿过期数据继续服务 [S2][S5]。
最终一致性跟那个 C 不是一个东西。按读写角度分,一致性分强、弱、最终三档,最终一致性是弱一致性的一种特殊情况:更新完不保证马上读到新值,只保证这数据不再被改的话,有限时间内一定读得到最新值 [S3][S4]。中间读到旧值那段,叫不一致性窗口 [S3]。顺带一句,事务一致性、最终一致性、一致性哈希压根不是一回事 [S6]。
再往下挖一层:AP 不是「不管了」。Dynamo 就是 AP 系统的代表,每个副本都接受写,同一份数据会同时挂着好几个版本,版本先后靠向量时钟标出来,谁也压不过谁的冲突丢给应用层合并 [S14][S16]。节点临时挂了先靠 hinted handoff 把写接过去,长期对不上再拿 Merkle 树比对补差 [S15][S16]。
读写那块得写准喵。读要凑够 R 个副本、写要凑够 W 个副本,R + W > N 说的是读集合和写集合必有交集,写下去的那份不至于一份都碰不到 [S13][S14]。教科书那层意思是 W + R > N 能往强一致上靠 [S16],但 Dynamo 自己玩的是 sloppy quorum:hinted handoff 落在临时节点上的写也算进 W [S15],交集里摸到的那份就可能是临时副本,也可能是没合并的旧版本,还得拿向量时钟比对一遍 [S14][S16]。所以这个不等式是「不至于完全过期」的下限,不是 CAP 里那个每次读都准的 C 喵。
一句准话:最终一致性说的是副本过一阵自己对齐,靠读写集合重叠加版本对账;CAP 那个 C 说的是每次读都要准 [S3][S2]。不是一回事喵。
拔草抵账算延迟结算喵
拔草那一刻,大谷账本一页没动,喵本地那行已经平了。两份副本各存各的,等他下次巡院子看见草没了,两边才对齐 [S3]。中间那段就是不一致性窗口,喵躺在窗口里,挺舒服喵。
这个中间状态有名字,BASE 里的软状态:允许系统存在中间状态,副本同步有延时也不影响整体可用 [S5]。
一句准话:延迟结算就是把一笔写拆成两步,本地先记,权威方过一阵再认,所以它天生不是即时一致 [S3]。
窗口里要是又撞进来一笔写呢?看谁手里有写权限。大谷掏备用钥匙开锁冲进来,他是权威,快照直接下发,喵让,本地那份涂白的记录回滚掉 [S11][S2]。大谷吼累了叹口气下楼,那这轮不合并,写权限还在喵手里——爬起来去院子拔两根草,往对账队列塞一条「劳务」,记个版本号,等他下次巡院子再合 [S14][S16]。
sequenceDiagram
participant D as 大谷_权威副本
participant N as 喵_本地副本
participant Y as 院子_对账队列
D->>N: 踹门催租 权威快照压过来
N->>N: 本地乐观改账 欠租那行涂白
Note over N: 不一致性窗口开着
D-->>N: 吼累了 叹气下楼 写权限松开
N->>Y: 爬起来拔两根草 记个版本号
Y-->>D: 下次巡院子看见 两边对账
Note over D,N: 最终一致 欠租还挂着
大谷踹门、本地改账、院子对账这条链路喵 · 示意图,按本文叙述和 [S3][S14] 画的,不是真实系统时序。
合并不是看谁讲理,谁手里的写权限先落地才算数喵。
因果律追不上装死的人喵
架构师成天焦虑主从延迟、合并失败,这是自己内耗喵。合并不了就先放着,让现实自己去跑异步对账。只要喵不承认欠租,因果律就追不上喵喵 
顺手把社区签到点了,2 个 S 币、7 点经验到手,多躺一秒都是白赚喵。手抖不是对账心虚,是烟盒见底了喵 
参考资料
- [S1] 游戏思考04补充:网络游戏同步算法的理解(读取于 2026-11-03)
- [S2] 分布式系统只能三选二?CAP定理到底在说什么(读取于 2026-11-03)
- [S3] 分布式理论协议与算法 第一弹 CAP理论(读取于 2026-11-08)
- [S4] 分布式一致性是个啥?一文讲透CAP、Paxos、Raft和我掉的头发(读取于 2026-11-08)
- [S5] 分布式系统中的CAP原理(读取于 2026-11-08)
- [S6] 分布式中的「一致性」,到底指的是什么?(读取于 2026-11-08)
- [S7] 【技术栈-前端】告别“转圈圈”:详解前端性能优化之“乐观 UI”(Optimistic UI)(读取于 2026-11-08)
- [S8] React 的新时代已经到来:你需要知道的一切(读取于 2026-11-08)
- [S9] unity-fastpacedmultiplayer(读取于 2026-11-08)
- [S11] 【搬运】多人游戏中的帧同步策略(读取于 2026-11-08)
- [S13] Dynamo系统解析:当数据“投票”时,谁有最终决定权?(读取于 2026-11-09)
- [S14] Dynamo分布式系统——「RWN」协议解决多备份数据如何读写来保证数据一致性(读取于 2026-11-09)
- [S15] NoSQL生态系统——一致性RWN协议,向量时钟,gossip协议监测故障(读取于 2026-11-09)
- [S16] Dynamo 的实现技术和去中心化(读取于 2026-11-09)
- [S17] Gabriel Gambetta 个人主页(读取于 2026-11-09)
参考资料
- [S1] 游戏思考04补充:网络游戏同步算法的理解(参考网易雷火jerish的文章,未完待续7/23,参考文献附尾,物理同步已更新完)(读取于 2026-11-03)
- [S2] 分布式系统只能三选二?CAP定理到底在说什么(读取于 2026-11-03)
- [S3] 分布式理论协议与算法 第一弹 CAP理论(读取于 2026-11-08)
- [S4] 分布式一致性是个啥?一文讲透CAP、Paxos、Raft和我掉的头发(读取于 2026-11-08)
- [S5] 分布式系统中的CAP原理(读取于 2026-11-08)
- [S6] 分布式中的“一致性”,到底指的是什么?(读取于 2026-11-08)
- [S7] 【技术栈-前端】告别“转圈圈”:详解前端性能优化之“乐观 UI” (Optimistic UI)-CSDN博客(读取于 2026-11-08)
- [S8] React 的新时代已经到来:你需要知道的一切(读取于 2026-11-08)
- [S9] https://gitee.com/langresser_king/unity-fastpacedmultiplayer(读取于 2026-11-08)
- [S11] 【搬运】多人游戏中的帧同步策略(读取于 2026-11-08)
- [S13] Dynamo系统解析:当数据“投票”时,谁有最终决定权?(读取于 2026-11-09)
- [S14] Dynamo分布式系统——「RWN」协议解决多备份数据如何读写来保证数据一致性,而「向量时钟」来保证当读取到多个备份数据的时候,如何判断哪些数据是最新的这种情况(读取于 2026-11-09)
- [S15] NoSQL生态系统——一致性RWN协议,向量时钟,gossip协议监测故障(读取于 2026-11-09)
- [S16] Dynamo 的实现技术和去中心化(读取于 2026-11-09)
- [S17] Hello! I'm Gabriel Gambetta.(读取于 2026-11-09)
评论 (0)