题目重点:从写入ACK、版本与读路径定义复制服务,说明quorum交集为何不自动带来线性一致,以及分区和旧主恢复的处理。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版单key读写、N副本、有版本,不承诺多key事务。先澄清linearizable还是允许旧读,再选择复制协议。
- 持久ACK指日志已落到规定故障域,非内存响应;复制数、quorum、容灾范围为训练参数。
- 文章是通用设计,不复原未公开的Azure Storage组件或当前产品实现。
解题路线
- 画请求→分片路由→复制组→持久日志→读响应,明确每个key归属与版本。写ACK必须说明W个副本接受什么内容、是否fsync及会失去哪类故障下的已确认数据。
- 对固定成员集合,R+W>N保证读集合与已完成写集合有交集,W>N/2保证两写quorum相交;这只提供交集条件。并发写版本、读修复、成员变更和sloppy quorum若没定义,不能宣称自然线性一致。
- 若要求线性一致,选leader与多数提交并处理任期/epoch、旧主拒写、读屏障或有效租约;读到未提交副本数据不是安全优化。若允许最终一致,定义版本冲突与应用合并,而非以本地时钟最新作绝对事实。
- 节点故障从日志/快照恢复、追尾校验,反熵修复遗漏;成员更换需要安全过渡,不能在两个互不相交成员集各自凑quorum写。删除保留tombstone至安全清理点,避免旧副本恢复复活数据。
- 网络分区按合同拒绝无法证明安全的写或提供可标记的旧读。容量看写放大N、热点key、恢复带宽与尾延迟;故障时限制追尾负载,保护正常流量。
手动走一遍
训练例N=3,W=2,R=2,一次写提交A/B,读B/C能见交集B;若读取A/B/C的版本规则未定义,存在并发写时仍不能推出唯一正确值。A离线后以旧epoch恢复,必须追尾并经过成员/任期核对,不能直接接受旧主写。
规模与取舍
写复制通信O(N)或quorum所需副本数,读O(R)网络操作;延迟取参与副本尾部与跨域往返。日志量按更新次数×值大小×副本估,恢复成本按未同步字节估。
易错点与追问
容易失分的边界
- R+W>N当成完整线性一致证明。
- 把内存ACK说成持久化。
- 删除没有tombstone,旧数据复活。
- 节点更换时直接改N,忽略quorum跨成员交集。
继续深挖
- 一个AZ失效后仍可写,需要怎样布副本?
- 如何避免旧leader网络恢复后继续写?
- 强一致读能否只读一个follower?
- 追尾恢复流量压垮正常写时如何调度?
