xsequence分布式序列號(hào)生成組件
項(xiàng)目介紹
微服務(wù)時(shí)代,我們需要生產(chǎn)一個(gè)連續(xù)的序列號(hào),變得比較麻煩。這里使用了Mysql簡(jiǎn)單的實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的分布式序列號(hào)生成組件。后續(xù)還可以支持Redis等其他高效中間件。
軟件架構(gòu)
原理很簡(jiǎn)單,在mysql數(shù)據(jù)專門創(chuàng)建一張表,例如:
CREATE TABLE IF NOT EXISTS `sequence`( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主鍵id', `value` bigint(20) NOT NULL COMMENT 'sequence當(dāng)前值', `name` varchar(32) NOT NULL COMMENT 'sequence對(duì)應(yīng)的名稱,通常是表名', `gmt_create` DATETIME NOT NULL COMMENT '創(chuàng)建時(shí)間', `gmt_modified` DATETIME NOT NULL COMMENT '修改時(shí)間', PRIMARY KEY (`ID`) ,UNIQUE uk_name (`name`) );
每鐘業(yè)務(wù)類型創(chuàng)建一條記錄,value表示當(dāng)時(shí)取的區(qū)間值,例如當(dāng)前value值是100。 當(dāng)我們?cè)O(shè)置step長(zhǎng)為100時(shí),來(lái)取一次,就會(huì)update到value。然后程序節(jié)點(diǎn)就可以把這個(gè)100分配出去。
使用說(shuō)明
1.API方式使用
public class SequenceTest_Api {
private Sequence userSeq;
@Before
public void setup() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl("jdbc:mysql://121.196.218.206:3306/admin?characterEncoding=UTF-8");
dataSource.setUsername("admin");
dataSource.setPassword("admin123");
dataSource.setMaxActive(300);
dataSource.setMinIdle(50);
dataSource.setInitialSize(2);
dataSource.setMaxWait(500);
DbSeqRangeConfig seqRangeConfig = new DbSeqRangeConfig();
seqRangeConfig.setDataSource(dataSource);
seqRangeConfig.setTableName("sequence");
seqRangeConfig.setRetryTimes(100);
seqRangeConfig.setStep(1000);
seqRangeConfig.setStepStart(0);
DbSeqRangeMgr seqRangeMgr = new DbSeqRangeMgr();
seqRangeMgr.setSeqRangeConfig(seqRangeConfig);
seqRangeMgr.init();
userSeq = new DefaultSequence();
userSeq.setName("user");
userSeq.setSeqRangeMgr(seqRangeMgr);
}
@Test
public void test() {
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
System.out.println("++++++++++id:" + userSeq.nextValue());
}
System.out.println("interval time:" + (System.currentTimeMillis() - start));
}
}
2.Spring使用方式
(1)XML文件配置
<!-- 數(shù)據(jù)源 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="jdbc:mysql://121.196.218.206:3306/admin?characterEncoding=UTF-8"/> <property name="username" value="admin"/> <property name="password" value="admin123"/> <property name="maxActive" value="300"/> <property name="minIdle" value="50"/> <property name="initialSize" value="2"/> <property name="maxWait" value="500"/> </bean> <!-- 序列號(hào)步長(zhǎng)管理器配置 --> <bean id="seqRangeConfig" class="com.xuan.xseq.range.impl.db.DbSeqRangeConfig"> <!-- 數(shù)據(jù)源[必選] --> <property name="dataSource" ref="dataSource"/> <!-- 表名[可選] 默認(rèn):sequence--> <property name="tableName" value="sequence"/> <!-- 更新失敗重試次數(shù)[可選] 默認(rèn):100--> <property name="retryTimes" value="100"/> <!-- 每次取數(shù)步長(zhǎng)[可選] 默認(rèn):1000--> <property name="step" value="1000"/> <!-- 起始數(shù),注意真實(shí)開(kāi)始可用數(shù)是stepStart+1,例如stepStart=0表示從1開(kāi)始[可選] 默認(rèn):0--> <property name="stepStart" value="0"/> </bean> <!-- 序列號(hào)步長(zhǎng)管理器 --> <bean id="seqRangeMgr" class="com.xuan.xseq.range.impl.db.DbSeqRangeMgr" init-method="init"> <property name="seqRangeConfig" ref="seqRangeConfig"/> </bean> <!-- 具體使用demo --> <bean id="userSeq" class="com.xuan.xseq.seq.impl.DefaultSequence"> <property name="seqRangeMgr" ref="seqRangeMgr"/> <property name="name" value="user"/> </bean>
(2)API代碼使用
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:sequence-test.xml" })
public class SequenceTest_Spring {
@Autowired
private Sequence userSeq;
@Test
public void test() {
for (int i = 0; i < 100; i++) {
System.out.println("++++++++++id:" + userSeq.nextValue());
}
}
}
評(píng)論
圖片
表情
