分布式事务、分布式锁与幂等设计

共 20 题
📑 题目列表 20 题
#
★★★

1. 两阶段提交(2PC)的协调者与参与者协议流程是什么,同步阻塞、协调者单点与脑裂问题如何产生?

说明两阶段提交(2PC)的协调者与参与者协议流程,以及同步阻塞、协调者单点与脑裂问题如何产生?

  • 2PC 的 prepare 与 commit 两阶段
  • 同步阻塞(参与者等待协调者)
  • 协调者单点与脑裂

2PC 由协调者(coordinator)与多个参与者(participant)组成。第一阶段 Prepare:协调者向所有参与者发送 prepare 请求,各参与者执行本地事务并响应"可以提交"或"中止";第二阶段 Commit/Abort:协调者若收到全部"可以提交"则广播 commit,否则广播 abort,各参与者据此提交或回滚。同步阻塞问题:参与者提交 prepare 后,必须阻塞等待协调者的最终决策,若协调者故障,参与者无法确定提交/中止,只能等待(阻塞)。协调者单点问题:协调者是唯一决策者,其故障导致整个事务无法推进。脑裂问题:若协调者与部分参与者网络分区,协调者无法确认全部参与者状态,可能做出与其他协调者不一致的决策,导致数据不一致。这些缺陷使 2PC 在分布式环境下可靠性不足。

2PC 的阻塞源于"协调者单点 + 全体一致 + 无超时恢复":参与者 prepare 后失去决策能力,协调者又是唯一决策者。脑裂则源于分区时无法确认全体状态。这些是 2PC 的固有缺陷,也是引入 3PC、SAGA、TCC 的原因。

#
★★★

2. 三阶段提交(3PC)相对 2PC 增加了哪些阶段与超时机制,为什么仍不能彻底解决网络分区问题?

说明三阶段提交(3PC)相对 2PC 增加了哪些阶段与超时机制,以及为何仍不能彻底解决网络分区问题?

  • 3PC 增加 CanCommit 阶段与超时
  • 参与者超时可自行中止
  • 仍无法解决分区/脑裂

3PC 在 2PC 基础上增加了一个 CanCommit 阶段(预询问所有参与者能否提交),并引入超时机制:参与者收到 prepare 后,若超时未收到协调者决策,可自行中止(而不是无限阻塞)。CanCommit 阶段先探测所有参与者可提交性,降低"部分提交部分中止"的概率;超时机制使参与者不再无限阻塞。但 3PC 仍不能彻底解决网络分区问题:因为分区时协调者无法与全部参与者通信,可能有两个不同分区各自做出不同决策(一个提交、一个中止),无人能保证一致性,导致脑裂。3PC 的"提交/中止"决策在分区下仍可能冲突,故不能完全解决分区。

3PC 通过"增加预询问阶段 + 超时中止"减轻了阻塞,但无法解决分区下的"决策冲突":分区使两个分区可能做出不同决策却又无法协调。这本质上仍是"无法在分区下达成一致"的固有限制,3PC 只能缓解阻塞性,不能彻底解决脑裂。

#
★★★

3. TCC(Try-Confirm-Cancel)的空回滚与悬挂问题是什么,它与 2PC 在资源锁定与最终一致性上有何本质区别?

说明 TCC(Try-Confirm-Cancel)的空回滚与悬挂问题,以及它与 2PC 在资源锁定与最终一致性上的本质区别?

  • TCC 的 Try/Confirm/Cancel 三阶段
  • 空回滚(未执行 Try 却 Cancel)与悬挂(前置请求未达)
  • 与 2PC 的资源锁定与一致性的区别

TCC 将事务拆为 Try(预留资源)、Confirm(确认)、Cancel(取消)三个业务操作。空回滚问题:当 Try 请求因网络延迟未到达、但 Cancel 已先执行时,业务会执行"空回滚"——Cancel 需对未预留的资源做幂等回滚,避免制造错误状态。悬挂问题:Try 请求迟到,在 Cancel 执行后才到达,导致预留资源悬挂(无 Confirm/Cancel 处理),需通过唯一标识与状态判断防止悬挂。TCC 与 2PC 的本质区别:TCC 用业务层面的资源预留(Try 预留业务资源)而非数据库锁,且是"最终一致"(Confirm/Cancel 异步补偿,允许短暂不一致),2PC 用数据库锁并追求强一致(prepare 后锁资源阻塞)。TCC 更灵活但依赖业务补偿逻辑的正确性。

