微服务时代,我们需要生产一个连续的序列号,变得比较麻烦。这里使用了Mysql简单的实现了一个简单的分布式序列号生成组件。后续还可以支持Redis等其他高效中间件。
软件架构原理很简单,在mysql数据专门创建一张表,例如:
CREATE TABLE IF NOT EXISTS `sequence`( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键id', `value` bigint(20) NOT NULL COMMENT 'sequence当前值', `name` varchar(32) NOT NULL COMMENT 'sequence对应的名称,通常是表名', `gmt_create` DATETIME NOT NULL COMMENT '创建时间', `gmt_modified` DATETIME NOT NULL COMMENT '修改时间', PRIMARY KEY (`ID`) ,UNIQUE uk_name (`name`));每钟业务类型创建一条记录,value表示当时取的区间值,例如当前value值是100。当我们设置step长为100时,来取一次,就会update到value。然后程序节点就可以把这个100分配出去。
使用说明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文件配置
<!-- 数据源 --><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><!-- 序列号步长管理器配置 --><bean id="seqRangeConfig" class="com.xuan.xseq.range.impl.db.DbSeqRangeConfig"><!-- 数据源[必选] --><property name="dataSource" ref="dataSource"/><!-- 表名[可选] 默认:sequence--><property name="tableName" value="sequence"/><!-- 更新失败重试次数[可选] 默认:100--><property name="retryTimes" value="100"/><!-- 每次取数步长[可选] 默认:1000--><property name="step" value="1000"/><!-- 起始数,注意真实开始可用数是stepStart+1,例如stepStart=0表示从1开始[可选] 默认:0--><property name="stepStart" value="0"/></bean><!-- 序列号步长管理器 --><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()); } }}
评论