面试知识

Redis(远程字典服务)缓存锁与高可用失败追问

91-高频追问题库 面试知识整理。

Redis(远程字典服务)缓存锁与高可用失败追问

本册只编排缓存、锁、持久化与高可用失败追问,不复制机制正文。所有项目陈述沿用 E0(待核对)、E1(直接证据)、E2(既有材料映射)和 E3(演练设计)边界;Redis(远程字典服务)只承担加速、协调和削峰,库存与支付最终事实必须由数据库条件、唯一流水、账务分录和对账裁决。

Redis(远程字典服务)缓存、锁与高可用失败追问闭环

正式图解读: 六个并行分支分别覆盖缓存三类失效、热键与大键、持久化恢复、主从/哨兵/集群、锁失租与脑裂、库存与支付不变量。正常路径以业务键和时间窗固定现场,经可证伪证据裁决后执行止血、修复、验证和复盘;证据不足时只能降为 E0(待核对)。图的前提是缓存命中、复制偏移、锁值和业务流水可关联,结论是 Redis(远程字典服务)恢复不能替代业务事实收敛。可编辑源见 redis-cache-lock-failure-followup.puml

1. 缓存穿透、击穿与雪崩

1.1 从请求分布到回源放大与恢复门禁

缓存穿透是大量不存在的业务键绕过缓存持续访问权威存储;缓存击穿是单个或少量热点键失效后并发回源;缓存雪崩是大量键在相近时间失效、节点故障或依赖退化后形成面状回源。三者都表现为命中率下降和数据库压力升高,但键分布、失效时间与回源集中度不同,必须先分类再止血。

flowchart LR
    A[固定请求键与时间窗] --> B{键是否存在}
    B -->|长期不存在| C[穿透:负缓存与前置过滤]
    B -->|存在且单键突发| D[击穿:合并回源与旧值兜底]
    B -->|大量键同步失效| E[雪崩:随机过期与分批预热]
    C --> F[限流并保护权威存储]
    D --> F
    E --> F
    F --> G[核对命中率、回源率与业务正确性]
    G --> H{恢复门禁达标}
    H -->|是| I[逐步退出降级]
    H -->|否| J[保留限流并继续取证]

图解读: 分支按“键是否存在、热点是否集中、失效是否同步”裁决三类故障;箭头把技术止血统一收敛到权威存储保护和业务验收。正常路径逐步退出降级,失败路径继续限流并补证据。前提是能按稳定业务键统计命中和回源,结论是命中率下降本身不能直接证明故障类型。

故障类型键分布与失效特征最小证据首轮止血修复与验收
穿透高比例键从未存在或已被恶意枚举不存在键比例、参数校验、回源结果参数校验、负缓存、按来源限流过滤器与负缓存过期可控,合法新数据不被误挡
击穿一个热点键在失效点并发回源单键请求率、失效时间、加载并发合并回源、旧值短时服务、热点限流仅一个加载者,旧值退出后内容正确
雪崩大量键或节点在同一窗口失效过期分布、节点事件、数据库连接与延迟全局限流、分级降级、暂停批量预热过期离散、预热有预算、回源峰值受控
伪命中率故障统计口径或键版本变化客户端版本、键前缀、采样口径冻结变更并分版本观察新旧键迁移和指标口径一致

数据演绎 1:失效如何放大数据库压力。 E3(演练设计)设商品详情平时每秒 12,000 个请求,命中率 98%,正常回源为 12000 × 2% = 240 个/秒。10 个热点键同时失效后命中率降到 70%,回源升为 12000 × 30% = 3600 个/秒,是正常值的 15 倍;若数据库稳定能力为 1,200 个/秒,则每秒净新增 2,400 个等待请求,20 秒可形成 48,000 个请求的理论积压。状态从命中、失效、并发回源推进到连接池耗尽;观测信号包括每键请求率、命中率、回源并发、数据库等待和错误率。结论是先把回源压到数据库能力以内,再讨论预热速度。

失败注入、证据链与项目落地: E3(演练设计)分别注入随机不存在商品号、让单个热点库存展示键过期、批量删除同一前缀键。证据链固定客户端、租户、仓库、SKU(库存单位)、键版本和时间窗,关联命中、回源、数据库查询与业务流水。止血按来源和热点键限流,允许非关键展示返回短时旧值,但库存预占仍执行数据库条件更新。修复后重放同量级流量,要求回源受预算、数据库无排队扩散、合法新商品可见、库存不为负。机制回链 缓存模式与一致性,属于 E2(既有材料映射);真实事故影响为 E0(待核对)。

热门面试题

  1. 问题(基础题):缓存穿透、击穿和雪崩怎样快速区分?
    • 考点:键存在性、热点集中度、失效分布。
    • 回答思路:先看不存在键比例,再看单键集中度和批量过期时间。
    • 详细答案:穿透以不存在键持续回源为主;击穿是存在的热点键在失效点集中回源;雪崩是大量键、节点或依赖同时失效形成面状回源。应把每键请求率、缓存结果、回源结果和过期分布放在同一时间窗比较。
    • 进阶追问:命中率从 99% 降到 80% 能直接判雪崩吗?
    • 进阶回答:不能,还可能是键版本变更、统计口径变化或单个超大热点;必须看键分布和失效事件。
  2. 问题(原理题):合并回源为什么仍可能把数据库打满?
    • 考点:锁粒度、跨实例、加载超时与重试。
    • 回答思路:说明单实例合并、全局热点和失败重试的边界。
    • 详细答案:若只在单实例合并,多实例仍会各自回源;若加载超时后所有等待者重试,回源会再次齐发;锁键错误还会让不同版本相互阻塞。应按稳定业务键协调,限制等待和重试,并给旧值或明确降级路径。
    • 进阶追问:让所有请求无限等待首个加载者可以吗?
    • 进阶回答:不可以,加载者卡住会形成请求堆积;等待必须有预算并能返回旧值、降级或失败。
  3. 问题(项目题):库存展示缓存雪崩时怎样保证不超卖?
    • 考点:缓存与库存事实分层、止血和业务验收。
    • 回答思路:展示可降级,预占仍由条件更新和唯一流水裁决。
    • 详细答案:先限制展示回源并暂停非关键预热,可返回带版本的短时旧展示;真正预占必须执行数据库 available >= quantity 条件更新并写唯一请求流水。恢复后既看命中和数据库延迟,也核对库存不为负、流水守恒和未知请求归零。
    • 进阶追问:缓存显示无货能否直接拒绝订单?
    • 进阶回答:若业务接受保守拒绝可以作为降级,但要标明口径并在缓存恢复后退出;不能把缓存显示有货当成扣减成功。

2. 热键、大键与单线程阻塞

2.1 从流量倾斜和命令成本到隔离治理

hot key(热键)是访问量显著集中、足以打满单节点网络或执行能力的键;big key(大键)是值体积或集合成员数过大、导致传输、遍历、删除、复制和持久化成本突增的键。二者可能重叠,但诊断证据不同:热键看请求分布和带宽,大键看编码后大小、成员数、命令时长和复制影响。

sequenceDiagram
    participant C as 客户端
    participant R as Redis(远程字典服务)节点
    participant O as 观测系统
    participant D as 权威存储
    C->>R: 高频读取或大对象命令
    R-->>O: 每键请求率、字节数、慢命令
    alt hot key(热键)
        O-->>C: 本地副本、请求合并、限流
    else big key(大键)
        O-->>C: 禁止全量读取、分批拆键
        R->>D: 核对完整业务事实
    end
    C->>R: 受预算的恢复流量
    R-->>O: 延迟、带宽与事件循环恢复

图解读: 客户端、节点、观测系统和权威存储共同区分流量热点与对象体积问题。正常路径按类型采用副本或拆键;失败路径若两者叠加,则先限流并禁止全量命令。前提是按键采样不会暴露敏感信息,结论是平均节点负载健康不能排除单分片热点。

维度hot key(热键)big key(大键)叠加风险验收信号
主要压力请求数、带宽、连接与单分片处理序列化、传输、遍历、删除与复制高频传输大对象,尾延迟陡升每键请求率和字节率回预算
定位证据客户端统计、代理采样、节点网络内存采样、成员数、慢命令、延迟事件同一键同时居于两类榜首节点与分片负载不再倾斜
止血本地短缓存、合并请求、限流、只读副本禁止全量命令、惰性删除、分批迁移先限制入口,再小步拆分无长阻塞和复制积压
根治按稳定维度分片、主动刷新、容量隔离数据模型拆分、分页访问、生命周期约束读模型与权威账本分离内容正确且历史键清理完成

数据演绎 2:热键与大键叠加的带宽成本。 E3(演练设计)某活动配置值为 2 MiB(兆字节),每秒读取 2,000 次,理论出站为 2 × 2000 = 4000 MiB/s,即约 3.9 GiB(吉比字节)每秒;即使节点命令数不高,网络和序列化也会先饱和。若改为 20 KiB(千字节)的版本摘要,本地命中 95%,回到 Redis(远程字典服务)的流量约为 20 KiB × 2000 × 5% ≈ 1.95 MiB/s。状态从全量远程读取变为摘要校验和本地副本;观测信号是每键字节率、响应大小、网络队列、事件循环延迟与客户端命中。结论是不能只看每秒命令数,字节成本同样决定热点上限。

失败注入、证据链与项目落地: E3(演练设计)给 IoT(物联网)报警规则键注入 50 万成员并让全部设备并发读取,再对键执行全量遍历和同步删除。保存命令耗时、节点延迟、网络、复制积压、持久化子进程和客户端超时。止血为关闭全量接口、按设备和租户限流、使用已有规则快照,并避免在高峰同步删除。修复采用规则分片、分页、版本摘要、本地只读副本和异步惰性清理;验证要求报警原始事件不丢、重复通知受幂等约束、节点延迟恢复且旧大键最终清除。机制回链 内存淘汰与热键大键治理,为 E2(既有材料映射)。

