Coinbase 内存数据库面试题 2026:90 分钟分阶段高分解法
Coinbase 内存数据库面试题 2026 在近期非常高频。
因此,你需要一套可复用模板。
此外,这里统一来源口径。
这是我们学员贡献的最新面经。
与此同时,本文按 2026年最新 标准复盘。
2026 面试流程深度复盘:Coinbase 内存数据库面试题 2026
首先,这题通常是 90 分钟。
因此,面试官会分 4 个阶段加码。
此外,时间戳单调递增是关键前提。
换句话说,你可以用追加写简化实现。
首先,第 1 阶段是基础 CRUD。
因此,你先写 store/get/delete。
此外,要先讲清删除语义。
具体来说,删除后应返回空值。
随后,第 2 阶段是 CAS 更新。
因此,要实现 storeItemIfMatch。
此外,判断对象是“当前可见值”。
换句话说,要先读再原子写入。
接着,第 3 阶段是前缀扫描。
因此,要实现 scanByKeyPrefix。
此外,你要解释索引为何可扩展。
与此同时,要给出复杂度结论。
最后,第 4 阶段是历史读取与 TTL。
因此,会加 getItemAtTimestamp。
此外,还会加 storeItemWithTTL。
总而言之,Coinbase 内存数据库面试题 2026 的核心是“多版本+可见性”。
在 Coinbase 内存数据库面试题 2026 里,常见追问很直接。
因此,你要准备“历史点扫描”扩展。
此外,要说明跨 key 一致性口径。
换句话说,所有 key 都按 scan_timestamp 判断可见。
核心题目解析
因此,推荐的数据模型是两层。
首先,key -> versions[] 存版本链。
此外,维护一个全局有序 key 索引。
与此同时,版本链按时间追加即可。
具体来说,版本结构至少含四项。
因此,需要 timestamp 与 value。
此外,需要 is_deleted 或空值墓碑。
与此同时,TTL 用 expire_at 表达。
但是,你要避免一个常见错误。
因此,TTL 过期后不应“回退旧值”。
此外,墓碑也不应回退旧值。
换句话说,只看查询时刻前的最新版本。
在 Coinbase 内存数据库面试题 2026 中,双时间戳很关键。
因此,get_timestamp 是目标历史点。
此外,timestamp 是当前操作时间。
具体来说,若 get_timestamp > timestamp,应拒绝或报错。
System Design 逻辑流程图
flowchart TD
A[接收操作与timestamp] --> B{操作类型}
B -->|store/delete/CAS/TTL写入| C[按key追加新版本]
C --> D[必要时更新有序key索引]
B -->|get/getAt| E[二分找到<=查询时刻的最新版本]
E --> F{版本在该时刻可见?}
F -->|是| G[返回value]
F -->|否| H[返回None]
B -->|scanPrefix/scanPrefixAt| I[在有序key中定位前缀范围]
I --> J[逐key执行历史可见性判断]
J --> K[返回有序结果集]
Python 参考代码(可直接改写为面试版本)
from __future__ import annotations
from dataclasses import dataclass
from bisect import bisect_left, bisect_right, insort
from typing import Dict, List, Optional, Tuple
@dataclass
class Version:
ts: int
value: Optional[str] # None means tombstone (deleted)
expire_at: Optional[int] # None means no TTL
class TimeKV:
def __init__(self) -> None:
self.hist: Dict[str, List[Version]] = {}
self.sorted_keys: List[str] = []
def _ensure_key(self, key: str) -> None:
if key not in self.hist:
self.hist[key] = []
insort(self.sorted_keys, key)
def _append(self, key: str, v: Version) -> None:
self._ensure_key(key)
self.hist[key].append(v)
def _last_version_at(self, key: str, at_ts: int) -> Optional[Version]:
versions = self.hist.get(key)
if not versions:
return None
lo, hi = 0, len(versions) - 1
ans = -1
while lo <= hi:
mid = (lo + hi) // 2
if versions[mid].ts <= at_ts:
ans = mid
lo = mid + 1
else:
hi = mid - 1
return versions[ans] if ans >= 0 else None
def _visible_value(self, v: Optional[Version], at_ts: int) -> Optional[str]:
if v is None or v.value is None:
return None
if v.expire_at is not None and at_ts >= v.expire_at:
return None
return v.value
def storeItem(self, key: str, item: str, timestamp: int) -> None:
self._append(key, Version(timestamp, item, None))
def deleteItem(self, key: str, timestamp: int) -> None:
self._append(key, Version(timestamp, None, None))
def getByKey(self, key: str, timestamp: int) -> Optional[str]:
v = self._last_version_at(key, timestamp)
return self._visible_value(v, timestamp)
def storeItemIfMatch(
self, key: str, cur_item: Optional[str], new_item: str, timestamp: int
) -> bool:
current = self.getByKey(key, timestamp)
if current != cur_item:
return False
self._append(key, Version(timestamp, new_item, None))
return True
def storeItemWithTTL(self, key: str, item: str, ttl: int, timestamp: int) -> None:
expire_at = timestamp + max(ttl, 0)
self._append(key, Version(timestamp, item, expire_at))
def getItemAtTimestamp(
self, key: str, get_timestamp: int, timestamp: int
) -> Optional[str]:
if get_timestamp > timestamp:
raise ValueError("get_timestamp cannot be greater than current timestamp")
return self.getByKey(key, get_timestamp)
def _keys_with_prefix(self, key_prefix: str) -> List[str]:
start = bisect_left(self.sorted_keys, key_prefix)
end = bisect_right(self.sorted_keys, key_prefix + chr(0x10FFFF))
out = []
for k in self.sorted_keys[start:end]:
if not k.startswith(key_prefix):
break
out.append(k)
return out
def scanByKeyPrefix(self, key_prefix: str, timestamp: int) -> List[Tuple[str, str]]:
res: List[Tuple[str, str]] = []
for k in self._keys_with_prefix(key_prefix):
v = self.getByKey(k, timestamp)
if v is not None:
res.append((k, v))
return res
def scanByKeyPrefixAtTimestamp(
self, key_prefix: str, scan_timestamp: int, timestamp: int
) -> List[Tuple[str, str]]:
if scan_timestamp > timestamp:
raise ValueError("scan_timestamp cannot be greater than current timestamp")
return self.scanByKeyPrefix(key_prefix, scan_timestamp)
专家备考策略与高频考点:Coinbase 内存数据库面试题 2026
因此,Coinbase 内存数据库面试题 2026 的备考要先抓主线。
首先,你要先讲“按序写入”收益。
此外,再讲“多版本可见性”规则。
总而言之,先语义后代码,成功率更高。
核心考点
- 因此,CRUD 要保证读写一致。
- 此外,CAS 要基于最新可见值。
- 但是,TTL 过期后不能回滚旧值。
- 与此同时,前缀扫描要有有序索引。
- 具体来说,历史查询要区分双时间戳。
- 总而言之,要清晰给出时空复杂度。
STAR 应对策略(BQ)
- S:因此,我接到分阶段内存库题。约束是时间戳单调。
- T:此外,我目标是先过功能。然后保证可扩展。
- A:与此同时,我采用版本链+有序 key 索引。并定义统一可见性函数。
- R:总而言之,我在时限内完成全部接口。还能回答复杂度与权衡。
总结与行动号召 (CTA)
总而言之,Coinbase 内存数据库面试题 2026 的破题法很明确。
因此,你先锁定语义。然后再写结构。
此外,你要用一套模板覆盖 CRUD、CAS、TTL、历史查询与前缀扫描。
如果你想做一轮实战模拟,可点这里:联系我们的专家进行一对一面试辅导。
与此同时,你也可以补充基础阅读:权威算法参考。