TCC 的空回滚与悬挂源于"网络消息乱序 + 业务补偿":需用幂等与状态机处理迟到的 Try/Cancel。TCC 以业务资源预留 + 异步补偿换取弱阻塞与最终一致,与 2PC 的数据库强锁强一致形成对比,代价是业务需实现可补偿逻辑。

#
★★★

4. SAGA 长事务如何用正向操作加补偿操作编排,补偿失败与幂等如何保证,与 TCC 的适用场景差异?

说明 SAGA 长事务如何用正向操作加补偿操作编排,以及补偿失败与幂等如何保证,与 TCC 的适用场景差异?

  • SAGA 的正向操作 + 补偿操作
  • 补偿失败与幂等设计
  • 与 TCC 的适用场景差异

SAGA 将长事务拆分为一系列正向操作(每个操作有对应的补偿操作),按顺序执行;若某步失败,则逆向执行已执行步骤的补偿操作来回滚。补偿操作必须是幂等的(多次执行结果一致),以应对重试;补偿失败时需重试、记录、人工干预,通过补偿日志与对账兜底。SAGA 与 TCC 的适用场景差异:SAGA 适合"无资源预留、允许最终一致、长流程"的场景(如订单、物流编排),补偿操作是"业务上对已生效操作的撤销";TCC 适合"需要预留资源、明确 Try/Confirm/Cancel 三态"的场景,对资源有明确的预留语义。SAGA 更简单、补偿更自然,但回滚非原子(可能部分成功);TCC 预留更强但业务实现更复杂。

SAGA 的补偿是"业务级撤销",需幂等 + 重试 + 对账保证;TCC 的 Try 阶段预留资源。SAGA 适合长流程、无需预留的场景,TCC 适合强资源预留的场景。理解差异有助于按业务选择编排模型。

#
★★★

5. 本地消息表与事务消息如何保证"业务提交"与"消息发送"的原子性,最终一致性的延迟与失败重试如何设计?

说明本地消息表与事务消息如何保证"业务提交"与"消息发送"的原子性,以及最终一致性的延迟与失败重试设计?

  • 本地消息表:业务与消息同库事务
  • 事务消息:两阶段提交式半消息
  • 重试与补偿、最终一致

本地消息表方案:在业务库中建立消息表,业务操作与消息插入在同一本地事务中提交,保证"业务提交"与"消息产生"原子;后台任务定期扫描消息表,把未发送的消息投递到 MQ,投递成功后标记。事务消息方案(如 RocketMQ):发送"半消息"(消费者不可见),待本地业务事务提交后,再确认(commit)消息使消费者可见;若业务回滚则回滚消息。若确认消息丢失(半消息回查),broker 回查业务事务状态决定 commit/rollback。这样保证业务与消息的原子性。最终一致性的延迟与重试:通过定时任务/回查补偿、消息重试(指数退避)、幂等消费设计,保证最终发送成功且不重复处理。

本地消息表用"同库事务"保证原子,事务消息用"半消息 + 回查"保证原子。两者都通过"重试 + 幂等 + 定时补偿"实现可靠最终一致,是"消息可靠发送"的经典方案。

#
★★★

6. 分布式锁应满足互斥、可重入、防死锁、防误删等哪些要求,加锁值携带唯一标识(token)为什么必要?

说明分布式锁应满足互斥、可重入、防死锁、防误删等要求,以及加锁值携带唯一标识(token)的必要性?

  • 互斥、可重入、防死锁、防误删
  • token 唯一标识防止误删他人锁
  • 公平性与超时

