美文网首页
提高基于DB的ID生成性能方案-IDSnowman

提高基于DB的ID生成性能方案-IDSnowman

作者: MarkZhu | 来源:发表于2017-01-15 15:59 被阅读0次
    ID Snow Man

    背景:

    分布式需求下的ID生成方案有很多种。但满足以下条件的不多:
    1、除现有的DB外,不增加运维负担和不增加基础设施的资源要求
    2、ID大体趋势递增(实际情况中一般不需要严格递增,即使是用AUTO_INCREMENT字段,也因事务提交顺序和rollback问题不会严格递增)
    3、ID种子状态需要持久化

    词汇:

    OSP:唯品会服务化基础平台
    Saturn:唯品会分布式JOB平台
    VMS:唯品会MQ平台

    基于AUTO_INCREMENT字段的方案

    基于现有应用环境,用DB实现以上需求可能是比较简单的方案。
    基于mysql的持久化和协调,可以有两个方案:
    1、建立带AUTO_INCREMENT字段的表,用AUTO_INCREMENT机制生成ID。
    有两个子方案:
    1a:获取ID时,insert into 然后 last_insert_id
    1b:加入唯一索引字段,获取ID时,replace into(唯一字段名) values ('重复的唯一字段值') 然后 last_insert_id。

    方案1b的好处是保证数据库中只有和行记录,不需要定期归档数据。
    基于AUTO_INCREMENT字段问题是:在高并发情况下生成ID相关的并发数、TPS数要求与数据一致。在业务已经分库,但ID生成没分库的情况下,势必成为瓶颈。
    解决方法是:
    1、把AUTO_INCREMENT字段的表也分库,按一定策略路由ID生成请求到不同的库。库与库进行ID号的隔离,方法可以是:
    a. AUTO_INCREMENT中不同的大初始号段
    b. AUTO_INCREMENT相同步长(如32),不同的初始值
    以上分库方法的问题是可能使ID大体趋势不是递增。

    批量号段派发方案-IDSnowman

    如果应用和DB的一次交互可以拿到一批连续ID,而且拿到ID有使用有效期。这样既可以减少DB TPS、并发、连接数,也可以提高ID的生成的平均时效。

    DB表结构

    CREATE TABLE `sequence_table` (
        `biz_type` VARCHAR(50) NOT NULL COMMENT '业务类型',
        `cur_id` BIGINT(20) NOT NULL COMMENT '当前值',
        `step` INT(11) NOT NULL COMMENT '步长',
        `time_to_live` INT(11) NOT NULL COMMENT '生存时长(秒)',
        PRIMARY KEY (`biz_type`)
    )
    COLLATE='utf8_general_ci'
    ENGINE=InnoDB;
    

    架构设计

    架构图

    说明:
    每个应用的业务线程池中,维护一个线程本地变量,IDBuffer,其结构大体如下:

    线程本地ID Buffer : [
    占用相关: {batch_max_id=800, cur_id=601, birthday="20170115 03:02:01"}
    调整相关:{……}]
    

    每个业务类型记录其当前批次的最大值,当前值,批次发放时间。

    具体的实时顺序图:

    具体的实时顺序图

    说明:
    ID生成库使用与业务分享独立的DB连接池,DB连接的事务为autocommit=1。即不使用事务。
    注意到其中的LAST_INSERT_ID(cur_id + Step) 。函数为设计DB连接的会话本地last_insert_id变量,不影响其它会话(见:http://dev.mysql.com/doc/refman/5.6/en/information-functions.html#function_last-insert-id)。

    这样,DB的TPS、并发、连接数可以因批次步长和批次有效时间的大小而数倍下降。ID也大体趋势递增。
    封装方法
    可以封装为OSP服务(好处是减少DB连接数)。或一个公共JAR(好处是减少运行服务依赖),由应用控制DB连接池。

    单点问题 single point of failure (SPOF)

    由DB决定。为DBA保障。

    封装讨论

    实现上,是否真有需要跨表的唯一顺序ID生成需求。这是值得考虑的。如果没有这个需求,事情可以简单很多。

    [参考文章]

    http://code.flickr.net/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/
    http://dev.mysql.com/doc/refman/5.6/en/information-functions.html#function_last-insert-id
    https://my.oschina.net/CandyDesire/blog/619122
    http://tech.meituan.com/mtddl.html

    ID Snow Man

    相关文章

      网友评论

          本文标题:提高基于DB的ID生成性能方案-IDSnowman

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