唯一主键方案之数据库维护区间分配
Posted JMCui
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了唯一主键方案之数据库维护区间分配相关的知识,希望对你有一定的参考价值。
我们介绍一种基于数据库维护自增 ID 区间,结合内存分配的策略,这也是淘宝的 TDDL 等数据库中间件使用的主键生成策略。
使用这种方式首先在数据库中创建 sequence 表,其中的每一行,用于记录某个业务主键当前已经被占用的 ID 区间的最大值。sequence 表的主要字段是 name 和 value,其中 name 是当前业务序列的名称,value 存储已经分配出去的 ID 最大值。
CREATE TABLE `sequence_global` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT \'Id\',
`app_name` varchar(64) NOT NULL COMMENT \'sequence name\',
`app_value` bigint(32) NOT NULL COMMENT \'sequence current value\',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT \'创建时间\',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT \'修改时间\',
PRIMARY KEY (`id`),
UNIQUE KEY `unique_name` (`app_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
接下来插入一条行记录,当需要获取主键时,每台服务器主机从数据表中取对应的 ID 区间缓存在本地,同时更新 sequence 表中的 value 最大值记录。
现在我们新建一条记录,比如设置一条 order 更新的规则,插入一行记录如下:
INSERT INTO sequence_global(app_name,app_value,create_time,update_time) values(\'test\',200,now(),now());
当服务器在获取主键增长区段时,首先访问对应数据库的 sequence 表,更新对应的记录,占用一个对应的区间。比如我们这里设置步长为 200,原先的 value 值为 1000,更新后的 value 就变为了 1200。
取到对应的 ID 区间后,在服务器内部进行分配,涉及的并发问题可以依赖乐观锁等机制解决。
有了对应的 ID 增长区间,在本地就可以使用 AtomicInteger 等方式进行 ID 分配。
不同的机器在相同时间内分配出去的 ID 可能不同,这种方式生成的唯一 ID,不保证严格的时间序递增,但是可以保证整体的趋势递增,在实际生产中有比较多的应用。
为了防止单点故障,sequence 表所在的数据库,通常会配置多个从库,实现高可用。
参考代码实现:https://github.com/JMCuixy/dubbo-demo/tree/master/sequence
以上是关于唯一主键方案之数据库维护区间分配的主要内容,如果未能解决你的问题,请参考以下文章
我爱java系列之---分布式ID生成解决方案:UUIDRedis生成idsnowflake