前言:本文意在对借助db和程序生成分布式id进行一些总结,以及对其特性进行比较分析;
1 实现方式:
- Db 通过配置步长和初始值的方式,使得每个db库生成id 的不同性,如 3个db 实例情况下:其步长均设置为3 ,db1 的初始值为1 ,db2 的初始为2,db3的初始值为3,则db1 生成的id为:1,4,7…;db2 生成的id为:2,5,8… ;db3 生成的id为:3,6,9… ;
- 百度的分布式id 则为改进版的雪花id生成,通过每次项目启动时都插入一条id 为自增的int 值,插入成功后以主键id 作为生成雪花id 的workId,利用id 的自增性,保证workId 的唯一性;
- 滴滴的分段id,通过先获取一段id 的方式,在真正需要生成id 时,则每次+1 生成id,如果+1后超过了本段id 的最大值,则取下一段id,来继续生成id;
- leaf 的分段id 和滴滴的分段id 生成方式基本相同;leaf雪花算法id 则通过向zookeeper 注册持久有序节点的方式来获取本次生成id所需要的workId,因为注册的是持久有序节点,则保证了新服务workId 的唯一性,对于已有的服务,则通过ip+port 的方式来获取之前已经注册的workId;
2 优缺点:
2.1 db 步长方式生成id:
# 设置步长为100
auto-increment-increment=100
# 设置自增初始值 6
auto-increment-offset=6
优点:
- id 生成的服务均由db 服务器控制,程序可以不关心id 的生成,开发效率高效;
- id 生成和数据插入性能又有db自身决定,方式简单;
缺点:
- 对于有些db 步长和初始值的设置,要想重启db服务后依然生效,需要按照db服务实例级别完成设置,而且设置完成对此db实例的所有数据库都生效,影响范围较广;
- 多个db 服务实例,需要占用较多的服务资源,维护成本也相应提高;
- mybatis 每次插入失败,虽然没有插入成功,但是本次的id不会被下一次使用,会造成id 的一定浪费;
2.2 百度的分布式id:
优点:
- id 由程序本身控制,id 生成是可控的;
- 对外提供起始时间戳,workId可以 覆盖设置,比较灵活;
缺点:
- id由程序生成,需要保证程序的高可用,有一定的维护成本;
- workId 通过自增的主键确定,每次服务重启都会得到一个新的workId,老的workId会被舍弃,造成workId 的一定浪费,并且最多支持2^workId 位 次数的重启,超过改次数 workId又会从0 开始;
2.3 滴滴的分段id:
CREATE TABLE `tiny_id_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`biz_type` varchar(63) NOT NULL DEFAULT '' COMMENT '业务类型,唯一',
`begin_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '开始id,仅记录初始值,无其他含义。初始化时begin_id和max_id应相同',
`max_id` bigint(20) NOT NULL DEFAULT '0' COMMENT '当前最大id',
`step` int(11) DEFAULT '0' COMMENT '步长',
`delta` int(11) NOT NULL DEFAULT '1' COMMENT '每次id增量',
`remainder` int(11) NOT NULL DEFAULT '0' COMMENT '余数',
`create_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '创建时间',
`update_time` timestamp NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '更新时间',
`version` bigint(20) NOT NULL DEFAULT '0' COMMENT '版本号',
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_biz_type` (`biz_type`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='id信息表';
优点:
- id 由程序本身控制,id 生成是可控的;
- 提供了客户端方式获取id,获取较为方便,并且id可以根据业务进行隔离;
- 提高双段id 可以容忍id生成服务的短时不可用;
缺点:
- 每次获取到的分段id 会被存入到系统的内存中,一旦服务重启,重新获取新的分段id,老的的分段id即时没有被使用也会丢弃,会造成id 的一定浪费;
- id 的生成是顺序递增的,如果业务中用于订单的id ,可能会被使用当前id-昨天id ,从而取的订单量;
2.3 美团的leaf :
CREATE TABLE `leaf_alloc` (
`biz_tag` varchar(128) NOT NULL DEFAULT '',
`max_id` bigint(20) NOT NULL DEFAULT '1',
`step` int(11) NOT NULL,
`description` varchar(256) DEFAULT NULL,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`biz_tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
优点:
- id 由程序本身控制,id 生成是可控的;
- 分段id提高双段id 可以容忍id生成服务的短时不可用,并且可以安装业务进行隔离;
- 整合了分段id 和雪花算法id;
- 雪花算法中workId 通过向zookeeper注册持久有序的节点,来获取workId,避免了每次重启都要获取新的workId,避免了workId 的浪费;
缺点:
- 目前对外只提供了http 获取id 的方式,需要考虑网络的可靠性;
分段id: - 每次获取到的分段id 会被存入到系统的内存中,一旦服务重启,重新获取新的分段id,老的的分段id即时没有被使用也会丢弃,会造成id 的一定浪费;
- id 的生成是顺序递增的,如果业务中用于订单的id ,可能会被使用当前id-昨天id ,从而取的订单量;
雪花算法: - 使用了zookeeper进行节点的注册,所以需要保证zookeeper的服务可用性;