分布式锁应满足:互斥(同一时刻只有一个持锁者)、可重入(同一线程可重复加锁)、防死锁(锁有超时/自动释放,避免持锁者崩溃后锁永存)、防误删(释放锁时须校验是本人持有的锁,避免误删他人锁)。加锁值携带唯一标识(token,如 UUID 或单调递增版本号)是必要的:因为锁可能因超时/网络被其他客户端获取,若释放时用固定的"解锁"命令,可能误删他人持有的锁;携带 token 后,释放锁时用"比较并删除"(Lua 脚本校验 token 匹配才删除),确保只释放自己持有的锁,防止误删与并发安全问题。token 还用于标识锁的"代次",防止持锁者因操作慢而误以为自己仍持有锁。

token 是"防误删"与"确权"的关键:释放时必须校验持有者身份。它把"锁的释放"从盲目操作变为"CAS 校验",是分布式锁安全的基石。理解 token 有助于设计安全的分布式锁。

#
★★

7. Redis SETNX 加过期时间实现分布式锁有哪些边界问题,Redlock 算法为何存在争议,什么场景不宜使用?

说明 Redis SETNX 加过期时间实现分布式锁的边界问题,Redlock 算法为何存在争议,以及什么场景不宜使用?

  • SETNX + 过期时间的边界问题
  • Redlock 的争议(时钟、故障、脑裂)
  • 不宜使用的场景

Redis SETNX 加过期时间实现分布式锁的边界问题:过期时间设置不当会导致持锁者还未完成就锁过期(锁被他人获取),或持锁者崩溃后锁需等过期才释放;主从环境中,主节点写锁后未同步就故障,从节点升级后锁丢失(另一客户端获得锁),破坏互斥;释放锁时若未校验 token 可能误删他人锁。Redlock 算法(多 Redis 实例过半加锁)的争议:它依赖时钟与故障模型,在"部分实例分区/故障"与"时钟漂移"时可能违背互斥(如 Redis 主从切换、进程停顿超过锁租期),且无法保证强一致,因此被质疑不能提供真正的互斥保证。不宜使用场景:对互斥有强要求(如只允许一个资源执行)且无法容忍锁失效的场景,不应依赖 Redis 锁;应使用 etcd/ZooKeeper 等基于共识的锁。可容忍轻微失效、追求性能的场景可用 Redis 锁。

Redis 锁的边界问题源于"非强一致 + 时钟 + 主从":锁可能丢失、过期、误删。Redlock 争议在于其"过半"仍无法保证互斥(时钟/分区/停顿破坏)。因此关键互斥场景应选 etcd/ZooKeeper,Redis 锁适合容忍轻微失效的场景。

#
★★

8. 基于 etcd/ZooKeeper 的分布式锁(租约加 watch)与 Redis 锁在一致性、可用性与运维成本上的差异?

对比基于 etcd/ZooKeeper 的分布式锁(租约加 watch)与 Redis 锁在一致性、可用性与运维成本上的差异?

  • etcd/ZK 基于共识的强一致
  • Redis 锁的弱一致与高性能
  • 可用性与运维成本

etcd/ZooKeeper 的分布式锁基于共识(Raft/Zab)实现,通过"租约 + watch"机制:加锁创建带租约的节点,watch 监听锁释放,释放后自动续租或删除。它提供强一致与可靠的通知(watch 事件驱动锁等待),且租约可自动续期、防死锁,锁不易丢失。一致性更强,但写入需走共识,吞吐较低、延迟较高,运维需部署集群(etcd/ZK 集群)。Redis 锁基于单机/主从 SETNX,性能高、延迟低、运维简单,但一致性弱(主从切换、时钟可能导致锁丢失),无法保证严格互斥。可用性上:etcd/ZK 多数派存活性高,Redis 主从切换可能丢锁。成本上:etcd/ZK 集群运维成本高,Redis 简单。因此:强一致性场景用 etcd/ZK 锁,高吞吐、容忍弱一致场景用 Redis 锁。

两者的本质差异是"共识强一致 vs 高性能弱一致":etcd/ZK 用共识保证锁的安全与可靠通知,Redis 用性能换一致性。选型需权衡一致性要求、吞吐与运维成本。

#
★★

9. 幂等设计的三个层次(唯一键、去重表、状态机)如何工作,重复请求为什么必须返回与首次一致的结果?