热门面试题

  1. 问题(基础题):hot key(热键)和 big key(大键)有什么区别?
    • 考点:访问频率、对象体积与资源模型。
    • 回答思路:分别从请求分布和单次命令成本定义。
    • 详细答案:hot key(热键)强调访问量集中,可能是很小的值;big key(大键)强调值或成员过大,即使低频也可能阻塞和放大复制。二者可叠加,因此定位要同时看每键请求率、字节率、成员数和命令时长。
    • 进阶追问:平均每节点处理器不高能排除热键吗?
    • 进阶回答:不能,热点可能先打满单分片网络、连接或事件循环,平均值会掩盖倾斜。
  2. 问题(原理题):为什么删除 big key(大键)也可能造成故障?
    • 考点:对象释放、单线程时间、复制与内存回收。
    • 回答思路:说明逻辑删除和实际释放都需要成本。
    • 详细答案:同步删除大集合需要遍历并释放大量内部对象,会长时间占用执行线程;惰性删除把释放移到后台,但仍消耗处理器和内存带宽。删除还会进入复制与持久化链路,因此应在低峰、受预算地分批执行并观察延迟。
    • 进阶追问:使用惰性删除就没有风险吗?
    • 进阶回答:没有消失,只是从前台延迟转为后台资源压力,还要防止待释放对象堆积。
  3. 问题(项目题):IoT(物联网)报警规则成为热键时怎样降级?
    • 考点:本地副本、版本一致性、报警不变量。
    • 回答思路:用版本化快照减少远程读取,并让原始事件持久化。
    • 详细答案:客户端保留最后校验成功的只读规则快照,通过小型版本键判断刷新;热点期间合并刷新并按租户限流。规则暂时旧可能影响通知时效,但原始报警事件必须持久化,恢复后按事件位点重算,不能因缓存故障丢事件。
    • 进阶追问:本地副本是否会导致规则不一致?
    • 进阶回答:会有短时版本差,因此要携带版本、设最大陈旧时间并保留回放路径;高风险规则可拒绝使用过旧快照。

3. RDB(快照持久化)、AOF(追加日志)与恢复

3.1 从确认边界到可复演恢复链

RDB(快照持久化)保存某一时点的数据镜像,恢复快但故障点之后的变更可能缺失;AOF(追加日志)记录写命令,数据损失窗口取决于刷盘策略,文件可能出现尾部截断、重写切换和磁盘空间风险。持久化可提高 Redis(远程字典服务)数据恢复能力,却不能把异步复制和缓存语义升级为库存或资金强一致。

stateDiagram-v2
    [*] --> 正常写入
    正常写入 --> 生成快照: RDB(快照持久化)触发
    正常写入 --> 追加日志: AOF(追加日志)写入
    追加日志 --> 刷盘确认
    生成快照 --> 故障恢复
    刷盘确认 --> 故障恢复
    故障恢复 --> 校验文件
    校验文件 --> 隔离恢复: 文件损坏或尾部异常
    校验文件 --> 加载数据: 校验通过
    隔离恢复 --> 修复副本
    修复副本 --> 加载数据
    加载数据 --> 业务对账
    业务对账 --> 分批开放
    分批开放 --> [*]

图解读: 状态机把写入、快照、日志、文件校验、隔离恢复、业务对账和放量串成可审计过程。正常路径直接校验并加载,失败路径先复制文件后修复,避免在唯一证据上原地操作。前提是恢复环境与生产隔离,结论是进程启动成功只证明文件可加载,不证明业务状态完整。

机制恢复输入主要损失窗口主要风险恢复验收
RDB(快照持久化)最近完整快照最近快照至故障点快照过旧、写时复制内存、文件损坏文件校验、键数量和业务版本对照
AOF(追加日志)已写入并保留的命令日志最后刷盘后的写尾部截断、磁盘满、重写切换错误日志检查、隔离加载和命令边界核对
混合恢复快照前缀加增量日志取决于增量刷盘格式版本、重写基线与增量衔接在相同版本隔离实例完整演练
副本重建健康主或备份取决于复制和备份新鲜度把落后副本当最新事实比较复制偏移、时间和业务账本

数据演绎 3:恢复点与业务事实的差距。 E3(演练设计)10:00:00 生成 RDB(快照持久化),10:05:00 进程故障;期间每秒 800 次缓存写,共 800 × 300 = 240000 次变化。若只加载快照,最多回退 5 分钟。AOF(追加日志)按每秒刷盘,理论上通常只暴露约 1 秒窗口,但磁盘阻塞、操作系统缓存和突然断电会改变真实边界,不能把“一秒”当绝对承诺。若这些写只是商品读模型,可从数据库重建;若误把支付状态只存缓存,则任何窗口都不可接受。观测信号包括快照时间、日志偏移、刷盘延迟、复制偏移和业务版本。

失败注入、证据链与项目落地: E3(演练设计)在隔离环境分别注入进程终止、磁盘写满、AOF(追加日志)尾部半条命令和重写期间故障。保留原文件只读副本,记录配置、版本、文件摘要、最后有效偏移和加载日志。止血时支付查询回到权威订单与账务库,库存展示可降级,禁止依据回退后的缓存重复扣减或补款。修复后先隔离加载、比对键版本,再从数据库或事件位点重建;验证要求缓存内容可再生、库存流水守恒、支付分录借贷平衡且未知订单已查证。机制回链 持久化与复制,为 E2(既有材料映射)。

热门面试题

  1. 问题(基础题):RDB(快照持久化)和 AOF(追加日志)如何选择?
    • 考点:恢复速度、数据窗口和运行成本。
    • 回答思路:按可接受恢复点、恢复时间和资源预算权衡。
    • 详细答案:RDB(快照持久化)文件紧凑、加载快,适合备份和快速重建,但快照间隔内数据可能丢失;AOF(追加日志)恢复点更细,却有写入、刷盘、重写和文件增长成本。常见做法是结合使用并用真实故障演练验证,而不是只背配置。
    • 进阶追问:开启两者就能零丢失吗?
    • 进阶回答:不能,刷盘、复制、文件和故障域仍有边界;缓存数据还必须可从权威来源重建。
  2. 问题(原理题):AOF(追加日志)尾部损坏时为什么不能直接删文件重启?
    • 考点:证据保护、有效边界和可回退恢复。
    • 回答思路:先复制原文件,再检查最后有效命令边界。
    • 详细答案:直接删除会同时丢掉可恢复数据和根因证据。应冻结写入、复制文件与摘要,在隔离环境用目标版本工具检查并修复副本,确认截断范围后加载,再与业务账本和复制偏移对照。
    • 进阶追问:工具返回成功是否代表数据完整?
    • 进阶回答:只代表格式可接受,还要核对键版本、数量、业务摘要和权威账本。
  3. 问题(项目题):支付缓存恢复后为什么不能据此补单?
    • 考点:资金权威事实、恢复回退和幂等查证。
    • 回答思路:缓存只提供查询加速,支付结果由订单、渠道与账务共同裁决。
    • 详细答案:恢复后的缓存可能回退、缺键或包含旧状态,直接补单会制造重复扣款或重复入账。应以原支付请求号查询渠道,核对支付订单状态、唯一分录和对账差异,再幂等重建缓存。
    • 进阶追问:渠道显示成功但本地订单失败怎么办?
    • 进阶回答:保持差异待处理,按原请求号补记唯一账务流程,禁止重新发起扣款。

4. 主从、哨兵与 Cluster(集群)

4.1 从复制延迟、故障转移到脑裂围栏

主从复制解决数据副本和读扩展,却因异步传播存在已返回写尚未到达副本的窗口;哨兵在单主拓扑上增加故障检测、投票和自动切换;Cluster(集群)通过 slot(槽)分片扩展容量,并为每个分片提供副本切换。它们都不能消除最近写丢失、旧主继续服务、客户端地址未刷新和业务多键原子边界。

graph TB
    C[客户端写入] --> M[旧主节点]
    M -->|异步复制| R1[从节点一]
    M -->|异步复制| R2[从节点二]
    S[哨兵多数或 Cluster(集群)多数] --> D{主节点是否客观失效}
    D -->|否| M
    D -->|是| P[选择复制较新的副本]
    P --> N[提升新主并发布新拓扑]
    C -->|地址未刷新| M
    C -->|刷新后| N
    M --> X[旧主写入分叉]
    N --> Y[新主写入历史]
    X --> Z[业务幂等、围栏与对账]
    Y --> Z

图解读: 数据面复制和控制面选主是两条链;正常路径让客户端刷新到新主,失败路径是旧连接继续写旧主并形成分叉。前提是多数派仍可形成选举,结论是“选出新主”不等于“所有客户端已停止写旧主”,业务副作用仍要围栏和对账。

拓扑解决的问题关键失败窗口最小证据业务防线
主从副本、只读扩展、备份来源主故障需人工接管,读从节点可能陈旧复制偏移、延迟、断连时间强读路径回主或查权威库
哨兵单主自动故障检测与转移误判、切换时间、旧主仍写、最近写丢失主客观下线、纪元、投票、角色变化客户端发现、旧主隔离、幂等与围栏
Cluster(集群)容量分片、分片级故障转移单分片热点、跨槽限制、迁槽重定向slot(槽)归属、配置纪元、重定向、复制状态稳定键设计、多键同槽边界、账本兜底
跨故障域部署降低单机房失效延迟、成本与多数派布局错误节点分布、链路延迟、故障演练明确可用性优先级与降级路径

数据演绎 4:异步复制和切换窗口。 E3(演练设计)旧主偏移为 500,000,两个从节点分别为 499,992 与 499,980;最后 8 条写已返回客户端但尚未复制。10:00:00 网络分区,10:00:08 新主完成提升,10:00:15 客户端才全部刷新地址。至少存在 8 条最近写风险和 7 秒双写窗口。若这些键只是库存展示,可从数据库流水重建;若锁资格只存在于旧历史,旧执行者和新执行者可能并发。观测信号是复制偏移、切换纪元、客户端目标地址、锁值、业务请求号和数据库提交结果。

