Tddl的分佈式Sequence

參考的版本是:tddl-sequence-3.2.jarjava

概述

  • 在GroupSequence調用nextValue()時,斷定當前GroupSequenceDao是否存在緩存值currentRange;
    • 有 :
      直接從currentRange經過 AtomicLong.getAndIncrement併發控制取nextValue;
    • 沒有:
      以ReentrantLock方式經過GroupSequenceDao的nextRange取指定sequence-name的數據庫表配置; 計算出新值 newValue =  oldValue + outStep ;  經過oldValue作樂觀鎖將新值newValue 更新進庫表(update sequence set value = ?, gmt_modified = ? where name = ? and value = ?),返回SequenceRange(newValue + 1, newValue + innerStep)。
      在指定的retryTime下重複獲取新的oldValue並執行計算,最終若失敗則拋出SequenceException。
  • GroupSequenceDao的innerStep 與outStep 很重要!
    • innerStep :控制緩存的最小值與最大值的範圍大小。 currentRange 的範圍是[newValue +1, newValue + innerStep ]
    • outStep : 控制更新數據庫sequnece的Value增加步長。 在GroupSequenceDao.init時   outStep =innerStep * dscount<數據源個數>;
       

使用方式

@Bean(name = "errorCenterIdSequence", initMethod = "init")
    public GroupSequence errorCenterIdSequence(SequenceDao sequenceDao) {
        GroupSequence sequence = new GroupSequence();
        sequence.setSequenceDao(sequenceDao);
        sequence.setName("seq_decision_exec_error_center_id");
        groupSequenceMap.putIfAbsent("seq_decision_exec_error_center_id", sequence);
        return sequence;
    }

    @Bean(initMethod = "init")
    public GroupSequenceDao idSequenceDao() {
        GroupSequenceDao idSequenceDao = new GroupSequenceDao();
        idSequenceDao.setAppName(appname);
        idSequenceDao.setDbGroupKeys(Lists.newArrayList(seqGroup));
        /*
         * 默認是sequence name value gmt_modified 
         * idSequenceDao.setDscount(2);
         * idSequenceDao.setInnerStep(1000); 
         * idSequenceDao.setRetryTimes(2);
         * idSequenceDao.setTableName("sequence");
         * idSequenceDao.setNameColumnName("name");
         * idSequenceDao.setValueColumnName("value");
         * idSequenceDao.setGmtModifiedColumnName("gmt_modified");
         */
        idSequenceDao.setAdjust(true);
        return idSequenceDao;
    }
  •  GroupSequenceDao.setAdjust(true); 
    設置的這個"adjust" 會在GroupSequence的初始化時經過GroupSequenceDao的adjust方法校驗sequence的name配置在數據庫表中,並斷定是否要自動插入表。
    private boolean check(int index, long value) {  
        return (value % outStep) == (index * innerStep); // 這裏不相等,就意味着outStep有調整過
    }
    
    // 具體調整
    newValue = (newValue - newValue % outStep) + outStep + index * innerStep;  
    // newValue - newValue % outStep 就是把數據縮減到最近一個能夠整除outStep的值,而後再加上一個outStep。
  • GroupSequenceDao 約定了sequence表名和表字段; 在init()時, dscount = max(dscount, 分庫數); 步長outStep  = innerStep * dscount 。

數據庫表:sql

CREATE TABLE `sequence` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `gmt_created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改時間',
  `name` varchar(64) DEFAULT NULL,
  `value` bigint(20) unsigned DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_sequence_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=100016 DEFAULT CHARSET=utf8 COMMENT='sequence生成器';

相關文章
相關標籤/搜索