说明幂等设计的三个层次(唯一键、去重表、状态机)如何工作,以及重复请求为何必须返回与首次一致的结果?

  • 唯一键(请求 ID)去重
  • 去重表(DB 唯一约束)
  • 状态机(状态流转防重)

幂等设计的三个层次:唯一键方案给每个请求生成全局唯一 ID(如请求号),服务端用该 ID 去重,重复请求直接返回首次结果;去重表方案在数据库中建唯一键(如业务唯一索引),重复插入时违反唯一约束而被拦截,返回已处理结果;状态机方案把业务建模为状态机,只有合法状态转移才执行,重复请求若状态已到达目标状态则跳过,返回当前状态。重复请求必须返回与首次一致的结果,是因为:客户端可能因超时重试,若返回不同结果会造成业务混乱(如重复扣款、重复下单),破坏幂等语义。幂等保证"同一请求多次执行结果一致",是分布式系统可靠性的基础。

三个层次分别从"请求标识、存储约束、状态约束"实现幂等。返回与首次一致的结果是幂等的核心语义,配合唯一约束与状态机,避免重复执行带来的副作用。

#
★★

10. 2PC、TCC、SAGA、消息最终一致分别适合什么一致性要求与业务场景,选型时应权衡哪些因素?

说明 2PC、TCC、SAGA、消息最终一致分别适合的一致性要求与业务场景,以及选型时应权衡的因素?

  • 各方案的一致性强度与适用场景
  • 强一致 vs 最终一致
  • 选型权衡(一致性、延迟、复杂度、可用性)

2PC 提供强一致(数据库锁、全体原子提交),适合强一致、短事务、跨多库一致性要求高的场景(如银行转账),但阻塞、单点、低可用。TCC 提供业务层面强一致(资源预留 + 补偿),适合需要预留资源、可接受的最终一致、业务可补偿的场景(如支付、库存)。SAGA 提供最终一致(正向 + 补偿),适合长流程、无预留、可容忍不一致的场景(如订单、物流编排)。消息最终一致提供最终一致(消息 + 异步),适合可异步、容忍延迟、以消息驱动的场景(如积分、通知)。选型权衡因素:一致性要求(强一致或最终一致)、事务时长、可用性要求、业务复杂度(能否实现补偿)、延迟容忍度、吞吐要求。强一致需求高选 2PC/TCC,长流程最终一致选 SAGA,异步解耦选消息最终一致。

选型本质是"一致性强度 vs 可用性/复杂度/延迟"的权衡:强一致(2PC)牺牲可用与延迟,最终一致(SAGA/消息)牺牲实时一致但更灵活。需结合业务对一致性、时延、成本的容忍度选择。

#
★★

11. CAP 与 BASE 在分布式事务中的指导意义是什么,为什么强一致事务与高可用通常难以兼得?

说明 CAP 与 BASE 在分布式事务中的指导意义,以及为何强一致事务与高可用通常难以兼得?

  • CAP 的分区权衡
  • BASE 的最终一致思想
  • 强一致与高可用的权衡

CAP 定理指出分布式系统在分区(P)发生时,只能在一致性(C)与可用性(A)之间二选一。BASE(Basically Available、Soft state、Eventually consistent)是"最终一致"的工程思想:保证基本可用、允许软状态、最终达到一致。在分布式事务中的指导意义:CAP 告诉我们强一致(如 2PC 式同步提交)在有分区时必须以牺牲可用性为代价(参与者阻塞等待协调者),而 BASE 允许放弃强一致、采用最终一致(如补偿、异步消息、SAGA)来换取高可用。为什么强一致事务与高可用通常难以兼得:强一致要求所有节点在提交前同步确认(达成一致),一旦发生分区,为了数据一致就必须拒绝部分节点请求(牺牲可用性),或为保持可用而接受不一致(牺牲一致性)。因此在线强一致事务与高可用在分区场景下是矛盾的两端,工程上常以"隔离范围 + 最终一致 + 补偿"折中,或用可线性化存储(如 Raft)在正常时保证一致、分区时降级。

CAP 的"P 发生时二选一"是强一致与高可用难兼得的根本原因:强一致提交需全网同步确认,分区时无法同时满足"继续响应"与"数据一致"。BASE 用最终一致换取可用性,是分布式事务在分区容忍下的工程妥协。