失败注入、证据链与项目落地: E3(演练设计)隔离旧主与多数控制节点,但保留旧主到一组客户端的链路,同时让新主提升并执行 slot(槽)迁移。按实例记录角色、配置纪元、复制偏移、重定向、连接目标和命令结果。止血先冻结高风险锁与缓存写、关闭硬编码旧地址客户端,让库存预占和支付查询回到权威数据库;修复客户端发现、重连、旧主网络隔离和业务围栏。验证要求旧主写入为零、重定向错误收敛、缓存可重建、库存与支付流水无重复。机制回链 主从哨兵与集群,为 E2(既有材料映射)。

热门面试题

  1. 问题(基础题):主从、哨兵和 Cluster(集群)分别解决什么问题?
    • 考点:复制、高可用与分片边界。
    • 回答思路:按副本、自动切换和容量扩展三层回答。
    • 详细答案:主从提供数据副本和读扩展;哨兵在单主场景完成协作故障判断和自动切换;Cluster(集群)把键映射到多个 slot(槽),解决单机容量与吞吐,并对各分片做副本切换。三者都需业务处理复制延迟、最近写丢失和旧客户端。
    • 进阶追问:数据不大时是否也应直接上 Cluster(集群)?
    • 进阶回答:不一定,分片带来跨槽、迁移和运维复杂度;应由容量、吞吐和恢复时间目标驱动。
  2. 问题(原理题):哨兵完成切主后为什么仍可能丢写?
    • 考点:异步复制、确认边界与副本选择。
    • 回答思路:区分客户端成功、复制接收和新主继承。
    • 详细答案:旧主可在写只落本地时就向客户端返回,故障发生后新主最多继承自身已有偏移。即使选择最接近旧主的副本,也无法恢复从未传播出去的命令;等待副本确认可以缩小窗口,但不是跨故障域事务提交。
    • 进阶追问:读从节点能否保证刚写后立刻读到?
    • 进阶回答:不能,异步复制存在延迟;强读路径应回主或由权威存储裁决。
  3. 问题(项目题):Runner(执行器)在切主期间如何避免双执行?
    • 考点:租约回退、世代、围栏令牌与幂等副作用。
    • 回答思路:缓存锁只减少竞争,持久化状态和下游围栏拒绝旧执行者。
    • 详细答案:任务领取写入持久化任务实例号和单调世代,Redis(远程字典服务)租约只作为快速协调。执行者提交结果或调用高风险下游时携带世代,数据库条件或下游幂等记录拒绝旧世代;切主后扫描超时任务,先查原副作用再恢复。
    • 进阶追问:只延长锁过期时间能解决吗?
    • 进阶回答:不能,切主可能让锁写回退,长租约还会延长故障后的不可用时间。

5. 锁失效、续期、误删与脑裂

5.1 从租约所有权到旧持有者围栏

Redis(远程字典服务)锁本质是有期限租约,不是业务事务。安全获取要原子写入唯一所有者值和 TTL(存活时间);释放必须原子比较所有者再删除;续期只能由仍持有同一租约的执行者进行。进程暂停、网络分区、任务超时、续期线程饥饿、主从切换或人工误删都可能让旧持有者仍在运行而新持有者已获得租约,因此高风险写还要 fencing token(栅栏令牌)或持久化世代拒绝旧请求。

timeline
    title 锁失租与双执行时间线
    00:00 : 执行者甲获取租约和值甲
    00:05 : 执行者甲长暂停,续期信号消失
    00:10 : 租约到期,执行者乙获取值乙与新世代
    00:12 : 执行者乙提交带新世代的写入
    00:15 : 执行者甲恢复并尝试提交旧世代
    00:16 : 下游围栏拒绝旧世代,所有者比较阻止误删

图解读: 时间线展示租约到期并不终止旧业务线程;正常路径由新世代提交,失败路径是旧执行者恢复后继续写。前提是世代单调且下游执行条件检查,结论是续期与所有者校验只能降低冲突,真正阻止迟到副作用需要围栏。

失败模式直接原因证据链错误止血正确修复与验证
锁提前失效任务超过 TTL(存活时间)或进程暂停获取、到期、任务阶段、暂停时间盲目把过期改得极长分段任务、合理租约、续期、下游围栏
续期失败网络、调度饥饿、客户端连接或角色切换续期发送与结果、线程状态、节点角色只看任务仍运行就认为锁有效续期失败立即停止新副作用并查世代
误删他人锁读取后非原子删除或无所有者值锁值变化、删除调用、持有者时间线删除后立刻重试原子比较值后删除并故障注入
脑裂双锁两侧各自认为可写或锁写未复制拓扑、偏移、客户端目标、锁值相信任一节点返回成功旧主隔离、持久化世代、幂等和对账
锁内未知态外部调用超时但可能已成功原请求号、下游查询、任务版本换请求号重做原键查证,未决时保持未知态

数据演绎 5:TTL(存活时间)与续期窗口。 E3(演练设计)租约为 30 秒,每 10 秒尝试续期;任务第 18 秒发生 17 秒暂停,则第 20 秒和第 30 秒续期均可能错过,租约在第 30 秒到期,新执行者第 31 秒获得租约,旧执行者第 35 秒恢复,形成至少 4 秒并发窗口。把租约改成 5 分钟会降低该场景概率,却让持有者宕机后的等待最长接近 5 分钟。状态从持有、暂停、到期、新租约、旧线程恢复推进;观测信号是暂停、续期结果、锁值、世代和下游写入。

失败注入、证据链与项目落地: E3(演练设计)在库存预占和支付补偿任务中注入长暂停、续期网络丢包、主从切换、释放前延迟和外部响应丢失。固定请求号、所有者值、租约世代、任务阶段与业务事务号。止血是暂停新领取、隔离旧实例、冻结自动补偿并按原请求查证;修复使用原子获取、原子所有者释放、受预算续期、持久化世代、数据库唯一约束和下游幂等。验证要求旧世代写入为零、误删为零、库存不为负、支付不重复扣款。机制回链 分布式锁与租约,为 E2(既有材料映射)。

热门面试题

  1. 问题(基础题):为什么释放锁必须比较所有者值再删除?
    • 考点:租约过期、锁重获与误删。
    • 回答思路:用旧持有者超时后删除新持有者锁的时间线解释。
    • 详细答案:执行者甲的锁可能已过期,执行者乙已获取同名新锁;甲恢复后若直接删除,就会删除乙的租约。比较所有者值和删除必须在服务端原子执行,确保只有当前租约所有者可以释放。
    • 进阶追问:先读取再判断、随后删除为什么不行?
    • 进阶回答:判断和删除之间可能发生过期与重获,存在竞态窗口,必须使用原子脚本或等价原子命令。
  2. 问题(原理题):自动续期能否保证业务只执行一次?
    • 考点:进程暂停、网络分区、切主与副作用边界。
    • 回答思路:续期降低失租概率,但不能强制停止旧线程或回滚外部动作。
    • 详细答案:续期线程也可能暂停、失联或连接旧主;租约到期后旧业务线程仍可恢复。外部请求还可能在锁失效前已发出并形成未知态,所以业务必须有唯一请求号、持久化世代和下游幂等或围栏。
    • 进阶追问:续期失败后应立即终止线程吗?
    • 进阶回答:应停止发起新副作用并协作退出,但已发出的动作要按原请求号查证,不能假设线程终止等于业务撤销。
  3. 问题(项目题):支付补偿任务拿到锁后就能安全重扣吗?
    • 考点:支付未知态、幂等键、资金不变量。
    • 回答思路:锁只协调执行者,支付结果仍需原请求查证和唯一分录。
    • 详细答案:不能。补偿任务先以原支付请求号查询渠道与本地订单,只有明确未扣且业务允许时才推进;扣款调用复用稳定幂等键,入账由唯一分录约束。锁失效、切主或双执行都不能造成重复扣款。
    • 进阶追问:两个补偿者都查询到未支付怎么办?
    • 进阶回答:依靠支付请求唯一键、状态条件更新和渠道幂等裁决,不能只依赖查询时刻的结果。

6. 库存与支付不变量的故障闭环

6.1 从缓存加速层回到权威账本

库存不变量至少包括可用量不为负、同一预占请求只生效一次、预占/释放/扣减流水可守恒;支付不变量至少包括同一支付意图不重复扣款、每笔资金变化有唯一分录、借贷或收支平衡、未知态最终可查证。Redis(远程字典服务)缓存、限流和锁只能减少压力与竞争,不能作为这些不变量的唯一裁决者。

erDiagram
    BUSINESS_REQUEST ||--o| CACHE_ENTRY : "加速读取"
    BUSINESS_REQUEST ||--o| LEASE_RECORD : "减少竞争"
    BUSINESS_REQUEST ||--|| IDEMPOTENCY_RECORD : "唯一请求"
    IDEMPOTENCY_RECORD ||--o{ INVENTORY_LEDGER : "库存流水"
    IDEMPOTENCY_RECORD ||--o{ PAYMENT_ENTRY : "资金分录"
    INVENTORY_LEDGER }o--|| RECONCILIATION_RESULT : "守恒核对"
    PAYMENT_ENTRY }o--|| RECONCILIATION_RESULT : "平衡核对"

图解读: 缓存条目和租约记录只与业务请求形成加速或协调关系;唯一请求记录、库存流水、支付分录和对账结果才构成业务事实链。正常路径从幂等记录落到权威流水,失败路径即使缓存或租约丢失也可重建。前提是业务请求号稳定,结论是 Redis(远程字典服务)中的值不能单独证明库存或资金正确。

