Java学习第10天:分布式 ID、分布式锁、分布式事务

4 阅读5分钟

一、今日核心目标

  1. 掌握分布式 ID 5 种方案、优缺点、落地选型
  2. 掌握分布式锁 3 种实现(Redis/Redlock/ZooKeeper),避坑 + 实战配置
  3. 掌握分布式事务 6 种方案:2PC、TCC、SAGA、本地消息表、事务消息、最大努力通知
  4. 全部内容:原理 + 落地 + 面试话术 + 避坑,一套吃透

一、分布式 ID(高并发系统必须)

1. 为什么需要分布式 ID

  • 单体:MySQL 自增 ID 够用
  • 分库分表后:自增 ID 重复、无序、不安全、不利于扩容
  • 要求:全局唯一、趋势递增、高性能、高可用、信息安全

2. 5 种分布式 ID 方案对比

① UUID

  • 优点:本地生成、无网络消耗、简单
  • 缺点:太长、无序、索引性能差、不安全
  • 结论:不推荐用于业务主键

② 数据库号段模式(优化版自增)

  • 思路:不每次取 1,而是每次取一段(1~1000)
  • 优点:性能高、稳定、可控
  • 缺点:依赖 DB、有单点风险
  • 落地:美团 Leaf、百度 UidGenerator都用这个

③ Redis 自增

  • 优点:高性能、简单
  • 缺点:Redis 挂了有风险、持久化丢数据
  • 适用:日志、流水号等非核心 ID

④ 雪花算法 Snowflake(最主流)

  • 结构:

    • 1 位符号
    • 41 位时间戳
    • 10 位机器 ID
    • 12 位序列号
  • 性能:单节点每秒 4096 个 ID

  • 优点:有序、长整型、性能极高、无依赖

  • 缺点:时钟回拨会导致重复 ID

⑤ 号段 + 雪花(混合方案,大厂首选)

  • 号段保证高可用
  • 雪花保证有序
  • 代表:Leaf、Baidu UidGenerator

3. 最终选型(面试 / 工作直接用)

  • 中小公司:雪花算法
  • 中大型 / 分库分表:号段模式(Leaf)
  • 绝对不推荐:UUID

二、分布式锁(高并发核心)

1. 为什么需要分布式锁

  • 单机:synchronized / ReentrantLock
  • 集群:多 JVM,本地锁失效
  • 场景:秒杀、扣库存、重复支付、幂等

2. 分布式锁三大实现方案

① 基于数据库(几乎不用)

  • 锁表 + 唯一索引
  • 缺点:性能差、无阻塞、无超时、不适合高并发

② Redis 分布式锁(最常用)

(1)基础实现
  • 加锁:SET lock_key value NX EX 30
  • 释放:DEL lock_key
(2)4 个致命坑(面试必考)
  1. 锁被其他线程误删→ 解决:value 用唯一 ID,删前判断是不是自己的锁
  2. 锁过期,业务还没执行完→ 解决:看门狗(WatchDog)自动续期
  3. 主从切换,锁丢失→ 解决:Redlock 或 Redisson
  4. 不可重入→ 解决:Redisson 内置可重入锁
(3)落地最佳实践:直接用 Redisson
  • 自动续期
  • 可重入
  • 阻塞锁
  • 分布式锁、联锁、红锁全支持

一句话总结:

高并发分布式锁,直接用 Redisson,不要自己手写。


③ ZooKeeper 分布式锁

  • 优点:可靠性极高、严格顺序、临时节点 + 自删
  • 缺点:性能不如 Redis
  • 适用:金融、支付等强一致场景

3. 三种分布式锁最终对比

方案性能可靠性复杂度推荐
MySQL不推荐
Redis极高推荐
ZK极高金融 / 强一致

三、分布式事务(面试最难、分值最高)

1. 什么是分布式事务

跨库、跨服务、跨机器的事务,需要要么都成功,要么都失败

典型场景:

  • 下单 → 扣库存 → 扣优惠券 → 加积分
  • 一个失败,全部回滚

2. CAP 理论(必背)

  • C:一致性
  • A:可用性
  • P:分区容错性分布式系统:必须 P,只能在 C 和 A 之间选择

3. BASE 理论

  • 基本可用
  • 柔性状态
  • 最终一致性→ 分布式事务大多基于最终一致性

四、分布式事务 6 大方案(超详细)

1. 2PC 两阶段提交(强一致)

  • 阶段 1:所有参与者准备
  • 阶段 2:协调者下发提交 / 回滚
  • 优点:强一致
  • 缺点:阻塞、性能差、协调者单点
  • 适用:数据库内部,不适合业务系统

2. 3PC 三阶段提交

解决 2PC 的单点和阻塞,但几乎不用


3. TCC 事务(Try-Confirm-Cancel)

业务侵入最强,性能最好

  • Try:预留资源
  • Confirm:确认执行
  • Cancel:释放预留资源

优点:高性能、不锁库缺点:开发量大、要考虑空回滚、悬挂、幂等适用:支付、金融、核心交易


4. SAGA 事务

长事务解决方案:

  • 把大事务拆成多个小事务
  • 失败反向执行补偿接口

优点:高可用、异步、无锁缺点:数据中间态可见适用:订单流程、物流、长链路业务


5. 本地消息表(经典可靠方案)

流程:

  1. 本地事务:业务数据 + 消息 一起入库
  2. 定时任务扫描未发送消息
  3. 发送 MQ
  4. 消费成功删除消息

优点:可靠、简单缺点:有侵入、和业务耦合


6. 事务消息(RocketMQ,最推荐)

半消息 + 事务回查

流程:

  1. 半消息(不可消费)
  2. 执行本地事务
  3. 提交 / 回滚半消息
  4. 超时回查本地事务状态

优点:高可用、高并发、无业务侵入缺点:依赖 RocketMQ适用:90% 互联网业务(下单、支付、库存)


7. 最大努力通知

  • 重试 + 定期校对
  • 适用:通知类、非核心(短信、推送)

五、6 种分布式事务最终选型(面试 / 工作直接背)

  1. 强一致、简单 → 2PC(数据库用)
  2. 高性能、金融核心 → TCC
  3. 长事务、业务链 → SAGA
  4. 简单可靠、不依赖 MQ → 本地消息表
  5. 互联网主流、高并发RocketMQ 事务消息(首选)
  6. 通知类、非核心 → 最大努力通知

一句话总结:

普通业务优先用 事务消息;金融支付用 TCC;长流程用 SAGA


六、面试高频 10 题(必背)

  1. 分布式 ID 有哪些方案?雪花算法结构?时钟回拨怎么办?
  2. 号段模式为什么比自增 ID 好?
  3. Redis 分布式锁有哪些坑?怎么解决?
  4. 为什么要用 Redisson?WatchDog 作用?
  5. 什么是 CAP、BASE?
  6. 2PC 缺点是什么?
  7. TCC 三个阶段?存在哪些问题?
  8. 本地消息表实现流程?
  9. RocketMQ 事务消息原理?半消息、回查机制?
  10. 你们项目用哪种分布式事务?为什么?