SWE · System Design

Customer内部服务:数据库、惰性枚举、缓存与并发

返回客户信息时要定义结果何时读取、数据库连接何时释放。

题目重点:返回客户信息时要定义结果何时读取、数据库连接何时释放。

题意与假设

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

  • 训练读取不可变Customer DTO,按tenant+customerID隔离;列表分页支持取消与超时。
  • 接口返回IEnumerable不自动说明是否数据库流式、可重枚举或线程安全。练习分别定义快照列表与单次惰性流。

解题路线

  1. 单客户get优先cache-aside,key包含tenant和必要投影版本。多个并发miss可single-flight合并同key查询,失败不缓存为正常客户。TTL/失效与读后写一致性按业务需求定。
  2. 列表惰性返回要把连接生命周期覆盖枚举,iterator的Dispose/取消路径释放reader。若函数内using结束后才枚举,会读取已关闭资源。快照ToList可稳定结果但占内存且提前读取全部。
  3. IEnumerable可每次枚举重跑查询;调用Count再foreach可能两次DB访问且数据不同。并发枚举同reader应拒绝或各自独立reader;异步I/O可采用IAsyncEnumerable,缓存已物化不可变数据而非活跃iterator。

手动走一遍

两个请求同时查tenantA/42,只发一次DB查询;tenantB/42不能拿A的缓存。消费者只读前10项就停止:流必须释放连接;若缓存的是iterator,第二个消费者可能接着读第11项,是错误共享状态。

规模与取舍

单get平均cache O(1),miss成本含DB索引查找/网络。列表N行物化O(N)空间,流式O(pageSize)缓冲但连接占用持续到枚举终止。

易错点与追问

容易失分的边界

  • 线程安全的cache容器不让其内部可变Customer自动线程安全。
  • 长时间流式读取会耗尽连接池,必须限制并发/取消/批次。

继续深挖

  • 负缓存多久有效,怎样避免新建客户后持续404?
  • 按页重开连接怎样用keyset和快照版本避免漏/重复?

技术参考

✓已复制微信号!