1.数据库自增ID
描述
自增Id是在设计表时将id字段的值设置为自增的形式,这样当插入一行数据时无
需指定id会自动根据前一字段的Id值+1进行填充
优点
主键自动增长,不用手工设值、数字型,占用空间小、检索非常有利、有顺序,不会重复。
缺点:
并发性能不高,受限于数据库性能、不太适合重构的系统,因为涉及旧数据迁移容易Id冲突,还有
外键要考虑、新旧系统上线同时运行,数据涉及双写容易Id冲突。
适用场景:
在互联网公司,对于高并发业务,一般的表主键都是采用数据库自增,即使采用分库分表,也是
设置主键自增,原因是:一般表的主键不参与业务处理, 比较常见的设计方式是业务表加一个
业务唯一健,而且唯一健不能改变,其他业务表关联这个表的唯一键参与各种逻辑处理。例如:
券表:券Id、券号----活动表:活动Id、活动code-----活动发送记录表:
记录Id、mobile、活动code、券号
2.UUID生成ID
描述
UUID是通用唯一标识码的缩写,集群全局唯一不会重复,UUID是基于当前时间、计
数器、机器的mac地址等数据计算生成的。
优点
本地生成没有网络IO,性能好、全局唯一不重复、使用简单不用引入中间件。
缺点:
UUID占用16个字符,空间占用较多,如果是千万级别甚至亿级别特别费空间、不
是递增的而且无序、随机写入索引性能下降。
适用场景:
对表空间没太多限制、重构类系统、UUID不作为查询字段的非高并发系统、集群
部署的中间件唯一Id。
3.Redis生成ID
描述
Redis计数器,原子性自增,调用incr、incrBy方法。
优点
并发性能高,有顺序、生成Id格式可以自定义,例如前缀+yyyyMMdd+5位自增。
缺点:
使用场景有限、因为自增,数据量容易被猜到,不安全、引入中间件、redis集群
部署需要保证高可用成本高。
适用场景:
生成Id要求自增、高性能、适合运营管理后台唯一Id生成,例如活动编号。
4.雪花算法生成ID
描述:
Twitter开源的分布式ID生成算法,主要是由64bit的long型生成的全局ID,引入
了时间戳和ID保持自增的属性,组成结构如下:
1bit(1:负数,0:正数)
41bit(时间戳)
5bit(表示机房Id,2^5个机房-32个机房)
5bit(表示机器Id,2^5个机器-32个机器)
12bit(序列号, 这个是用来记录同一个毫秒内产生的不同id,4096)
优点:
不依赖外部组件、性能好、按时间递增。
缺点:
机房+机器设置不合理高并发下可能会重复(应用启动机房Id、机器ID作为启动参
数传递保证唯一)、有时钟回拨的坑。
例如:729786672057983180、729786672057983181
适用场景:
互联网高并发系统
百度UidGenerator算法
描述:
UidGenerator是Java实现的, 基于Snowflake算法的唯一ID生成器。
UidGenerator以组件形式工作在应用项目中, 支持自定义workerId位数和初始化策略,
从而适用于k8s环境下实例自动重启、IP漂移等场景。
优点:
在实现上, UidGenerator通过借用未来时间来解决sequence天然存在的并发限制;
采用RingBuffer来缓存已生成的Uid, 并行化Uid的生产和消费, 同时对CacheLine补齐,
避免RingBuffer带来的伪共享问题. 最终单机QPS可达600万。
缺点:
非高并发业务不适合
适用场景:
互联网高并发系统
Leaf
描述
什么是Leaf
全局唯一,绝对不会出现重复的ID,且ID整体趋势递增。
高可用,服务完全基于分布式架构,即使MySQL宕机,也能容忍一段时间的数据库不可用。
高并发低延时,在CentOS 4C8G的虚拟机上,远程调用QPS可达5W+,TP99在1ms内。
接入简单,直接通过公司RPC服务或者HTTP调用即可接入。
leaf是叶子的意思,使用的Leaf是美团公司开源的一个分布式序列号(id)生成系统
我们可以在Github网站上下载项目直接使用
更多介绍可以参考官方信息:
官方介绍地址:Leaf——美团点评分布式ID生成系统 - 美团技术团队
github:GitHub - Meituan-Dianping/Leaf: Distributed ID Generate Service
为什么需要Leaf
上面的图片中
是一个实际开发中常见的读写分离的数据库部署格式
专门进行数据更新(写)的有两个数据库节点
它们同时新增数据可能产生相同的自增列id
一旦生成相同的id,数据同步就会有问题
会产生id冲突,甚至引发异常
我们为了在这种多数据库节点的环境下能够产生唯一id
可以使用Leaf来生成
Leaf的工作原理
Leaf底层支持通过"雪花算法"生成不同id
我们使用的是单纯的序列
要想使用,需要事先设置好leaf的起始值和缓存id数
举例,从1000开始缓存500
也就是从id1000~1499这些值,都会保存在Leaf的内存中,当有服务需要时,直接取出下一个值
取出过的值不会再次生成,当缓存的数据取完时,会往后再缓存500个,从1500-1999
leaf要想设置起始值和缓存数
需要给leaf创建一个指定格式的数据库表
运行过程中会从数据库表获取信息
我们当前的信息保存在leafdb.leaf_alloc表中
leafdb.leaf_alloc代码
USE `leafdb`;
DROP TABLE IF EXISTS `leaf_alloc`;
CREATE TABLE `leaf_alloc` (
`biz_tag` varchar(128) NOT NULL DEFAULT '' COMMENT '业务key',
`max_id` bigint NOT NULL DEFAULT '1' COMMENT '当前已经分配了的最大id',
`step` int NOT NULL COMMENT '初始步长,也是动态调整的最小步长',
`description` varchar(256) DEFAULT NULL COMMENT '业务key的描述',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '数据库维护的更新时间',
PRIMARY KEY (`biz_tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
/*Data for the table `leaf_alloc` */
insert into `leaf_alloc`(`biz_tag`,`max_id`,`step`,`description`,`update_time`) values
('admin',1000,1000,'测试','2021-12-29 09:43:09'),
('cart',1000,1000,'测试','2022-02-22 14:32:21'),
('order',5000,1000,'测试','2022-02-28 16:28:42'),
('order_item',5000,1000,'测试','2022-02-28 16:28:42'),
('sku',8000,1000,'测试','2022-03-07 17:29:01'),
('spu',7000,1000,'测试','2021-12-13 14:59:56'),
('user',1000,1000,'测试','2022-02-22 14:31:56');
优点
支持号段模式和雪花算法:
号段模式依赖于数据库,但是区别于数据库主键自增的模式。假设100为一个号段
100,200,300,每取一次可以获得100个Id ,性能显著提高。
缺点:
非高并发业务不适合
适用场景:
互联网高并发系统