美文网首页
MySQL ID生成策略

MySQL ID生成策略

作者: MikeMiao | 来源:发表于2018-06-29 13:55 被阅读0次

    简介

    随着微服务框架的逐步应用,分布式ID生成策略要支持高并发、有序性、易读性。常用方案有UUID、GUID、Redis、MongoDB等,本次只提供数据库生成方式。作为平台框架基于适配原则提供数据库层面的选择,以下为具体的设计。

    1. 可适用于ID持续增长,固定编码长度,不足补零。
    2. 可适用于每天、每月、每年阶段性的清零自增长。
    3. 可指定编码的前缀、后缀。
    4. 阶段性的清零操作无需定时任务。

    创建表结构

    CREATE TABLE `tb_ids` (
      `ID` int(11) DEFAULT NULL COMMENT '编码',
      `object` varchar(100) DEFAULT NULL COMMENT '对象',
      `segment` varchar(100) DEFAULT NULL COMMENT '切分段落',
      `prefix` varchar(10) DEFAULT NULL COMMENT '前缀',
      `format` varchar(50) DEFAULT NULL COMMENT '段落格式',
      `length` int(11) DEFAULT NULL COMMENT '数字长度',
      `sequence` int(11) DEFAULT NULL COMMENT '当前序列',
      `suffix` varchar(10) DEFAULT NULL COMMENT '后缀',
      `type` int(11) DEFAULT NULL COMMENT '类型[1:持续累计;2:阶段性累计]'
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    

    初始化数据

    1. 指定前缀,按日重新累计;
    2. 指定前缀,从1开始一直累加;
    3. 指定前缀,按年月重新累计;
    4. 指定前缀,按两位年份重新累计;
    INSERT INTO `tb_ids` VALUES ('1', 'ORDER', '20180629', 'R', '%Y%m%d', '6', '0', '', '2');
    INSERT INTO `tb_ids` VALUES ('2', 'USER', null, 'U', '', '6', '0', '', '1');
    INSERT INTO `tb_ids` VALUES ('3', 'SALE', '201806', 'SO', '%Y%m', '6', '0', '', '2');
    INSERT INTO `tb_ids` VALUES ('5', 'YEAR', '18', 'Y', '%y', '6', '0', '', '2');
    

    创建函数

    CREATE  FUNCTION `sequnce`(in_object VARCHAR(50)) RETURNS varchar(200) CHARSET utf8
    BEGIN
    #定义下个编码变量
    DECLARE next VARCHAR (100);
    #定义是否同段内的编码,如果不是从1开始。
    DECLARE is_same_segment TINYINT (1);
    
    #如果是连续递增的编码,设置为是同一段的编码
    SELECT
        (t.type = 1 )  INTO is_same_segment
    FROM
        tb_ids t
    WHERE
        t.object = in_object  ;
    
    #如果不是连续递增的编码,查询现在时间和上次编码生成时间是否同一个段落
    if (!is_same_segment) then 
        SELECT
            t.segment = DATE_FORMAT(NOW(), t.format) INTO is_same_segment
        FROM
            tb_ids t
        WHERE
            t.object = in_object  ;
    end if;
    
    #更新编码,如果统一段落加一,否则从一开始;更新此次编码生成的段落;
    UPDATE tb_ids t
        SET t.sequence = (
            CASE
            WHEN !is_same_segment THEN # 不同段落从1开始
                1
            ELSE # 相同段落累计
                sequence + 1
            END
        ),
        t.segment = DATE_FORMAT(NOW(), t.format)
    WHERE
        object = in_object  ;
    
    # 根据前缀、段落、序号,后缀生成编码
    SELECT
        CONCAT(
            IFNULL(t.prefix,''),#前缀
            IFNULL(DATE_FORMAT(NOW(), t.format),''),#段落
            LPAD(sequence, t.length, 0),#序列
            IFNULL(t.suffix,'')#后缀
        ) INTO next
    FROM
        tb_ids t
    WHERE
        t.object = in_object  ;
    
    RETURN next;
    
    END
    

    测试

    image.png

    相关文章

      网友评论

          本文标题:MySQL ID生成策略

          本文链接:https://www.haomeiwen.com/subject/chqayftx.html