加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

Java技醒目货分享:浅谈订单号天生存划方案

发布时间:2019-08-15 19:32:36 所属栏目:建站 来源:IT技术分享
导读:最简朴的方法 基于数据库 auto_increment_increment 来获取 ID。起首在数据库中建设一张 sequence 表,个中 seq_name 用以区分差异营业标识,从而实现支持多种营业场景下的自增 ID, current_value 为当前值, _increment 为步长,可支持漫衍式数据库的哈
副问题[/!--empirenews.page--]

 Java技醒目货分享:浅谈订单号天生存划方案

最简朴的方法

基于数据库 auto_increment_increment 来获取 ID。起首在数据库中建设一张 sequence 表,个中 seq_name 用以区分差异营业标识,从而实现支持多种营业场景下的自增 ID, current_value 为当前值, _increment 为步长,可支持漫衍式数据库的哈希计策。

  1. CREATE TABLE `sequence` (  
  2. `seq_name` varchar(200) NOT NULL,  
  3. `current_value` bigint(20) NOT NULL, 
  4. `_increment` int(4) NOT NULL,  
  5. PRIMARY KEY (`seq_name`)  
  6. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 

通过 SELECT LAST_INSERT_ID() 要领,更新 sequence 表,举办 ID 递增,并同时获取前次更新的值。这里留意, current_value = LAST_INSERT_ID(current_value + _increment) 将更新的 ID 赋值给了 LAST_INSERT_ID ,不然返回的将是行 id。

  1. UPDATE sequence 
  2. SET 
  3. current_value = LAST_INSERT_ID(current_value + _increment) 
  4. WHERE 
  5. seq_name = #{seqName} 

最后 Dao 提供处事,必要提示的是留意数据库的事宜断绝级别,假如将 getSeq() 要领放到 Service 中有事宜的要领里,将呈现题目,由于数据库事宜开启会建设一张视图,在事宜没有提交之前,更新的 ID 还没有被提交到数据库中,这在多线程并发操纵的环境下,假如事宜里的其他要教育致机能慢了,也许呈现两个哀求获取到沟通的 ID,以是办理要领一是不要将 getSeq() 要领放到有事宜的要领里,另一种就是将 getSeq() 要领的断绝界别为 PROPAGATION_REQUIRES_NEW ,实现开启新事宜,外层事宜不会影响内部事宜的提交。

  1. @Autowired  
  2. private SeqDao seqDao; 
  3. @Autowired  
  4. private PlatformTransactionManager transactionManager;  
  5. @Override  
  6. public long getSeq(final String seqName) throws Exception {  
  7. TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);  
  8. // 事宜举动,独立于外部事物独立运行 
  9. transactionTemplate 
  10. .setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);  
  11. return (Long) transactionTemplate.execute(new TransactionCallback() {  
  12. public Object doInTransaction(TransactionStatus status) {  
  13. try {  
  14. Seq seq = new Seq();  
  15. seq.setSeqName(seqName);  
  16. if (seqDao.update(seq) == 0) { 
  17. throw new RuntimeException("seq update failure.");  
  18. }  
  19. return seq.getId();  
  20. } catch (Exception e) { 
  21. throw new RuntimeException("seq update error.");  
  22. }  
  23. }  
  24. });  

稍伟大一点的要领

上述的要领的题目,想必各人都知道,就是每次获取 ID 都要挪用数据库,在高并发的环境下会对数据库发生极大的压力,我们的改造要领也很简朴,就是一次申请一个段的 ID,然后发到内存里,每次获取 ID 先从内存里取,当内存中的 ID 段所有被获取完毕,则再一次挪用数据库从头申请一个新的 ID 段。

同样稀有据库表的计划,通过 Name 区分营业,用 ID 标明已经申请到的最大值。虽然假如是漫衍式架构,也可以通过增进步长属性来实现。

  1. CREATE TABLE `sequence_value` (  
  2. `Name` varbinary(50) DEFAULT NULL,  
  3. `ID` int(11) DEFAULT NULL  
  4. ) ENGINE = InnoDB DEFAULT CHARSET = utf8 

Step 是 ID 段的内存工具,有两个属性,个中 currentValue 当前的行使到的值,endValue 是内存申请的最大值。

  1. class Step {  
  2. private long currentValue;  
  3. private long endValue;  
  4. Step(long currentValue, long endValue) {  
  5. this.currentValue = currentValue;  
  6. this.endValue = endValue;  
  7. }  
  8. public void setCurrentValue(long currentValue) {  
  9. this.currentValue = currentValue;  
  10. }  
  11. public void setEndValue(long endValue) {  
  12. this.endValue = endValue;  
  13. }  
  14. public long incrementAndGet() {  
  15. return ++currentValue;  
  16. }  

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读