Files
examination/topics/architecture/cache-system/cache-read-write-strategy/fill_blank.json
T

192 lines
7.1 KiB
JSON
Raw Normal View History

{
"topic": "cache-read-write-strategy",
"type": "fill_blank",
"schema_version": "1.0.0",
"generated": "09-2026-09-05T00:00:00+08:00",
"questions": [
{
"id": "fb-001",
"type": "fill_blank",
"difficulty": 1,
"tags": [
"Cache-Aside",
"写策略"
],
"question": "Cache-Aside 策略的写流程是:先写______,再______缓存。",
"answer": [
"数据库",
"删除(失效)"
],
"answer_rule": "ordered",
"explanation": "Cache-Aside 的标准写流程:先把数据库当作真相源写入,再把缓存中的该 key 删除使其失效,等下次读请求 miss 后再回填,从而避免缓存与数据库长时间不一致。",
"source": null,
"related": []
},
{
"id": "fb-002",
"type": "fill_blank",
"difficulty": 1,
"tags": [
"Cache-Aside",
"Read-Through",
"CacheLoader"
],
"question": "Cache-Aside 的读流程是:先查缓存,若 miss 则查询______,并把结果______到缓存后返回。",
"answer": [
"数据库",
"回填(写入)"
],
"answer_rule": "ordered",
"explanation": "读请求先查缓存,miss 时由应用查数据库拿到最新值并回填缓存,再返回给调用方。这样后续相同 key 的读可以直接命中缓存,减少数据库压力。",
"source": null,
"related": []
},
{
"id": "fb-003",
"type": "fill_blank",
"difficulty": 3,
"tags": [
"Write-Through",
"Write-Behind"
],
"question": "Write-Through 策略写操作是______地把数据写入缓存和数据库;而 Write-Behind 是先写入缓存、数据库由后台______批量刷写。",
"answer": [
"同步",
"异步"
],
"answer_rule": "ordered",
"explanation": "Write-Through 写缓存即同步写数据库,强一致但慢;Write-Behind 写入缓存后立即返回成功,数据库由后台攒批/定时异步刷写,吞吐高但有丢失与乱序风险。",
"source": null,
"related": []
},
{
"id": "fb-004",
"type": "fill_blank",
"difficulty": 3,
"tags": [
"Write-Behind",
"Write-Back",
"数据安全"
],
"question": "Write-Behind 策略在返回成功到数据落库之间若缓存进程宕机,会带来______风险;因此它只适合最终一致且可容忍______的数据,不适合交易、余额、库存。",
"answer": [
"丢失",
"丢失"
],
"answer_rule": "any",
"explanation": "Write-Behind 先缓存后异步落库,若缓存宕机且尚未刷库则数据永久丢失。因此只适用于「最终一致 + 可容忍丢失」的数据,例如计数、会话、中间态;交易、余额等绝不可用。",
"source": null,
"related": []
},
{
"id": "fb-005",
"type": "fill_blank",
"difficulty": 3,
"tags": [
"多级缓存",
"L1",
"L2"
],
"question": "经典多级缓存结构是 L1 ______ 缓存 → L2 ______ 缓存 → DB。",
"answer": [
"本地(进程内)",
"Redis(共享)"
],
"answer_rule": "ordered",
"explanation": "经典多级缓存为「L1 本地进程内缓存(如 Caffeine)→ L2 Redis(共享)→ DB」。本地命中最快零网络,Redis 次之毫秒级,DB 兜底保证最终一致。",
"source": null,
"related": []
},
{
"id": "fb-006",
"type": "fill_blank",
"difficulty": 4,
"tags": [
"多级缓存",
"一致性"
],
"question": "多级缓存架构最大的代价是其______:同一数据在多个缓存层、多个节点上有副本,更新后若任一副本残留旧值就会不一致。写路径需要在先写数据库后,逐层________。",
"answer": [
"一致性",
"失效(删除/清理)"
],
"answer_rule": "ordered",
"explanation": "多级缓存中同一数据在 L1、L2 及多节点均有副本,跨层跨节点难以保证实时一致,所以一致性是最大代价。写路径以数据库为真相源,写后须逐层失效:删除 Redis 并广播清理各节点本地缓存。",
"source": null,
"related": []
},
{
"id": "fb-007",
"type": "fill_blank",
"difficulty": 4,
"tags": [
"双删",
"延时",
"竞态"
],
"question": "双删方案是:更新数据库后先删一次缓存,延时约______毫秒后再删一次,用来清掉第一次删除之后刚被回填的旧值。",
"answer": [
"50"
],
"answer_rule": "any",
"explanation": "标准双删的延时通常在几十毫秒(教材常取约 50ms),目的是让可能已读取旧值并发起回填的并发读请求完成回填,然后用第二次删除把它清掉。延时过短则回填可能还没发生,过长则会放大读 miss 窗口。",
"source": null,
"related": []
},
{
"id": "fb-008",
"type": "fill_blank",
"difficulty": 4,
"tags": [
"版本号回填",
"竞态"
],
"question": "在解决「旧值被回填」竞态问题的方案里,最彻底的是______回填:缓存数据带版本号,回填前比较,旧版本直接丢弃。",
"answer": [
"版本号"
],
"answer_rule": "any",
"explanation": "版本号回填在缓存里同时存业务值和版本号,回填前比较新旧版本,旧版本直接丢弃,杜绝读线程把库里的旧值重新写回缓存。相比双删的「概率性清理」更彻底,是根治竞态窗口来源2的方案。",
"source": null,
"related": []
},
{
"id": "fb-009",
"type": "fill_blank",
"difficulty": 3,
"tags": [
"CacheLoader",
"refreshAfterWrite",
"Read-Through"
],
"question": "Caffeine 用 ________ 把 Cache-Aside 封装成 Read-Through,缓存 miss 时自动加载;用 ________ 在写后到点异步刷新,防止热点 key 被击穿。",
"answer": [
"CacheLoader",
"refreshAfterWrite"
],
"answer_rule": "ordered",
"explanation": "CacheLoader 让 Caffeine 在 miss 时自动回调加载数据(Read-Through 的本地版);refreshAfterWrite 在写入指定时长后异步刷新,避免过期瞬间大量请求同时穿透数据库造成击穿。",
"source": null,
"related": []
},
{
"id": "fb-010",
"type": "fill_blank",
"difficulty": 3,
"tags": [
"Caffeine",
"TinyLFU"
],
"question": "Caffeine 的淘汰算法是 ________,它通过记录 key 的访问________来判定淘汰,比 LRU 更能保留高频 key。",
"answer": [
"TinyLFU",
"频率"
],
"answer_rule": "ordered",
"explanation": "Caffeine 使用 TinyLFU 淘汰算法,维护计数器记录 key 的访问频率并带时间衰减与最近访问,可避免 LRU 被批量顺序扫描冲垮,更适合热点集中的真实负载。",
"source": null,
"related": []
}
]
}