题目重点:Senior VO SD 题目给 get/put/delete、paginated get(key*)、最终一致和高可用;按冲突、tombstone、索引与 cursor 拆解。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版 key 是可按字节/词典序比较的字符串,get(key*) 表示给定 prefix 的分页扫描,返回固定 pageSize 与下一页 cursor。
- 单键读写最终收敛;高可用指单节点/单区故障下仍尽量服务,具体 RPO/RTO 和冲突策略需确认。
- 不支持多键原子事务;删除以带版本 tombstone 传播,避免旧副本将已删数据复活。
解题路线
- 先算 key 数、平均 value、读写比、热点、保留期与复制地域,再明确写入确认等级和读到旧值是否可接受。
- 按 key 分片并复制,put/delete 先生成唯一版本与请求 ID 后写入副本;异步复制提高可用性,读可返回旧值,需明说 read-your-writes 是否额外提供。
- 冲突策略可用带版本的 LWW、向量/逻辑时钟或应用合并;不能把壁钟时间当无误全序,跨区时钟漂移会带来覆盖。
- delete 写 tombstone 并保留足够长的反熵窗口,保证离线副本恢复后不会把旧值带回;后台修复与压缩要确认所有副本已见删除。
- get(prefix) 依 key 范围扫描或前缀索引,按稳定 (key,version) 顺序分页;cursor 带 prefix、最后 key 和快照/版本水位。若未提供快照语义,必须告知并发写入时可能重复/漏项。
- 监控副本落后、读旧率、冲突率、分区热点、tombstone 积压和分页延迟,并做节点/Region 故障演练。
手动走一遍
训练例:put('ab1',v1)、put('ab2',v2) 后分页 get('ab*',1) 首次返回 ab1 和 cursor。翻页前 ab0 插入,若只用 offset=1 会重复/漏项;以最后 key=ab1 的 keyset cursor 在约定快照下继续返回 ab2。删除 ab1 时保留 tombstone,旧副本回归不能复活。
规模与取舍
精确 key 的路由/读写可接近 O(1) 次分片定位及副本网络操作;有序索引前缀分页约 O(log K+P) 查找/输出,K 为分片 key 数、P 为页大小。总存储约数据量×副本数加索引/tombstone;最终延迟取决于复制拓扑,题目无数值。
易错点与追问
容易失分的边界
- 只讲 hash 分片,却无法支持 key* 的有序分页。
- 删除直接移除,旧副本复活数据。
- 使用 offset 分页却不定义并发写入语义。
- 声称高可用与跨区强一致、零丢失均无代价。
- 没有明确同键并发写冲突策略。
继续深挖
- 如何提供 read-your-writes?
- 前缀热点如何拆分?
- 分页需要强快照时成本如何变化?
- tombstone 何时能安全清理?
