欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 双ID链法实现MQ消费者幂等

双ID链法实现MQ消费者幂等

2025/6/23 0:05:12 来源:https://blog.csdn.net/LUCIAZZZ/article/details/148809921  浏览:    关键词:双ID链法实现MQ消费者幂等

什么是双ID链法

双ID链法通过 组合两种不同特性的ID生成器(通常选择互补的方案),生成一个复合ID,利用两者的优势,规避各自的缺陷


最常见的组合是:

  • 主ID:全局唯一但可能不连续(如雪花算法/Snowflake)
  • 副ID:局部有序且绝对连续(如数据库自增序列、Redis INCR)

ID结构示例:

[主ID(雪花算法)]_[副ID(自增序列)]  
↓                  ↓
保证全局唯一性      保证局部连续性

例如:1256892300152455168_42(前半部分是雪花ID,后半部分是Redis自增序列)

双ID是放到消息题里面作为标识的


为什么需要双ID链法

单一ID生成器的缺陷:

ID生成方案

优点

缺点

雪花算法

高性能、分布式唯一

时钟回拨可能导致重复

数据库自增序列

绝对有序

性能低、单点故障风险

Redis INCR

高并发

主从切换可能重复

双ID链的解决思路:

  • 主ID(如雪花算法):解决分布式唯一性问题
  • 副ID(如Redis的Incr):解决连续性、防时钟回拨问题

两者结合后:

  • 即使主ID因时钟回拨重复,副ID也能保证整体唯一性
  • 即使副ID因主从切换不连续,主ID仍能保证全局唯一

双ID链法解决的核心问题

1. 主从切换后的ID重复

问题:Redis主节点宕机后,从节点可能重复分配已丢失的ID

解决:即使副ID重复,主ID(雪花算法)的机器ID和时间戳仍不同

2. 时钟回拨问题

问题:雪花算法依赖系统时钟,时钟回退可能导致ID重复

解决:副ID的自增序列不受时钟影响,可作为回拨时的补偿

3. 消息重复消费

问题:消费者可能重复处理同一条消息

解决:用双ID作为消息唯一键,消费端可同时校验主ID和副ID

用雪花算法解决分布式唯一性问题

用自增序列解决局部有序性问题

两者组合后,即使一个组件失效,另一个仍能兜底


与MQ幂等性的协作

即使使用双ID作为Key,仍需配合MQ的幂等机制:

防护层级

作用

实现示例

双ID

生产端避免生成重复ID

雪花ID+自增ID

生产者幂等

Broker端去重

Kafka设置 enable.idempotence=true

消费者幂等

业务层最终防重

数据库唯一约束或Redis判重

Kafka设置 enable.idempotence=true如何实现生产者幂等

当启用 enable.idempotence=true 时,Kafka 会为每个生产者分配一个唯一标识,并跟踪每条消息的状态:

要素

作用

类比现实场景

PID (Producer ID)

每个生产者实例的唯一ID,由Broker分配

就像快递员的工号,唯一标识发货人

Sequence Number

每条消息的递增序列号(从0开始),按 <Topic, Partition>

维度维护

快递员每次发货的包裹编号

Epoch

生产者实例的版本号(防止僵尸生产者)

工号的有效期(防冒用)

这可以实现在Broker端,也就是MQ端本身进行去重复

新消息:必须满足 当前Seq == Broker存储的LastSeq + 1
(如Broker记录的最后Seq=5,则下一条必须为6)

重复消息:收到 Seq ≤ LastSeq 的消息直接丢弃
(如重复发送Seq=5,而Broker已处理到Seq=7)


Redis生成副ID-避免Redis单点故障主从切换时的数字漏洞

问题:

只依赖Redis的incr生成ID的话,在Redis 主节点故障切换后,incr 生成的 ID 可能重复(主节点未同步的命令丢失),导致 “订单 ID 冲突”

方案 1:单纯 Redis Key + 过期时间
完全依赖 Redis 生成 ID,主从切换时必然存在 ID 重复风险(除非关闭主从异步复制,牺牲性能)

方案 2:双 ID 链(主 ID 用雪花算法)
主 ID 由雪花算法生成(基于时间戳 + 机器码),不依赖 Redis,天然避免主从切换导致的 ID 重复。辅助 ID 用于 Redis 分片,即使 Redis 主从切换,辅助 ID 短暂重复也不影响主 ID 的唯一性(业务逻辑以主 ID 为准)


双ID链法优化大Key问题

用副id将双ID进行分片存储,控制不同id存储的位置

例如下面就是一个双ID:

1256892300152455168_42

例如我们以1000数量为一组

42/1000=0

1001/1000=1

2001/1000=2

那么就是副id为0-999的双id存在 xxxKey1

那么就是副id为1000-1999的双id存在 xxxKey2

那么就是副id为2000-2999的双id存在 xxxKey3

这样子就优化了大Key问题

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词