在我们业务数据量不大的时候,单库单表完全可以支撑现有业务,数据再大一点搞个MySQL主从同步读写分离也能对付。
但随着数据日渐增长,主从同步也扛不住了,就需要对数据库进行分库分表,但分库分表后需要有一个唯一ID来标识一条数据,数据库的自增ID显然不能满足需求;例如我们的订单,需要有一个全局唯一标识的订单号,这个订单号就是分布式ID
String uuid = UUID.randomUUID().toString().replaceAll("-","");
优点:
缺点:
基于数据库的auto_increment自增ID也可以生成一个分布式ID
优点:
缺点:
为了解决第二种数据库单个DB的风险,可以采用数据库集群的模式来解决这个问题。
号段模式是当下分布式ID生成器的主流实现方式之一,号段模式可以理解为从数据库批量的获取自增ID,每次从数据库取出一个号段范围,例如 (1,1000] 代表1000个ID,具体的业务服务将本号段,生成1~1000的自增ID并加载到内存,典型的是TinyID。表结构如下:
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`)
)
等这批号段ID用完,再次向数据库申请新号段,对max_id字段做一次update操作,update max_id= max_id + step,update成功则说明新号段获取成功,新的号段范围是(max_id ,max_id +step]。
SQL语句:
update id_generator set max_id = #{max_id+step} where biz_type = XXX
为了解决并发更新的问题,使用乐观锁控制,优化后的SQL:
update id_generator set max_id = #{max_id+step}, version = version + 1 where version = # {version} and biz_type = XXX
优点:
Redis也同样可以实现,原理就是利用redis的 incr命令实现ID的原子性自增。
Redis是内存数据库,需要考虑持久化的问题,redis有两种持久化方式RDB和AOF
雪花算法(Snowflake)是twitter公司内部分布式项目采用的ID生成算法,开源后广受国内大厂的好评,在该算法影响下各大公司相继开发出各具特色的分布式生成器。
Snowflake生成的是Long类型的ID,一个Long类型占8个字节,每个字节占8比特,也就是说一个Long类型占64个比特。
Snowflake ID组成结构:正数位(占1比特)+ 时间戳(占41比特)+ 机器ID(占5比特)+ 数据中心(占5比特)+ 自增值(占12比特),总共64比特组成的一个Long类型。
Snowflake雪花算法最核心的是中间的10位工作机器ID的分配,做到自动生成workID,避免运维人员的去分配
优点:
缺点:
根据算法的思路,使用java语言可以直接生成一个工具类,进行本地调用用来生成全局唯一的ID,
参考github地址:https://github.com/beyondfengyu/SnowFlake
Tinyid由滴滴开发,Github地址:https://github.com/didi/tinyid
Tinyid是基于号段模式每个服务获取一个号段(1000,2000]、(2000,3000]、(3000,4000]
1:具体实现原理:
2:架构图
提供了两种接入方式:
优点:
缺点:
UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器。Github地址:https://github.com/baidu/uid-generator
UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略, 从而适用于docker等虚拟化环境下实例自动重启、漂移等场景, UidGenerator通过借用未来时间来解决sequence天然存在的并发限制; 采用RingBuffer来缓存已生成的UID, 并行化UID的生产和消费。
具体算法实现:
Snowflake算法:
Snowflake算法描述:指定机器 & 同一时刻 & 某一并发序列,是唯一的。据此可生成一个64 bits的唯一ID(long)。默认采用上图字节分配方式:
Leaf由美团开发,github地址:https://github.com/Meituan-Dianping/Leaf
同时支持号段模式和Snowflake算法模式,可以切换使用。
1:Leaf-segment号段模式:
在使用数据库的方案上,做了如下改变:
号段模式的具体实现思路同TinyID一样
2:Leaf-snowflake雪花算法:
完全沿用snowflake方案的bit位设计,即是“1+41+10+12”的方式组装ID号。为了解决集权下workID的问题,美团的Leaf-snowflake跟百度不一样,百度是通过数据库来生成workID,而美团是通过Zookeeper持久顺序节点的特性自动对snowflake节点配置wokerID,所以Leaf是依赖ZK服务的。
特点: