?

浅谈订单号生成的设计方案

作者:媒体转发 时间:2019-08-27 09:30

字号

今天讨论分享下订单号生成的简单实现方案,为实际场景中需要用到订单号生成服务提供解决思路。

浅谈订单号生成的设计方案

最简单的方式

基于数据库 auto_increment_increment 来获取 ID。首先在数据库中创建一张 sequence 表,其中 seq_name 用以区分不同业务标识,从而实现支持多种业务场景下的自增 ID,current_value 为当前值,_increment 为步长,可支持分布式数据库的哈希策略。

CREATE?TABLE?`sequence`?(?

`seq_name`?varchar(200)?NOT?NULL,?

`current_value`?bigint(20)?NOT?NULL,?

`_increment`?int(4)?NOT?NULL,?

??PRIMARY?KEY?(`seq_name`)?

)?ENGINE=InnoDB?DEFAULT?CHARSET=utf8?

通过 SELECT LAST_INSERT_ID() 方法,更新 sequence 表,进行 ID 递增,并同时获取上次更新的值。这里注意,current_value = LAST_INSERT_ID(current_value + _increment) 将更新的 ID 赋值给了 LAST_INSERT_ID,否则返回的将是行 id。

<insert?timeout="30"?id="update"?parameterType="Seq">?

????UPDATE?sequence?

????SET?

????current_value?=?LAST_INSERT_ID(current_value?+?_increment)?

????WHERE?

????seq_name?=?#{seqName}?

<selectKey?resultType="long"?keyProperty="id"?order="AFTER">?

?????????

selectKey>?

insert>?

最后 Dao 提供服务,需要提醒的是注意数据库的事务隔离级别,如果将 getSeq() 方法放到 Service 中有事务的方法里,将出现问题,因为数据库事务开启会创建一张视图,在事务没有提交之前,更新的 ID 还没有被提交到数据库中,这在多线程并发操作的情况下,如果事务里的其他方法导致性能慢了,可能出现两个请求获取到相同的 ID,所以解决方法一是不要将 getSeq() 方法放到有事务的方法里,另一种就是将 getSeq() 方法的隔离界别为 PROPAGATION_REQUIRES_NEW,实现开启新事务,外层事务不会影响内部事务的提交。

@Autowired?

private?SeqDao?seqDao;?

?

@Autowired?

private?PlatformTransactionManager?transactionManager;?

?

@Override?

public?long?getSeq(final?String?seqName)?throws?Exception?{?

????TransactionTemplate?transactionTemplate?=?new?TransactionTemplate(transactionManager);?

//?事务行为,独立于外部事物独立运行?

????transactionTemplate?

????????????.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);?

return?(Long)?transactionTemplate.execute(new?TransactionCallback()?{?

public?Object?doInTransaction(TransactionStatus?status)?{?

try?{?

????????????????Seq?seq?=?new?Seq();?

????????????????seq.setSeqName(seqName);?

if?(seqDao.update(seq)?==?0)?{?

throw?new?RuntimeException("seq?update?failure.");?

????????????????}?

return?seq.getId();?

????????????}?catch?(Exception?e)?{?

throw?new?RuntimeException("seq?update?error.");?

????????????}?

????????}?

????});?

}?

稍复杂一点的方法

责任编辑:CQITer新闻报料:400-888-8888 ? 本站原创,未经授权不得转载
关键词 >> 订单号生成,数据库,ID
继续阅读
热新闻
推荐
关于我们联系我们免责声明隐私政策 友情链接