#
★★

12. 可靠消息最终一致中的最大努力通知、回调重试与人工对账如何兜底,消息积压时如何降级?

说明可靠消息最终一致中的最大努力通知、回调重试与人工对账如何兜底,以及消息积压时如何降级?

  • 最大努力通知(尽力投递)
  • 回调重试与人工对账兜底
  • 消息积压时的降级

可靠消息最终一致中,最大努力通知(best-effort notification)指系统尽力把消息投递到对端,若失败则按重试策略不断重试(指数退避),不保证一次成功但保证最终尽力送达。回调重试:对端处理失败时,通过回调重试机制(如定时任务、重试队列)重新触发处理。人工对账兜底:当自动重试仍无法解决时,通过对账(核对双方数据)与人工干预(人工补偿)最终一致,这是最终兜底手段。消息积压时降级:降低重试频率、暂停非关键消息、优先处理高优先级消息、拒绝新增(限流/熔断)、横向扩容消费者、消息过期清理等,必要时丢弃可延迟消息并记录,保证关键消息不被阻塞。

可靠消息最终一致"尽力投递 + 重试 + 对账兜底",是"最终一致"的工程保障。积压降级是应对峰值的手段,通过优先级、限流、扩容保护关键链路。理解这些兜底与降级机制有助于设计健壮的最终一致系统。

#
★★

13. XA 协议与 Seata AT 模式的实现原理(全局锁、分支事务、undo log)及相对 2PC 的性能改进?

说明 XA 协议与 Seata AT 模式的实现原理(全局锁、分支事务、undo log),以及相对 2PC 的性能改进?

  • XA 两阶段资源管理
  • Seata AT 的全局锁、分支事务、undo log
  • 相对 2PC 的性能改进(非阻塞)

XA 协议是数据库层面的两阶段提交标准,协调者通过数据库资源管理器(XA 接口)在 prepare/commit 阶段协调分布式事务,prepare 时数据库锁资源、事务阶段阻塞。Seata AT 模式(Automated Transaction)是应用层的分布式事务方案:它用全局锁(协调者管控的全局锁)协调各分支事务;每个分支事务在本地数据库执行并写 undo log(记录回滚镜像),提交时通过 undo log 反向补偿实现回滚;分支事务先本地提交(不加持久的数据库锁),全局提交/回滚通过异步协调。相对 2PC,Seata AT 的分支事务本地提交后不长期阻塞数据库锁,全局锁在协调层短暂持有,性能更高、更少阻塞,但依赖 undo log 与全局锁的协调,且存在最终一致与幂等补偿需求。

XA 用数据库资源锁 + 两阶段强一致,Seata AT 用"全局锁 + 分支本地提交 + undo log 回滚"实现非阻塞的最终一致。AT 模式以"undo log + 全局锁"换取性能与低阻塞,是相对 2PC 的工程优化。

#
★★

14. 分布式事务的监控与治理,全局事务状态、分支事务超时与悬挂事务的检测、人工干预与补偿重放流程如何设计?

说明分布式事务的监控与治理,包括全局事务状态、分支事务超时与悬挂事务检测、人工干预与补偿重放流程的设计?

  • 全局事务状态跟踪
  • 分支超时与悬挂检测
  • 人工干预与补偿重放

分布式事务的监控与治理需要:跟踪全局事务状态(通过事务协调台/日志记录全局事务 id、各分支状态、当前阶段),用于监控与故障定位;检测分支事务超时(分支未在时限内完成则标记超时并触发重试/回滚)与悬挂事务(分区导致的未决事务,通过扫描与状态判断识别,防止资源悬挂);人工干预流程(对无法自动解决的事务,提供人工处理界面,如手动提交/回滚/补偿);补偿重放流程(对补偿失败的事务,通过重试队列、对账定时任务重放补偿,直至成功或人工确认)。通过这些治理手段,分布式事务在异常下能恢复、可观测、可人工兜底,保证最终一致与系统健康。