不变量权威证据Redis(远程字典服务)可承担Redis(远程字典服务)不得单独承担恢复验收
库存不为负数据库条件更新、库存余额与流水热点预判、展示、限流、短租约最终扣减与唯一预占事实余额非负、流水守恒、重复为零
预占只生效一次稳定请求号、唯一约束、状态条件快速去重提示跨故障域唯一性重放同请求只产生一条有效流水
支付不重复扣款支付意图、渠道请求号、渠道结果查询缓存、短期幂等加速渠道结果与扣款事实原请求查证、重复扣款为零
账务平衡不可变分录、账户余额、对账结果聚合读模型分录生成与余额唯一事实分录唯一、收支平衡、差异闭环
未知态可收敛原请求号、查询记录、补偿状态限流与任务协调直接把超时判失败未知年龄归零且无重复副作用

数据演绎 6:缓存预扣为什么不能证明库存正确。 E3(演练设计)数据库可用库存为 100,同一请求因客户端重试到达两次,每次数量 30。若仅在缓存执行两次预扣,缓存变为 40;随后主从切换丢失第二次写,缓存回到 70,既无法证明真实扣了几次,也可能再次放行。正确路径以请求号唯一,数据库执行一次 100 - 30 = 70 并写一条预占流水;第二次重试命中同一结果。缓存无论显示 40、70 或缺失,都从余额和流水重建。支付同理:一次超时不能触发新请求号重扣,必须查询原请求并核对唯一分录。

失败注入、证据链与项目落地: E3(演练设计)组合注入缓存过期、锁失租、主从切换、数据库响应丢失和渠道支付超时。统一记录租户、仓库、SKU(库存单位)、订单号、支付意图、请求号、锁世代和事务结果。止血先关闭自动重试和高风险补偿,保留查询与对账通道;修复让数据库条件、唯一流水、渠道幂等和不可变分录承担裁决,缓存按版本重建。验证同时覆盖技术信号与业务守恒:库存非负、重复预占为零、支付不重复扣款、分录平衡、未知态清零。项目回链 库存与支付项目案例支付资金一致性,均为 E2(既有材料映射);生产事故结果为 E0(待核对)。

热门面试题

  1. 问题(基础题):为什么缓存和分布式锁都不能保证库存绝不超卖?
    • 考点:加速层、租约边界与权威写入。
    • 回答思路:说明缓存可回退、锁可失租,最终由数据库条件和流水裁决。
    • 详细答案:缓存可能过期、淘汰、切主回退;锁可能超时、续期失败或脑裂。即使它们工作正常,也只减少并发冲突。库存扣减必须在共享权威存储执行非负条件更新,并用稳定请求号和唯一流水防重复。
    • 进阶追问:数据库条件更新成功但响应丢失怎么办?
    • 进阶回答:保持未知态,以原请求号查询流水和余额,不能换请求号再次扣减。
  2. 问题(原理题):支付超时为什么不能直接标记失败?
    • 考点:通信结果与业务结果分离、未知态和查证。
    • 回答思路:超时只说明没有及时收到响应,不证明渠道未执行。
    • 详细答案:请求可能已被渠道受理甚至扣款,只是响应丢失。应保留原支付请求号,主动查询或等待可靠回调,并由支付订单、渠道结果和唯一账务分录收敛;直接重扣会破坏不重复扣款不变量。
    • 进阶追问:Redis(远程字典服务)幂等键还在能否判定已扣?
    • 进阶回答:不能,它只能提示请求曾被处理,最终仍要查渠道和账务事实。
  3. 问题(项目题):怎样证明缓存故障已经真正恢复?
    • 考点:技术恢复、业务恢复、历史差异和复盘。
    • 回答思路:从新流量、存量未知态、权威账本和故障再现四层验收。
    • 详细答案:新流量要满足命中、回源、延迟和错误预算;存量键按版本重建且不覆盖新值;库存与支付分别通过流水守恒、分录平衡和对账;最后重复原故障注入并逐步放量,确认无回源反弹和重复副作用。
    • 进阶追问:命中率恢复就能宣布结束吗?
    • 进阶回答:不能,历史重复、丢失、未知请求和账务差异可能仍未收敛。

7. 综合口述题

