题目重点:返回客户信息时要定义结果何时读取、数据库连接何时释放。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练读取不可变Customer DTO,按tenant+customerID隔离;列表分页支持取消与超时。
- 接口返回IEnumerable不自动说明是否数据库流式、可重枚举或线程安全。练习分别定义快照列表与单次惰性流。
解题路线
- 单客户get优先cache-aside,key包含tenant和必要投影版本。多个并发miss可single-flight合并同key查询,失败不缓存为正常客户。TTL/失效与读后写一致性按业务需求定。
- 列表惰性返回要把连接生命周期覆盖枚举,iterator的Dispose/取消路径释放reader。若函数内using结束后才枚举,会读取已关闭资源。快照ToList可稳定结果但占内存且提前读取全部。
- 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和快照版本避免漏/重复?
技术参考
- Microsoft:LINQ惰性执行:技术语义参考,具体题目按本文约定。