分布式事务的"治理"是"可观测 + 可恢复":全局状态跟踪提供可观测性,超时/悬挂检测与补偿重放提供可恢复性,人工干预提供兜底。设计这些机制是分布式事务落地生产的关键。

#
★★

15. 幂等去重窗口与并发安全,去重表在并发重复请求下的唯一索引冲突处理、去重记录的保留周期与清理策略,以及与状态机幂等的组合?

说明幂等去重窗口与并发安全,包括去重表在并发重复请求下的唯一索引冲突处理、去重记录保留周期与清理,以及与状态机幂等的组合?

  • 并发下唯一索引冲突的处理
  • 去重记录保留周期与清理
  • 与状态机幂等的组合

幂等去重表在并发重复请求下,用唯一索引保证同一业务键只插入一次;并发插入时多个请求竞争唯一索引,只有一个成功,其余因违反唯一约束而被拦截(捕获冲突异常后返回已处理结果),从而保证并发安全。去重记录的保留周期需覆盖"可能的重试窗口"(如 24 小时/7 天),超过后需清理(定期删除过期记录)以控制表大小;清理策略需权衡"重试窗口覆盖"与"存储成本"。与状态机幂等的组合:去重表负责"请求级去重"(同一请求只处理一次),状态机负责"业务级幂等"(同一业务状态只流转一次),二者结合可同时处理"请求重复"与"业务状态重复",实现更全面的幂等。例如去重表拦截重复请求,状态机保证状态流转不重复执行。

去重表用唯一索引处理并发冲突,保留周期覆盖重试窗口,状态机补充业务状态幂等。组合"请求级 + 状态级"幂等是生产系统的完整方案,兼顾并发安全与业务正确性。

#
★★

16. SAGA 的编排实现,集中式编排(状态机)与事件驱动 choreography 的差异,补偿链断裂时的恢复与对账机制?

说明 SAGA 的编排实现,包括集中式编排(状态机)与事件驱动 choreography 的差异,以及补偿链断裂时的恢复与对账机制?

  • 集中式编排(orchestration)状态机
  • 事件驱动 choreography
  • 补偿链断裂的恢复与对账

SAGA 的编排有两种实现:集中式编排(orchestration)用统一协调器(状态机)管理整个事务流程,按序调用各正向操作、失败时按序触发补偿,流程清晰、易追踪但协调器是单点;事件驱动 choreography 由各服务通过事件消息串联,每个服务监听事件并执行操作、发布下一个事件,无中心协调器、松耦合,但流程隐式、难追踪、易出现补偿链断裂。补偿链断裂时,需通过补偿日志、重试机制、对账任务恢复:记录每个补偿操作的状态,对未完成的补偿持续重试,并用对账(核对各服务最终状态)发现不一致,触发人工或自动补偿,确保最终一致。

orchestration 集中控流程、易追踪但单点;choreography 松耦合但流程隐式。补偿链断裂是 SAGA 的常见故障,需"日志 + 重试 + 对账"兜底恢复。理解二者差异有助于按流程复杂度选择编排方式。

#
★★

17. 分布式锁的公平性与等待机制,锁等待队列、自旋 vs 阻塞、超时重试如何设计,避免惊群与饿死?

说明分布式锁的公平性与等待机制,包括锁等待队列、自旋 vs 阻塞、超时重试设计,以及避免惊群与饿死?

  • 锁等待队列与公平性
  • 自旋 vs 阻塞等待
  • 避免惊群与饿死

分布式锁的公平性指等待较久的客户端先获得锁,可通过锁等待队列(FIFO 排队)实现,保证先到先得。等待机制:自旋(短等待时轮询锁,延迟低但耗 CPU)vs 阻塞(等待锁释放通知,如 watch/事件,省 CPU 但依赖通知机制)。超时重试:客户端加锁失败后等待一段随机时间再重试,避免集中重试。避免惊群:当锁释放时,不能唤醒所有等待者(会惊群,大量竞争),应只唤醒队首(如 etcd 的顺序锁/watch 只通知下一个),或仅允许一个获得锁,其余继续等待。避免饿死:保证公平队列使每个等待者最终获得锁,防止某客户端长期无法获得锁(如重复加锁被抢占)。设计上需结合公平队列、随机退避、受控唤醒平衡。