纯口述统计口径: 每题只统计 **口述答案** 字段冒号后的第一个字符,到第一处 **追问 1** 之前的全部非空白有效字符;不把题干、六字段短答案、追问、直接回答和详情链接计入。硬性范围为 570—900 个有效字符,每题配置 4 组追问直答。

  1. 问题:商品查询遭遇大量随机不存在编号,怎样从缓存穿透走到完整事故闭环?

    • 考点:恶意与误流量区分、负缓存、过滤器、数据库保护。
    • 回答思路:固定来源和业务键,证明不存在键持续回源,再按可回滚顺序止血。
    • 详细答案:穿透不是“命中率低”的同义词,必须证明请求集中在不存在键并持续到达权威存储;过滤与负缓存只能降低回源,合法新数据仍需可见。
    • 进阶追问:布隆类过滤结构能否保证没有误判?
    • 进阶回答:不能,它可能把不存在判断成可能存在,但不应把真实存在判断成不存在;业务仍需参数校验和权威查询兜底。
    • 口述答案:我先把现象定义为“高比例不存在商品号持续绕过缓存并访问数据库”,而不是看到命中率下降就定性。固定租户、客户端版本、来源地址、商品号、键版本和时间窗,按每键请求数关联缓存结果、数据库空结果、接口延迟与连接池等待。假设一是外部枚举随机编号,证据是来源集中、编号分布离散且长期无对应记录;假设二是新旧键前缀切换,证据是同一真实商品在旧键命中、新键缺失;假设三是批量任务参数错误,证据是某版本上线后规则化地产生无效编号。止血先做格式和权限校验,按来源及租户限流,对确定不存在的键写短期负缓存,并为数据库保留库存和支付核心连接;不能用永久空值封死未来新增商品。若过滤器可用,只把它作为前置概率判断,过滤器异常时必须可旁路。修复统一键生成、负缓存失效和新数据发布顺序,给批量入口设置请求预算。验证要重放合法存在、合法新建、随机不存在和热点混合流量,确认回源率低于数据库能力、合法数据不被误挡、负缓存能在创建后及时失效。复盘记录无效键比例、来源基数、数据库空查率、规则变更和演练门禁。机制属于 E2(既有材料映射),所有量级是 E3(演练设计),真实攻击与损失保持 E0(待核对)。 退出降级时我会先放开内部与低风险租户,比较限流组和对照组的空查、延迟与误伤,再逐级恢复外部流量;任何一批出现数据库等待反弹就立即回退。事故结论必须能落到具体来源、版本和证据,不把“疑似攻击”写成未经核对的生产事实。
    • 追问 1:负缓存过期设得越长越好吗? 直接回答:不是,越长越可能遮蔽新建数据,应按创建频率和风险设置并支持主动失效。
    • 追问 2:数据库空结果能证明是攻击吗? 直接回答:不能,也可能是客户端缺陷或键迁移错误,要看来源、版本和分布。
    • 追问 3:过滤器重建期间怎么办? 直接回答:双版本构建并灰度切换,异常时旁路到受限权威查询。
    • 追问 4:恢复只看命中率吗? 直接回答:还要看空查率、数据库等待、合法新数据可见性和限流误伤。
    • 对应详细章节:缓存模式与一致性
  2. 问题:热点库存键过期后数据库连接瞬间耗尽,怎样证明是缓存击穿并安全恢复?

    • 考点:单键集中、合并回源、旧值兜底、库存事实。
    • 回答思路:用热点键和失效时点对齐回源尖峰,先保护数据库再修复加载协议。
    • 详细答案:击穿的关键证据是存在的热点键在过期或被删后形成并发回源;库存展示可短时陈旧,真实预占仍由数据库条件和流水裁决。
    • 进阶追问:给热点键设置永不过期是否最简单?
    • 进阶回答:会引入永久陈旧和人工失效风险,应采用逻辑过期、主动刷新或带版本旧值并保留最大陈旧边界。
    • 口述答案:我先固定仓库、SKU(库存单位)、缓存键版本和失效秒点,把该键每秒请求数、命中状态、回源并发、数据库连接等待与库存条件更新放在同一时间轴。若故障只集中在一个原本存在的热点键,并在过期后从一次加载放大成多实例并发查询,就支持击穿假设;若大量键同时失效则转查雪崩,若键长期不存在则转查穿透。止血先按热点键限流并合并回源,给展示接口返回带版本且有最大陈旧时间的旧值,暂停非关键预热,为库存预占保留数据库连接;绝不能因为缓存显示有货就跳过 available >= quantity 条件更新。修复时让每个稳定业务键在一个加载周期只有受预算的加载者,等待者有限等待、读旧值或明确降级;加载失败不应立即删除旧值并唤醒所有请求重试。多实例场景还要限制全局加载并发,设置过期抖动和主动刷新。验证注入加载慢、加载失败、执行者暂停和键被删,要求数据库回源峰值受控、等待者不无界堆积、旧值在新值成功后退出,同时库存余额非负、预占流水唯一、失败请求结果明确。复盘补充热点识别、加载耗时、旧值年龄、回源放大倍数和自动降级阈值。方案为 E2(既有材料映射),注入参数为 E3(演练设计),真实收益为 E0(待核对)。 为避免修复动作本身制造第二次尖峰,我会把缓存重建和线上自然回填共用同一回源预算,并观察等待者年龄而非只看队列长度。退出旧值兜底前还要抽样比较数据库版本、缓存版本与返回内容,确保性能恢复没有以陈旧库存展示换取。
    • 追问 1:本地互斥能否解决多实例击穿? 直接回答:只能约束单实例,多实例仍可能同时回源,需要全局预算或分层合并。
    • 追问 2:加载者超时后等待者都重试吗? 直接回答:不能齐发,应退避、读旧值或按预算选出下一加载者。
    • 追问 3:旧值会不会掩盖库存变化? 直接回答:展示可能短时陈旧,所以预占必须查权威条件,旧值还要有版本和最大年龄。
    • 追问 4:怎样宣布恢复? 直接回答:回源和数据库等待稳定、旧值退出,并且库存流水和未知请求共同收敛。
    • 对应详细章节:缓存模式与一致性
  3. 问题:一次批量发布后大量缓存同步失效,如何处理雪崩而不造成二次预热风暴?

    • 考点:失效分布、全局回源预算、分级降级、恢复放量。
    • 回答思路:确认面状失效和变更相关性,先限制总回源,再分批重建。
    • 详细答案:雪崩可能来自同步过期、节点故障或键版本整体切换;预热必须受数据库容量约束,否则修复动作会复制原故障。
    • 进阶追问:给 TTL(存活时间)加随机值就能根治吗?
    • 进阶回答:只能降低同步过期,无法解决节点故障、依赖变慢、批量删除和无预算预热。
    • 口述答案:我会先把发布时间、键版本、过期分布、节点事件和数据库压力对齐,证明这是大量键在同一窗口失效,而不是单热点击穿或指标口径变化。证据包括每分钟前后缀键数量、剩余 TTL(存活时间)分布、每分片命中率、回源请求率、数据库连接等待、慢查询和客户端重试。止血第一目标是让总回源低于权威存储稳定能力:按业务优先级限流,商品展示可返回短时旧值或降级摘要,暂停报表、全量预热和自动重试,库存预占与支付查询保留独立资源。若新键版本有缺陷,优先回退键路由而不是继续填充错误版本。修复采用随机过期、主动刷新、分批发布和带总预算的预热队列;每批先校验内容与版本,再扩大范围,失败立即暂停。预热读取数据库时要分页、有并发上限、可从检查点恢复,不能在缓存为空时由线上请求无限接管重建。验证重放节点失效、批量删除和发布切换,要求命中率平滑恢复、回源无第二峰、数据库尾延迟与连接余量达标;再核对库存非负、支付未知态清零和缓存版本一致。复盘记录变更审批、过期分布检测、预热容量公式、退出降级门禁和负责人。量级属于 E3(演练设计),生产原因与影响属于 E0(待核对)。 放量采用固定批次和观察窗口,每批都比较缓存填充速度、数据库有效完成率、失败重试与业务错误;若总请求下降但单次回源成本上升,同样不能继续。事故关闭前还要确认临时限流、旧值和旁路开关均有明确退出时间,避免应急方案永久化。
    • 追问 1:先扩数据库再预热可以吗? 直接回答:扩容可争取余量,但预热仍必须限速,否则会把瓶颈推到磁盘、锁或网络。
    • 追问 2:命中率达到 95% 就全量放开吗? 直接回答:不能,还要看回源分布、数据库余量和业务不变量。
    • 追问 3:缓存节点恢复后是否自动拥有全部热数据? 直接回答:不会,冷节点需要受控预热或自然回填,突然接全量会再次抖动。
    • 追问 4:怎样避免发布切键造成雪崩? 直接回答:双读或小流量验证新版本,分批迁移并保留快速回退路由。
    • 对应详细章节:缓存模式与一致性
  4. 问题:大促期间单个 SKU(库存单位)读流量压垮一个分片,如何治理 hot key(热键)?

    • 考点:单分片倾斜、本地副本、请求合并、库存正确性。
    • 回答思路:证明压力按键集中,再分读路径和写路径治理。
    • 详细答案:hot key(热键)可能让集群总负载不高却单分片饱和;读可复制与合并,写仍需权威条件和稳定顺序。
    • 进阶追问:把同一个键复制成十个随机键是否可行?
    • 进阶回答:读副本可分摊,但写入、失效和版本一致性成本会上升,必须有单一发布版本和回收策略。
    • 口述答案:我先确认问题是否真按仓库与 SKU(库存单位)集中:统计每键请求数、响应字节、所在 slot(槽)、节点网络、事件循环延迟、客户端连接和数据库回源。若一个键占据大部分读取,而其他分片健康,就支持 hot key(热键)假设;还要检查值是否同时很大,避免漏掉热键与大键叠加。止血先对该键做请求合并和分层限流,商品展示可使用带版本的进程内短缓存或只读副本,暂停非关键刷新;库存预占不能读本地副本后直接扣减,仍由数据库非负条件和唯一流水裁决。修复把读模型改为小型版本摘要加本地不可变快照,主动刷新时只允许少量加载者,并按租户设置公平预算;若业务可自然分区,再按仓库或活动维度拆读键,但不能通过随机后缀破坏同一事实的版本管理。写路径继续保持稳定业务键、幂等请求号与权威提交。验证使用相同热点分布,而不是均匀压测,注入本地快照失效、刷新失败和节点切换,要求单分片带宽及延迟回落、刷新无齐发、其他键不受牵连,并核对缓存版本、库存余额和流水。复盘建立热点提前识别、单键字节率、自动降级阈值和活动容量演练。机制为 E2(既有材料映射),压测数据为 E3(演练设计),真实峰值为 E0(待核对)。 我还会审查热点治理后的成本转移:进程内副本会随实例数放大内存,版本广播可能丢失,只读副本可能陈旧,拆键会增加聚合复杂度。因此验收同时测总内存、刷新失败、最大陈旧时间和扩容冷启动,不能只展示远程请求数下降。
    • 追问 1:读从节点能彻底解决热键吗? 直接回答:不能,仍有网络和副本延迟,还会增加陈旧读风险。
    • 追问 2:本地缓存多久合适? 直接回答:由业务可接受陈旧时间、刷新能力和故障边界共同决定,不能凭经验固定。
    • 追问 3:热点写能否也随机拆键? 直接回答:只有可交换聚合场景适合,库存扣减这类强不变量不能简单随机拆散。
    • 追问 4:平均节点负载正常为何还告警? 直接回答:平均值掩盖单 slot(槽)和单节点倾斜,应看高位分片与每键分布。
    • 对应详细章节:内存淘汰与热键大键治理
  5. 问题:一个百万成员集合导致超时和复制积压,怎样排查并拆解 big key(大键)?

    • 考点:成员规模、单命令成本、异步删除、迁移正确性。
    • 回答思路:先禁全量操作和保现场,再以版本化分片迁移并校验守恒。
    • 详细答案:big key(大键)影响执行、网络、释放、复制和持久化;拆键不能只搬数据,还要处理双读、写入路由与历史清理。
    • 进阶追问:直接在低峰执行删除是否足够?
    • 进阶回答:低峰降低影响但不能消除长阻塞、后台释放和复制成本,仍需分批及监控。
    • 口述答案:我会先固定键名、类型、编码后大小、成员数、所在分片和命令时间窗,关联慢命令、节点延迟、网络字节、复制积压、持久化重写和客户端超时,证明不是普通热键或全局网络故障。止血立即关闭全量读取、全量返回和同步删除入口,按游标分页读取并限制并发;若该键用于 IoT(物联网)规则或报警去重,继续使用最后校验快照,同时把原始事件持久化,避免为了保护缓存而丢报警。修复先设计稳定分片键和版本,例如按租户、规则与时间窗口拆分,迁移期间采用新写入只进新结构、旧数据分批复制、读取按版本受控双读;每批记录成员数、唯一标识摘要和游标检查点。确认新结构完整且所有客户端切换后,再把旧键逻辑下线并用惰性、分批方式释放,观察后台队列和复制压力。验证要覆盖最大成员、删除、节点切换、迁移中断和重复执行,要求 旧结构唯一成员 = 新分片唯一成员并集,无漏项和重复副作用,节点尾延迟、复制偏移与持久化时长恢复。复盘增加键大小门禁、写入增长速率、危险命令审计和迁移回退方案。机制为 E2(既有材料映射),百万规模及阈值为 E3(演练设计),生产影响为 E0(待核对)。 历史清理设置可暂停的检查点,每次释放前确认新读路径已覆盖该分片,释放后观察常驻内存、后台释放队列和副本差;若出现延迟反弹就停止下一批。最终复盘还要追到大键为何能持续增长,包括缺少成员上限、生命周期、分页契约或数据模型评审,并明确整改负责人。
    • 追问 1:扫描命令是否绝对不会阻塞? 直接回答:不是,单次返回量和集合内部工作仍有成本,要控制批量并观察延迟。
    • 追问 2:惰性删除后内存会立即下降吗? 直接回答:不会,实际释放在后台进行,短期仍占内存并消耗资源。
    • 追问 3:迁移双读会不会放大压力? 直接回答:会,所以必须限并发、分批客户端切换并设置退出条件。
    • 追问 4:成员数量相等就代表迁移正确吗? 直接回答:不代表,还要比较稳定标识集合、摘要、版本和业务结果。
    • 对应详细章节:内存淘汰与热键大键治理
  6. 问题:节点故障后只剩较旧 RDB(快照持久化),怎样恢复缓存并证明没有破坏业务事实?

    • 考点:恢复点、隔离加载、缓存重建、库存支付对账。
    • 回答思路:先保护原文件和确定恢复窗口,再区分可再生缓存与不可丢业务事实。
    • 详细答案:RDB(快照持久化)只代表快照时点,加载成功不代表故障点状态完整;缓存应从权威存储按版本重建。
    • 进阶追问:快照键数量与故障前接近能否直接放量?
    • 进阶回答:不能,数量接近可能仍有关键键回退或内容错误,还需版本、摘要和业务账本对照。
    • 口述答案:我先冻结自动重启和写入,复制原 RDB(快照持久化)文件、配置与摘要,记录快照生成时间、故障时间、节点角色、复制偏移和业务变更窗口。第一步不是直接覆盖生产,而是在相同版本的隔离实例校验并加载,统计键空间、过期分布、版本和抽样内容。然后把数据分成两类:商品、库存展示、限流窗口等可从数据库或事件位点重建的读模型,只把快照当加速基线;支付结果、库存预占、任务完成等若发现只存在 Redis(远程字典服务),立即按高风险设计缺陷处理,不能用快照猜最终事实。止血期间展示接口可降级或返回带时间的旧值,库存预占继续使用数据库条件与唯一流水,支付查询回到账务和渠道,关闭基于回退缓存的自动补偿。修复以权威记录版本为准分批回填,采用写入新前缀、校验后切流,避免旧数据覆盖故障后的新状态。验证比较快照、权威库和重建结果的稳定业务键、版本与摘要,重放快照后新增、更新、删除和过期事件;库存要求余额非负且流水守恒,支付要求分录唯一、收支平衡、未知态逐笔查证。复盘记录恢复点目标、备份新鲜度、隔离恢复时长、重建容量和季度演练。恢复方法为 E2(既有材料映射),窗口与样本为 E3(演练设计),真实丢失范围为 E0(待核对)。 切流过程必须记录每一批键前缀、版本、开始结束时间和回退点,重建失败时删除的是未发布的新前缀,而不是覆盖权威数据。恢复完成后继续观察一个完整过期周期,确认批量过期、冷启动和自然回填没有再次打穿数据库,才撤销事故状态。
    • 追问 1:能否先加载快照再慢慢对账? 直接回答:低风险只读可灰度,但高风险写和自动补偿必须等权威事实核对后开放。
    • 追问 2:过期键恢复后会怎样? 直接回答:取决于快照中保存的过期时间和当前时钟,仍要核对批量过期是否造成雪崩。
    • 追问 3:快照越频繁越好吗? 直接回答:会缩小窗口,但增加写时复制、磁盘和运行抖动,应按目标与压测权衡。
    • 追问 4:怎样证明恢复可重复? 直接回答:保留脚本、输入摘要和验收结果,在隔离环境从同一备份再次完整演练。
    • 对应详细章节:持久化复制与恢复
  7. 问题:AOF(追加日志)尾部损坏且磁盘接近写满,怎样止血、修复和验证?

    • 考点:证据保护、命令边界、磁盘风险、隔离恢复。
    • 回答思路:停止扩大损坏,复制文件后修复副本,并用业务账本验证恢复点。
    • 详细答案:格式修复成功只表示日志可加载,不能证明尾部业务写完整;磁盘写满还可能影响重写、复制和日志保存。
    • 进阶追问:能否直接在原 AOF(追加日志)上执行修复工具?
    • 进阶回答:不应,原文件是唯一现场,应先只读复制、计算摘要并在副本上操作。
    • 口述答案:我先停止该节点接收新写并防止自动重写覆盖现场,记录磁盘使用、文件大小、最后刷盘时间、重写状态、节点角色和复制偏移,随后对原 AOF(追加日志)做只读副本与摘要。若有健康且更新的副本,先评估从副本重建;若必须修复日志,则在相同版本隔离环境检查最后有效命令边界,明确会截掉多少字节、覆盖哪个时间窗,再对副本执行修复。止血期间清理磁盘只能处理已确认可删的临时文件,不能删除持久化、业务审计或根因日志;同时让库存展示和支付查询回到权威库,冻结自动重试与补偿,防止缓存回退触发重复副作用。修复后先隔离加载,比较键数量、过期分布、重点业务键版本与复制偏移,再按数据库记录或事件位点重建可再生读模型。验证要注入尾部半条命令、刷盘延迟、重写切换和磁盘再次逼近阈值,确认节点不会带病接流量、告警在写失败前触发、重写有空间预算。业务验收仍是库存余额与流水守恒、支付订单与渠道及唯一分录一致、未知请求逐笔收敛。复盘补充磁盘增长预测、重写峰值预算、备份恢复和人工操作审批。机制为 E2(既有材料映射),故障注入为 E3(演练设计),真实截断范围为 E0(待核对)。 人工处置要形成可复核记录:谁在何时基于哪个文件摘要执行了什么命令、截断到哪个偏移、隔离加载结果如何、由谁批准切流。这样后续发现遗漏时仍能回到原文件重演,而不是只剩一个已经修改且来源不清的恢复文件,并持续保存审批证据。
    • 追问 1:修复工具退出码为零代表什么? 直接回答:只代表格式处理成功,不代表所有业务命令和最终事实完整。
    • 追问 2:为什么重写时更怕磁盘满? 直接回答:新旧文件可能同时存在并持续接收增量,需要额外峰值空间。
    • 追问 3:有从节点就一定不用 AOF(追加日志)吗? 直接回答:不一定,从节点可能同样落后或受同一故障域影响,需按恢复目标设计。
    • 追问 4:恢复后先开读还是先开写? 直接回答:通常先灰度低风险读并核验,写路径须等拓扑和业务事实确认。
    • 对应详细章节:持久化复制与恢复
  8. 问题:主节点宕机后新主缺少最近写,如何建立复制丢失证据链并恢复业务?

    • 考点:异步复制、偏移量、确认边界、业务重建。
    • 回答思路:用旧主、候选副本和客户端成功记录比较偏移,再回到权威账本。
    • 详细答案:选择最新副本只能减少丢失,不能恢复未传播写;客户端成功、复制接收和新主继承是不同事实。
    • 进阶追问:使用等待副本确认是否等于强一致提交?
    • 进阶回答:不等于,它可缩小单主确认窗口,但仍受超时、故障域、选主和持久化边界影响。
    • 口述答案:我先固定切换前后拓扑、配置纪元、旧主最后可见复制偏移、各从节点偏移、客户端请求号和返回时间,画出“旧主执行、返回客户端、复制发送、副本接收、新主提升”的时间线。若客户端已收到成功而所有候选副本偏移都停在该命令之前,就能证明最近写没有进入新历史;若副本已接收但新主选择了更旧节点,则继续查候选优先级、断连时间和选主日志。止血先冻结依赖缓存锁和缓存状态的自动副作用,让库存、支付和任务状态回到权威数据库查询;旧主若仍可访问,先隔离网络和只读取证,不能重新接入写流量制造分叉。修复客户端发现与重连、合理的副本写保护和等待确认策略,但明确这些措施只能缩小窗口。可再生缓存按数据库版本或事件位点重建;丢失的租约不能直接补回,任务应按持久化世代扫描并查原副作用。验证注入主进程终止、复制延迟和候选副本落后,要求切换时间达标、客户端停止写旧主、偏移差可解释;业务侧库存流水唯一、支付不重复扣款、过期任务旧世代写入为零。复盘记录恢复点目标、复制延迟高位、选主理由、客户端地址刷新和故障演练。机制为 E2(既有材料映射),注入与阈值为 E3(演练设计),真实丢写为 E0(待核对)。 恢复放量按缓存读、低风险写和高风险协调分层进行,先证明客户端拓扑稳定,再开放依赖租约的任务。每层都有偏移差、错误率、旧地址连接和业务差异门槛;任何旧主写入或未知请求增长都触发回退,避免把快速切换误当完整恢复。
    • 追问 1:新主缺键能否从旧主复制回来? 直接回答:不能直接合并两条分叉历史,应先按业务权威源重建并审计差异。
    • 追问 2:从节点越多丢写概率越低吗? 直接回答:可能增加副本机会,但不能替代确认协议和故障域设计,还会增加成本。
    • 追问 3:读从节点在切换前后有什么风险? 直接回答:复制延迟会读到旧值,强读路径应回主或权威库。
    • 追问 4:缓存丢写是否可以忽略? 直接回答:只有确认它可再生且不承担业务事实后才可按重建处理。
    • 对应详细章节:主从哨兵与集群
  9. 问题:哨兵切主期间旧主仍接受部分客户端写,怎样处理脑裂?

    • 考点:控制面多数、数据面旧连接、分叉写、围栏与对账。
    • 回答思路:证明两个写入口并存,先隔离旧主和高风险写,再按权威事实收敛。
    • 详细答案:新主选出不代表旧连接立刻消失;脑裂窗口中的两条历史不能靠简单同步自动合并。
    • 进阶追问:客户端使用哨兵发现就能完全避免脑裂吗?
    • 进阶回答:不能,长连接、暂停、单向网络和刷新延迟仍可能让旧主短时接收写。
    • 口述答案:我先固定网络分区时间、主客观下线判断、配置纪元、领导者投票、新主提升时间和每个客户端实际连接地址,再比较旧主与新主的命令、复制偏移和业务请求号。脑裂成立需要证明多数控制面已经产生新主,同时旧主仍能服务隔离区客户端并形成不同写历史,不能只凭“两个节点都在线”下结论。止血优先在网络、代理和客户端三层隔离旧主,冻结依赖租约资格的 Runner(执行器)任务及支付补偿,库存展示可降级,但库存预占仍走数据库条件与唯一流水。保留旧主只读现场和命令摘要,不允许直接把旧主重新提升或双向合并。修复客户端地址发现、断线重连、角色校验和副本不足拒写,并让高风险业务提交携带持久化世代或 fencing token(栅栏令牌),下游拒绝旧世代。恢复时按权威数据库和事件位点重建缓存,对脑裂窗口所有库存、支付与任务请求逐笔对账,未知态使用原请求号查询。验证重复注入旧主与多数派隔离、客户端暂停和网络恢复,要求旧主写入迅速归零、旧世代提交被拒、新主稳定且业务差异收敛。复盘记录隔离耗时、硬编码地址、投票布局、拒写策略和季度演练。方案为 E2(既有材料映射),演练窗口为 E3(演练设计),真实脑裂影响为 E0(待核对)。 脑裂窗口内每一笔请求都按“旧主记录、新主记录、权威库结果、外部副作用”建立差异单,自动修复只处理结论唯一的可再生缓存;涉及库存、资金或任务未知态的记录必须走原请求查证和审批补偿。关闭事故前复核差异单数量为零并保存演练证据。
    • 追问 1:网络恢复后旧主会自动合并写吗? 直接回答:通常会降为从节点并接受新主历史,其分叉写可能被丢弃,不会自动业务合并。
    • 追问 2:把超时调得更短能减少窗口吗? 直接回答:可能加快发现,也会放大短抖动误切换,必须按故障域压测。
    • 追问 3:旧主拒写配置是否足够? 直接回答:能缩小风险,但不能覆盖所有旧连接和历史副作用,业务仍需围栏。
    • 追问 4:如何处理脑裂期间支付缓存差异? 直接回答:以支付订单、渠道结果和唯一分录为准,幂等重建两侧缓存。
    • 对应详细章节:主从哨兵与集群
  10. 问题:Cluster(集群)迁槽期间重定向、超时与重复写同时出现,如何安全收敛?

  • 考点:slot(槽)迁移、客户端拓扑、临时重定向、幂等写。
  • 回答思路:区分路由错误、迁移中状态和业务未知态,先冻结扩迁再逐项裁决。
  • 详细答案:迁槽会让源节点、目标节点和客户端缓存短时不一致;超时不等于写失败,重试必须复用稳定请求号。
  • 进阶追问:客户端刷新全部槽位就能避免重复写吗?
  • 进阶回答:不能,首个写可能已成功但响应丢失,拓扑刷新只修路由,不裁决业务结果。
  • 口述答案:我先固定迁移批次、slot(槽)范围、源与目标节点、集群配置纪元、客户端版本和业务请求号,关联重定向响应、超时、重试、键实际位置与数据库结果。假设一是客户端槽位缓存过旧,持续访问源节点;假设二是键处于迁移中,临时重定向未被客户端正确处理;假设三是首次写已在目标节点成功但响应丢失,调用方换请求号重试造成重复副作用;假设四是多键操作跨槽,应用错误地把部分成功当整体失败。止血先暂停新的迁槽和扩容批次,限制重试与热点流量,升级或旁路不支持正确重定向的客户端;库存和支付高风险写回到数据库条件、唯一流水与渠道幂等,不让缓存路由错误决定业务结果。修复前先核对每个槽的唯一归属、键迁移状态和集群一致视图,再小批继续;键模型使用稳定哈希标签只解决必要的同槽操作,不能滥用成新热点。验证注入迁移中断、客户端拓扑陈旧、响应丢失和源节点故障,要求重定向与超时收敛、槽无双重归属、键数量和摘要守恒、业务重复为零。复盘记录迁移门禁、客户端兼容矩阵、每批容量、回退条件和全链路幂等。机制为 E2(既有材料映射),批次与故障为 E3(演练设计),真实重复写为 E0(待核对)。 迁移完成后我还会从客户端视角验证:滚动重启不同版本实例,确认槽位刷新、有限重试和连接回收一致;随后从服务端核对无遗留迁移状态、槽全覆盖和副本健康。只有客户端与服务端视图同时收敛,且业务对账无差异,才结束变更。
  • 追问 1:为什么多键操作会失败? 直接回答:Cluster(集群)按 slot(槽)分片,多键若不在同槽就无法由单节点原子执行。
  • 追问 2:哈希标签用得越多越好吗? 直接回答:不是,过度同槽会制造分片热点和容量失衡。
  • 追问 3:迁槽时能否持续全量压测? 直接回答:应受预算、小批执行并保留回退,避免压测掩盖迁移故障。
  • 追问 4:键数守恒是否足够? 直接回答:不够,还要校验稳定键集合、值版本、摘要和业务副作用。
  • 对应详细章节:主从哨兵与集群
  1. 问题:库存预占任务超过锁 TTL(存活时间),两个执行者同时运行,怎样止血和根治?
  • 考点:租约失效、旧持有者存活、围栏世代、库存条件更新。
  • 回答思路:还原获取、到期、重获和提交时间线,用下游条件拒绝旧执行者。
  • 详细答案:锁到期只删除协调资格,不会终止旧线程;加长 TTL(存活时间)只能改变窗口,不能替代围栏与幂等。
  • 进阶追问:发现双执行后能否先删除锁再重跑?
  • 进阶回答:不能,删除可能扩大并发,还要先查询两边已产生的库存流水和事务结果。
  • 口述答案:我先固定租户、仓库、SKU(库存单位)、预占请求号、两个执行者标识、锁值、获取时间、TTL(存活时间)、任务阶段和数据库事务结果,画出甲持锁、任务变慢、租约到期、乙重获、甲恢复提交的时间线。证据要同时包含 Redis(远程字典服务)键事件或客户端日志、进程暂停、续期结果、数据库条件更新行数和唯一预占流水,避免只看到两个线程就猜锁失效。止血先停止该热点键的新领取和自动重试,隔离旧执行实例,冻结未知请求的后续发货或扣减;按原预占请求号查询流水,已经成功的不能再执行,未知的保持待查。修复把长任务拆成可检查阶段,锁只做前置协调;每次领取生成持久化单调世代,提交库存时携带请求号和世代,由数据库执行 available >= quantity 条件更新及唯一流水,旧世代即使恢复也写不进去。租约时长与续期周期根据暂停高位和任务阶段压测,但续期失败必须停止新副作用。验证注入长暂停、数据库慢、响应丢失和锁重获,要求两个执行者可以同时存活但最多一个业务提交成功,库存始终非负、同请求流水唯一、未知态最终清零。复盘记录任务时长分布、失租率、旧世代拒绝数和演练门禁。机制为 E2(既有材料映射),时长与注入为 E3(演练设计),真实超卖影响为 E0(待核对)。 业务侧恢复不是把锁重新建立即可,还要处理双执行窗口里已经发出的请求、锁外计算和迟到提交。我会生成受影响请求清单,逐条标记成功、失败或未知,成功的不重做,失败的按原键重试,未知的先查证;这样止血和历史修复属于同一闭环。
  • 追问 1:把 TTL(存活时间)设为任务最大时长可以吗? 直接回答:最大时长可能无界或受故障放大,长租约还会拖慢持有者宕机后的恢复。
  • 追问 2:数据库条件更新为何还需唯一流水? 直接回答:条件保证非负,唯一流水保证同一请求不重复生效并可审计。
  • 追问 3:旧执行者怎样感知被围栏? 直接回答:提交返回世代不匹配后立即停止,并按原请求查询已发生副作用。
  • 追问 4:锁服务恢复是否代表库存恢复? 直接回答:不代表,还要核对余额、流水、未知请求和发货状态。
  • 对应详细章节:分布式锁与租约
  1. 问题:自动续期线程被暂停,锁失效后业务线程恢复,如何证明续期失败并安全退出?
  • 考点:续期调度、进程暂停、租约所有权、协作取消。
  • 回答思路:区分续期未发送、发送失败和写到旧主,并追踪业务线程的迟到副作用。
  • 详细答案:业务线程仍运行不能证明租约仍有效;续期失败后要停止新副作用,已发出请求则按原键查证。
  • 进阶追问:续期日志缺失能直接证明进程暂停吗?
  • 进阶回答:不能,也可能是线程池饥饿、连接故障或日志丢失,要结合运行时暂停、调度延迟和节点角色。
  • 口述答案:我先固定锁名、所有者值、续期计划时间、实际发送与返回、节点角色、进程暂停和业务线程阶段,构造每个续期周期的证据。假设一是整个进程长暂停,续期与业务都停止;假设二是续期共用拥塞线程池而饥饿,业务仍在推进;假设三是网络分区让续期写到旧主或超时;假设四是客户端错误地把续期异常吞掉。止血要求一旦无法确认仍持有同一租约,业务线程停止发起新的库存、支付或外部副作用,保存检查点并进入待查;不能简单强杀后假设业务未发生,因为请求可能已经到达下游。对已发出动作复用原请求号查询,对旧世代提交由数据库或下游围栏拒绝。修复把续期调度与业务线程隔离,原子校验所有者后续期,设置连续失败预算和租约剩余时间门槛;长任务分段,并在每个不可逆动作前再次检查持久化世代。验证分别注入进程暂停、续期池耗尽、连接断开、切主和响应丢失,要求续期状态可观测、失租后不再产生新副作用、旧请求可查证、接替者能从可信检查点继续。复盘增加调度延迟、剩余租期、续期失败、旧世代拒绝和未知态年龄告警。机制为 E2(既有材料映射),注入窗口为 E3(演练设计),生产采用情况为 E0(待核对)。 退出待查状态需要三个条件同时成立:新世代接替者已经稳定、旧执行者确认停止或所有下游均能拒绝旧世代、历史外部请求均有确定结果。若只能证明线程退出,却无法证明渠道或数据库结果,仍不能清除未知态,更不能自动补发。
  • 追问 1:续期线程独立后就绝对安全吗? 直接回答:不绝对,整个进程暂停、网络和主从切换仍可让续期失败。
  • 追问 2:续期频率越高越好吗? 直接回答:过高会增加服务和网络压力,应给故障检测留余量并经压测确定。
  • 追问 3:失租后能否立即释放锁? 直接回答:若已不是所有者就无权释放,只能停止业务并让原子所有者校验保护新锁。
  • 追问 4:怎样验证协作退出? 直接回答:看失租后新增副作用为零、检查点完整、旧世代提交被拒和接替成功。
  • 对应详细章节:分布式锁与租约
  1. 问题:旧持有者误删新持有者的锁,又叠加主从切换,如何建立完整证据链?
  • 考点:所有者值、原子释放、切换回退、双执行与历史修复。
  • 回答思路:串起锁值世代、释放调用、拓扑偏移和业务提交,先阻断新副作用。
  • 详细答案:读取后删除存在竞态,切主还可能回退锁状态;必须用原子所有者释放与业务围栏双层防护。
  • 进阶追问:锁已经不存在还能证明是谁误删的吗?
  • 进阶回答:需依靠客户端请求日志、所有者值、命令审计、切换时间和业务世代交叉推断,证据不足则降为 E0(待核对)。
  • 口述答案:我先固定锁名、甲乙两个所有者值、每次获取与释放请求、TTL(存活时间)、节点地址、复制偏移、切换纪元和下游业务世代,画出“甲读取旧值、锁到期、乙获取新值、甲执行删除、主从切换、双方提交”的时间线。若甲在读取和删除之间没有服务端原子校验,且删除时间落在乙获取之后,就支持误删;若切换后新主本来就缺少乙的锁写,还要区分复制回退和删除两条原因,不能混成一个结论。止血先暂停该锁域的新任务,隔离甲乙实例,冻结库存调整和支付补偿,按稳定请求号查询已发生的数据库与渠道副作用;不要重新创建一个无世代锁后盲目重跑。修复使用随机唯一所有者值,释放与续期都在服务端原子比较后执行;客户端连接必须跟随新拓扑,旧主隔离。更关键的是领取时生成持久化单调世代,下游状态条件、唯一流水或 fencing token(栅栏令牌)拒绝旧世代,即使锁被误删也不产生第二次业务效果。验证注入释放前暂停、到期重获、复制延迟、切主和旧实例恢复,要求新锁不被旧持有者删除、旧世代写入为零、同请求副作用唯一。复盘加入原子脚本审查、锁值日志脱敏、切换演练和高风险操作审批。机制为 E2(既有材料映射),演练为 E3(演练设计),真实原因和损失为 E0(待核对)。 修复上线采用影子记录和小流量故障注入,先统计原子释放拒绝、锁值不匹配和旧世代提交,而不直接改变全部任务。确认拒绝的都是预期迟到者、正常持有者无误伤后再扩大范围;任何无法解释的删除都保留原始请求与拓扑证据继续调查。
  • 追问 1:随机所有者值可以用线程标识吗? 直接回答:单独线程标识可能复用且跨进程不唯一,应使用足够唯一的租约标识并关联业务世代。
  • 追问 2:原子释放能解决脑裂吗? 直接回答:只能保护当前节点上的所有权,不能阻止两侧各自成功,仍需拓扑隔离和围栏。
  • 追问 3:切主后锁键缺失是否应立即补建? 直接回答:先按持久化任务和副作用查证,再由新领取流程生成新世代,不能复制旧锁资格。
  • 追问 4:为什么还要历史修复? 直接回答:阻断新问题不等于已发生的重复库存或支付动作自动消失,必须逐笔对账补偿。
  • 对应详细章节:分布式锁与租约
  1. 问题:缓存回退、锁失租和数据库响应丢失同时发生,如何保证 WMS(仓储管理系统)库存不变量?
  • 考点:条件更新、唯一流水、未知态、缓存重建与对账。
  • 回答思路:把 Redis(远程字典服务)信号降为辅助证据,由数据库事务和请求号裁决。
  • 详细答案:库存正确性要求余额非负、同请求只生效一次、流水守恒;响应丢失时保持未知态并查原请求。
  • 进阶追问:缓存显示库存恢复为原值,能否说明扣减失败?
  • 进阶回答:不能,缓存可能因切主回退,必须查询数据库余额与预占流水。
  • 口述答案:我先明确三条库存不变量:可用量永不为负,同一预占请求最多生效一次,预占、释放和实际扣减流水可与余额守恒。然后固定租户、仓库、SKU(库存单位)、订单行、预占请求号、缓存版本、锁世代和数据库事务时间线。缓存回退只能解释展示或预判变化,锁失租只能解释可能出现两个执行者,数据库响应丢失则意味着业务结果未知,三者都不能直接判成功或失败。止血先关闭该热点键的自动重试与批量放量,隔离旧执行者,展示可返回带版本旧值,但新预占仍执行数据库 available >= quantity 条件更新;所有重试复用原请求号,先查唯一流水,未知请求不得换号再扣。修复让预占事务同时完成非负条件更新和唯一流水写入,任务领取携带持久化世代,缓存仅在事务提交后按版本删除或重建;释放与取消也使用原业务请求和状态条件,防止迟到动作覆盖新状态。验证组合注入缓存切回旧值、锁到期、数据库已提交但响应丢失、旧线程恢复和客户端重复请求,要求缓存可任意缺失或回退而数据库余额始终非负,同请求只有一条有效流水,旧世代写入为零,未知态可通过原请求查证。恢复后逐仓库对账并小流量放开。复盘记录锁失租、条件失败、未知态年龄、缓存版本漂移和库存差异。方案为 E2(既有材料映射),注入为 E3(演练设计),真实超卖数据为 E0(待核对)。 放量按仓库和热点等级分批,每批至少跨过一个锁租期和一次缓存刷新周期,持续观察条件更新失败、重复请求命中、旧世代拒绝与差异单。若缓存指标漂亮但库存对账仍增长,立即回退;业务守恒是高于命中率和延迟的退出门槛。
  • 追问 1:唯一流水插入成功但余额未变怎么办? 直接回答:二者应在同一数据库事务;若历史已不一致,冻结该键并按审计规则修复。
  • 追问 2:缓存删除失败会超卖吗? 直接回答:本身不应,若最终扣减仍有数据库非负条件;它会造成陈旧展示和额外冲突。
  • 追问 3:锁完全不用是否可行? 直接回答:正确性可由数据库保证,但热点下冲突成本可能高,锁可作为优化而非唯一防线。
  • 追问 4:怎样验证流水守恒? 直接回答:按初始量、入库、预占、释放、扣减和调整复算余额,并逐请求核对唯一性。
  • 对应详细章节:工程场景与项目案例
  1. 问题:支付查询缓存雪崩、补偿锁脑裂且渠道响应超时,如何保证资金一致性并完成复盘?
  • 考点:支付未知态、渠道幂等、唯一分录、缓存降级、锁围栏。
  • 回答思路:先停止自动重扣,以支付意图和原请求号串起渠道、订单、账务与对账。
  • 详细答案:缓存和锁都不承担资金事实;支付不重复扣款、分录唯一与平衡、未知态可查证才是恢复标准。
  • 进阶追问:补偿任务持有锁时渠道仍超时,能否换请求号再试?
  • 进阶回答:不能,超时不代表未扣,必须保留原请求号主动查询或等待可靠回调。
  • 口述答案:我先定义资金不变量:同一支付意图不能重复扣款,每次资金变化必须有唯一不可变分录,账户收支平衡,所有超时未知态最终都能按原请求查证。固定订单号、支付意图、渠道请求号、缓存版本、补偿任务实例、锁所有者与世代、渠道调用和账务提交时间线。查询缓存雪崩只影响读路径和回源压力;补偿锁脑裂说明可能有两个执行者;渠道超时只说明通信没有按时返回,三者都不能证明扣款失败。止血立即暂停自动补偿和换号重试,按商户、渠道和订单限流,支付查询回到权威订单及账务库并保留渠道查询能力;隔离旧锁持有者,所有未决订单进入未知态队列。修复要求所有渠道调用复用稳定幂等键,补偿领取生成持久化世代,下游状态条件拒绝旧世代;渠道成功后用唯一分录和订单状态事务化落账,迟到回调按同一请求幂等处理。缓存从权威状态按版本重建,不能反向驱动扣款。验证组合注入缓存批量失效、主从切换、双补偿者、渠道已扣但响应丢失、回调重复和对账延迟,要求渠道侧同请求最多一次有效扣款、本地分录唯一且平衡、旧世代提交为零、未知态年龄归零。复盘记录回源预算、锁脑裂窗口、渠道查证时长、对账差异、手工处置审批和演练责任人。方案为 E2(既有材料映射),注入量级为 E3(演练设计),真实资金影响必须由 E1(直接证据)支持,否则为 E0(待核对)。 事故结束需要技术、业务和运营三方共同签字:技术侧回源与拓扑稳定,业务侧订单、渠道、分录和账户余额一致,运营侧受影响商户与人工补偿清单归零。任何无法取得渠道证据的订单继续保持未知并受控跟踪,不能为了报表好看强行改成失败或成功。
  • 追问 1:渠道查询也超时怎么办? 直接回答:保持未知态并退避重查,限制人工操作,等待回调或对账证据,绝不直接重扣。
  • 追问 2:锁只允许一个补偿者为何还需渠道幂等? 直接回答:锁可失租和脑裂,且人工或其他入口也可能重试,渠道幂等是独立防线。
  • 追问 3:分录唯一但金额错误算一致吗? 直接回答:不算,还要校验币种、金额、方向、账户和业务意图,并通过对账发现差异。
  • 追问 4:缓存命中率恢复后何时退出事故? 直接回答:还需未知订单清零、渠道与本地对账完成、重复扣款为零并通过故障复演。
  • 对应详细章节:支付资金一致性与项目话术

8. 复习清单

  • 能用键存在性、热点集中度和失效分布区分穿透、击穿与雪崩。
  • 能同时从每键请求率、字节率、成员数和命令成本区分 hot key(热键)与 big key(大键)。
  • 能说明 RDB(快照持久化)、AOF(追加日志)、复制与新主继承的不同确认边界。
  • 能画出主从、哨兵、Cluster(集群)在切换、迁槽和脑裂时的证据链。
  • 能解释 TTL(存活时间)、续期、所有者释放与 fencing token(栅栏令牌)的职责边界。
  • 能在失败注入中固定业务键、版本、世代、时间窗和权威账本,不凭单一指标猜根因。
  • 能按“止血、修复、验证、复盘”回答,并给出退出降级与逐步放量门禁。
  • 能坚持库存非负、请求唯一、流水守恒,以及支付不重复扣款、分录唯一平衡、未知态可查证。
  • 能明确 E0(待核对)、E1(直接证据)、E2(既有材料映射)和 E3(演练设计),不把演练数字说成生产收益。