超级小牙医
126.69M · 2026-03-22
设计思想参考上一篇文章:高并发强一致性顺序号生成系统 -- SequenceGenerator github:SequenceGenerator
本组件采用了 "Redis 主生成 + DB 异步备份 + DB 乐观锁降级" 的高可用架构设计。
INCR)在内存中原子完成,无锁、无阻塞。整个系统围绕三种状态进行运转:
stateDiagram-v2
[*] --> NORMAL : 启动初始化
NORMAL --> FAILOVER : Redis 连接超时/执行异常
FAILOVER --> RECOVERING : 达到 N 次请求探活发现 Redis 恢复
RECOVERING --> NORMAL : DB 最大值同步到 Redis 完成
RECOVERING --> FAILOVER : 恢复期间发生异常
sequenceDiagram
participant Client as 客户端线程
participant StateMachine as 状态机 (StateMachineManager)
participant Redis as Redis (主)
participant ThreadPool as 异步线程池 / Kafka
participant MySQL as MySQL (备份)
Client->>StateMachine: 请求 nextId()
StateMachine->>Redis: INCR 获取最新序号 (V)
Redis-->>StateMachine: 返回序号 V
StateMachine->>ThreadPool: 提交异步写 DB 任务 (seqKey, date, V)
StateMachine-->>Client: 组装前缀返回完整 ID
Note right of ThreadPool: 异步执行,不阻塞主线程
ThreadPool->>MySQL: UPSERT ... GREATEST(curr_value, V)
MySQL-->>ThreadPool: 写入成功
sequenceDiagram
participant Client as 客户端线程
participant StateMachine as 状态机 (StateMachineManager)
participant Redis as Redis (宕机)
participant MySQL as MySQL (降级提供服务)
Client->>StateMachine: 请求 nextId()
StateMachine->>Redis: 尝试 INCR
Redis--xStateMachine: Timeout Exception
Note over StateMachine: 捕获异常,将状态切为 FAILOVER
StateMachine->>MySQL: 查询当前最大记录
MySQL-->>StateMachine: 返回 current_value (如 100)
StateMachine->>MySQL: CAS 乐观锁 UPDATE sys_sequence SET curr_value=101 WHERE version=v
MySQL-->>StateMachine: 受到影响行数 = 1 (成功)
StateMachine-->>Client: 返回序号 101
sequenceDiagram
participant Client as 客户端线程 (触碰间隔 N)
participant StateMachine as 状态机
participant Redisson as 分布式锁
participant MySQL as MySQL
participant Redis as Redis (已恢复)
Client->>StateMachine: 请求 nextId(),触发 failoverCounter % N == 0
StateMachine->>Redisson: 尝试获取恢复锁 (tryLock)
Redisson-->>StateMachine: 获取成功
Note over StateMachine: 状态切换为 RECOVERING (阻塞后续请求)
StateMachine->>Redis: 探活 (PING)
Redis-->>StateMachine: PONG (存活)
StateMachine->>MySQL: 读取 DB 中最大序号 (如 500)
MySQL-->>StateMachine: 返回 500
StateMachine->>Redis: SET 强制重置 Redis 的值为 500 (对其 DB 进度)
Redis-->>StateMachine: OK
Note over StateMachine: 状态切回 NORMAL,释放锁
StateMachine->>Redis: INCR 生成最新序号 (501)
Redis-->>StateMachine: 501
StateMachine-->>Client: 返回序号 501
系统提供两种异步持久化 DB 的策略,可以通过 application.yml 的 sync-mode 参数灵活切换:
sys_sequence 表的 Upsert 操作。CallerRunsPolicy 降级为同步执行,牺牲一点性能但绝对不丢数据。@KafkaListener 消费者进行写库。ON DUPLICATE KEY UPDATE curr_value = GREATEST(curr_value, newValue) 语法,无惧消息的乱序消费,只记录最大值。