公平性用等待队列,等待用自旋/阻塞权衡,重试用随机退避,惊群用"只唤醒队首",饿死用"公平保证"。这些机制共同构成健壮的分布式锁等待模型,避免资源竞争失控。

#

18. 分布式锁的续期(看门狗)机制如何工作,主从切换导致的锁丢失问题有哪些缓解方案?

说明分布式锁的续期(看门狗)机制如何工作,以及主从切换导致锁丢失的缓解方案?

  • 看门狗自动续期
  • 主从切换锁丢失
  • 缓解方案(共识锁、fencing)

分布式锁的续期(看门狗)机制:持锁者在加锁后启动一个后台看门狗线程,定期在锁过期前续期(延长过期时间),只要持锁者存活就持续续期,防止业务未完成时锁过期被他人获取;持锁者完成或崩溃后,看门狗停止,锁自动过期释放。主从切换导致锁丢失:Redis 主节点写锁后未同步就故障,从节点升级为主节点后锁丢失,另一客户端可获取锁,破坏互斥。缓解方案:使用基于共识的锁(etcd/ZooKeeper,主从一致,不会丢锁);使用 fencing token(每次加锁分配递增 token,持锁者操作时服务器校验 token 是当前最新,防止旧持锁者操作);适度延长锁过期时间;业务侧用 token/版本号校验防止旧持锁者操作。

看门狗解决"业务未完成锁过期"问题,主从切换丢锁是 Redis 锁的固有缺陷。缓解需用共识锁(强一致)或 fencing token(业务侧校验)来阻断"旧持锁者误操作",这是分布式锁安全的关键工程手段。

#

19. 分布式事务的性能优化,异步化、本地事务加消息、批量提交与读写分离如何降低同步开销?

说明分布式事务的性能优化,包括异步化、本地事务加消息、批量提交与读写分离如何降低同步开销?

  • 异步化减少同步等待
  • 本地事务加消息(本地消息表/事务消息模式)
  • 批量提交与读写分离

分布式事务的性能优化包括:异步化,把非关键步骤异步处理(如异步通知、异步补偿),减少同步等待与耦合;本地事务加消息(本地事务 + 消息表/事务消息),用本地事务保证业务与消息原子,避免跨服务同步事务,降低协调开销;批量提交,把多个分支/消息批量提交,减少 RPC 次数与网络开销;读写分离,把读操作路由到副本,减少对主事务协调的负载,降低同步开销。这些手段把"同步强一致"转化为"异步 + 本地 + 批量",显著提升吞吐与响应,代价是改为最终一致或弱一致。

性能优化的核心是"减少同步协调与网络往返":异步化、本地事务、批量提交、读写分离都服务于这一目标,把强一致同步事务转为异步/最终一致。

#

20. 分布式事务与消息的衔接,事务消息的半消息回查失败、消息重复投递与最终一致性的兜底如何配合?

说明分布式事务与消息的衔接,包括事务消息半消息回查失败、消息重复投递与最终一致性的兜底如何配合?

  • 半消息回查失败处理
  • 消息重复投递的幂等
  • 最终一致性兜底

事务消息与分布式事务的衔接中,半消息(half message)在业务事务未提交前消费者不可见,业务提交后确认消息才可见。半消息回查:若确认消息丢失(业务提交了但 broker 未收到确认),broker 会回查业务事务状态,若事务已提交则最终确认消息,若已回滚则删除消息。回查失败处理:若回查无法确定业务状态(如业务不可用),需重试回查、记录告警、人工兜底。消息重复投递:消费者必须幂等处理(去重表/唯一键),即使用户重复收到消息也不会重复执行业务。最终一致性兜底:通过重试、对账、人工补偿,保证消息最终被正确处理、业务最终一致。三者配合:半消息回查保证"消息可见性"与"业务提交"一致,重复投递幂等保证"消费安全",兜底机制保证"最终一致"。

事务消息的关键是"半消息 + 回查"保证业务与消息原子一致,重复投递靠幂等,兜底靠重试对账。三者配合使"分布式事务 + 消息"在异常下最终一致。