Backend Engineering Specialist · OA Coding Levels 1–4

xAI 内存 DB 四级题:字段扫描、TTL 半开区间与备份恢复

Backend Specialist OA 给 set/get/delete、字典序 scan、带时间戳 TTL 和 backup/restore;重点是恢复时保留剩余寿命。

题目重点:Backend Specialist OA 给 set/get/delete、字典序 scan、带时间戳 TTL 和 backup/restore;重点是恢复时保留剩余寿命。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练版 set 覆盖同 key/field 的旧值;delete 返回是否实际删掉,get 缺失返回 null;scan 格式为 `field(value)` 并按 field 字典序。题目只列操作名,返回状态以具体测试契约为准。
  • 时间戳操作单调不减且不与无时间 API 混用;TTL>0,写入 t 的有效区间 [t,t+ttl)。无 TTL 项的到期时间记无穷。
  • backup(t) 只保存 t 时仍有效的字段及剩余寿命 expiry−t;restore(now, target) 选 backupTime≤target 的最新备份,把有限 TTL 字段新到期设为 now+remaining,恢复后整个当前状态替换为快照副本。
  • 若同一时间戳有多个操作,训练版按调用顺序执行;同时间戳 backup/restore 次序不在题目中。

解题路线

  1. 用 records[key][field]=(value,expiry) 存活跃状态;每次 get/scan/delete 先判断 t<expiry,过期字段按懒删除清理,空 record 可删。无时间 API 只运行前两级,不强行赋合成时间戳。
  2. scan 与 scan_by_prefix 先收集有效 field,再对 field 排序并转成 `field(value)`;过滤发生在排序前或后结果等价,但 prefix 仅检查字段名。
  3. backup 生成与当前 records 不共享可变引用的快照。有限 TTL 存 remaining=expiry−backupTime,永久字段保留无穷;保存 backup 时间和有效字段数以支持返回值。
  4. restore 通过有序 backup 时间二分或顺序扫描选最新≤target;为每个字段以当前 now 重建 expiry=now+remaining。这样等待很久再恢复不会把备份时的绝对到期时间直接搬回来。
  5. 用覆盖写、恰到期、前缀空结果、同时间戳备份、恢复后过期、恢复后再备份做状态转移测试;题目时间压力下先实现 L1/L2 再加 TTL/backup,避免一开始过度设计。

手动走一遍

训练例:t=10 写 field=a、ttl=5,有效至 t<15;t=12 备份时 remaining=3。t=20 调 restore(now=20,target=12) 后,新到期为 23;get_at(22) 可见、get_at(23) 不可见。若直接保存旧 expiry=15,恢复后立刻过期,与 Level 4 要求冲突。

规模与取舍

K 个 key、F 个当前字段:set/get/delete 平均 O(1) 字典操作加懒过期判断;某 key 的 m 个字段 scan 为 O(m log m) 时间、O(m) 临时空间。每次 backup 复制 O(F) 时间和空间;B 份备份共 O(BF) 最坏空间,restore 选备份 O(log B) 并复制 O(F)。

易错点与追问

容易失分的边界

  • 把 TTL 结束 t+ttl 当成仍有效,违反半开区间。
  • scan 排序的是完整 `field(value)` 字符串而非 field 名,在字段名前缀关系下可能得到错误顺序。
  • backup 仅保存绝对 expiry,长时间后 restore 无法复活剩余 TTL。
  • 快照与当前 DB 共用嵌套 dict,后续 set 改写旧备份。
  • restore 选第一个早于目标的快照而非最新一个。

继续深挖

  • 如何把大量备份改为增量快照或 copy-on-write?
  • 恢复后无 TTL 字段怎样表示?
  • 同时间戳的 set、delete、backup 次序如何定义并测试?
  • 若操作时间不再单调,懒过期方案有什么问题?
✓已复制微信号!