为什么需要分布式ID
在业务量不大的时候,单库单表就可以支持现有的业务,随着数据量的增多,我们可能就需要分库分表,分库分表后如果依然使用自增ID那么就会容易造成ID重复,所以就需要分布式ID。分布式ID就是全局唯一ID。
分布式ID实现思路
既然数据库里面存在自增ID这种方式,那么我们就会想到最为简单的一种分布式ID的实现方式,我们单独维护一张表,当我们需要一个ID的时候,就插入一条数据继而得到ID。
这种方式有一个缺陷,那就是频繁的操作数据库,性能瓶颈会落在数据库这里。
我们可以对这种方式进行改进,我们每次取ID的时候,不再取一个ID,而是取批量的ID,然后再将批量ID保存到内存中,操作内存肯定是比数据库快,等内存中的ID使用完以后,在到数据库中取批量的ID,如此往复。
这种取分布式ID的方式叫做数据库号段模式。
分布式ID实现细节
1,数据库建表语句
CREATE TABLE `sequence_value` (
`id` bigint(20) NOT NULL,
`name` varchar(20) NOT NULL COMMENT '场景名称',
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2,核心步骤
a.根据场景名称获取对应id
select id from sequence_value where name = 'test'
a_1.若场景名称没有对应的id,则步骤a_2
a_2.插入数据,并给场景名称对应id赋值为0
insert into sequence_value(id, name) values(0, 'test')
a_3.存在对应id,执行步骤b
b.得到场景名称的对应id以后,用旧id值 + stepSize(步长) 去更新 场景名称对应的id值,这里会使用乐观锁来确保并发数据的正确性
update sequence_value set id = 旧id + stepSize where name = 'test' and id = 旧id
b_1.若更新成功,则表示获取到批量id,当 旧id~~旧id + stepSize 这个范围里面的id使用完了以后在去数据库取批量id,步骤依然是a到b
b_2.若更新失败,则表示批量获取id失败,那么则需要重新执行步骤a到步骤b
3,源代码地址
https://gitee.com/chenxinfan/distributed_id