分布式ID生成方案总结

分布式场景下,由于通常是分库分表,所以通常无法仅仅使用数据库的自增Id。需要使用其他方案生成唯一的id。目前业界主流的是基于雪花算法或者雪花算法的改进版本。

UUID

有什么特点?

  • 足够的简单,java原生自带。本地生成具有唯一性。
  • 缺点:不是自增的。不具备趋势递增性。没有具体的业务含义。长度业比较大。

基于数据库

使用一个单独的数据库实例去生成。访问量剧增,mysql本身就是瓶颈。单点风险。

数据库集群。

多个db。使用不常。这样就可以确保每一个db生成的都是不重复的。

比如3个db实例,db1 从1开始生成,每次自增3。db2从2,每次自增3。这样就能保证唯一性。

  • 致命缺点:不利于后续扩容(几乎很少去使用)

基于数据库的号段模式(重点)

号段模式是当下分布式ID生成器的主流实现方式之一,号段模式可以理解为从数据库批量的获取自增ID,每次从数据库取出一个号段范围,例如 (1,1000] 代表1000个ID,具体的业务服务将本号段,生成1~1000的自增ID并加载到内存。表结构如下:

CREATE TABLE id_generator (

id int(10) NOT NULL,

max_id bigint(20) NOT NULL COMMENT '当前最大id',

step int(20) NOT NULL COMMENT '号段的布长',

biz_type int(20) NOT NULL COMMENT '业务类型',

version int(20) NOT NULL COMMENT '版本号',

PRIMARY KEY (id)

)

biz_type :代表不同业务类型

max_id :当前最大的可用id

step :代表号段的长度

version :是一个乐观锁,每次都更新version,保证并发时数据的正确性

等这批号段ID用完,再次向数据库申请新号段,对max_id字段做一次update操作,update max_id= max_id + step,update成功则说明新号段获取成功,新的号段范围是(max_id ,max_id +step]。

update id_generator set max_id = #{max_id+step}, version = version + 1 where version = # {version} and biz_type = XXX

由于多业务端可能同时操作,所以采用版本号version乐观锁方式更新,这种分布式ID生成方式不强依赖于数据库,不会频繁的访问数据库,对数据库的压力小很多。

雪花算法

雪花算法(Snowflake)是twitter公司内部分布式项目采用的ID生成算法,开源后广受国内大厂的好评,在该算法影响下各大公司相继开发出各具特色的分布式生成器。

Snowflake生成的是Long类型的ID,一个Long类型占8个字节,每个字节占8比特,也就是说一个Long类型占64个比特。

Snowflake ID组成结构:正数位(占1比特)+ 时间戳(占41比特)+ 机器ID(占5比特)+ 数据中心(占5比特)+ 自增值(占12比特),总共64比特组成的一个Long类型。

第一个bit位(1bit):Java中long的最高位是符号位代表正负,正数是0,负数是1,一般生成ID都为正数,所以默认为0。

时间戳部分(41bit):毫秒级的时间,不建议存当前时间戳,而是用(当前时间戳 - 固定开始时间戳)的差值,可以使产生的ID从更小的值开始;41位的时间戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年

工作机器id(10bit):也被叫做workId,这个可以灵活配置,机房或者机器号组合都可以。

序列号部分(12bit),自增值支持同一毫秒内同一个节点可以生成4096个ID

根据这个算法的逻辑,只需要将这个算法用Java语言实现出来,封装为一个工具方法,那么各个业务应用可以直接使用该工具方法来获取分布式ID,只需保证每个业务应用有自己的工作机器id即可,而不需要单独去搭建一个获取分布式ID的应用。

nowFlake可以保证:
优缺点:

  • 同一台服务器所有生成的id按时间趋势递增
    整个分布式系统内不会产生重复id(因为有datacenterId和workerId来做区分)
    存在的问题:
  • 机器ID(5位)和数据中心ID(5位)配置没有解决,分布式部署的时候会使用相同的配置,任然有ID重复的风险。
  • 使用的时候需要实例化对象,没有形成开箱即用的工具类。
  • 强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。(这点在正常情况下是不会发生的)

作者:程序员内点事 链接:

https://juejin.im/post/5e48a9af6fb9a07cc200c203

来源:掘金

相关推荐
ModelWhale19 分钟前
“大模型”技术专栏 | 浅谈基于 Kubernetes 的 LLM 分布式推理框架架构:概览
分布式·kubernetes·大模型
愿天堂没有C++1 小时前
C++——分布式
分布式
UPToZ1 小时前
【Docker】搭建一个高性能的分布式对象存储服务 - MinIO
分布式·docker·容器
前端世界14 小时前
鸿蒙任务调度机制深度解析:优先级、时间片、多核与分布式的流畅秘密
分布式·华为·harmonyos
A尘埃14 小时前
金融项目高可用分布式TCC-Transaction(开源框架)
分布式·金融·开源
夜影风15 小时前
RabbitMQ核心架构与应用
分布式·架构·rabbitmq
电商API_1800790524720 小时前
大规模调用淘宝商品详情 API 的分布式请求调度实践
服务器·数据库·分布式·爬虫
Light601 天前
模型驱动与分布式建模:技术深度与实战落地指南
分布式·生成式ai·元模型·crdt·模型驱动架构·分布式建模
斯普信专业组1 天前
Rabbitmq+STS+discovery_k8s +localpv部署排坑详解
分布式·kubernetes·rabbitmq
愚昧之山绝望之谷开悟之坡2 天前
Kafka 的消费
分布式·kafka