• 唯一主键方案之数据库维护区间分配


    我们介绍一种基于数据库维护自增 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

  • 相关阅读:
    使用Mockito进行单元测试【2】—— stub 和 高级特性[转]
    使用Mockito进行单元测试【1】——mock and verify[转]
    一个更加简洁的 建造者模式
    建造者模式
    另一种 模板模式
    模板模式
    适配器模式的另一种解释
    适配器模式
    迭代器模式
    迭代器模式 循环数组
  • 原文地址:https://www.cnblogs.com/jmcui/p/14872603.html
Copyright © 2020-2023  润新知