国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

淺談?dòng)唵翁?hào)生成的設(shè)計(jì)方案

開發(fā) 開發(fā)工具
今天討論分享下訂單號(hào)生成的簡單實(shí)現(xiàn)方案,為實(shí)際場景中需要用到訂單號(hào)生成服務(wù)提供解決思路。

今天討論分享下訂單號(hào)生成的簡單實(shí)現(xiàn)方案,為實(shí)際場景中需要用到訂單號(hào)生成服務(wù)提供解決思路。

[[274637]]

最簡單的方式

基于數(shù)據(jù)庫 auto_increment_increment 來獲取 ID。首先在數(shù)據(jù)庫中創(chuàng)建一張 sequence 表,其中 seq_name 用以區(qū)分不同業(yè)務(wù)標(biāo)識(shí),從而實(shí)現(xiàn)支持多種業(yè)務(wù)場景下的自增 ID,current_value 為當(dāng)前值,_increment 為步長,可支持分布式數(shù)據(jù)庫的哈希策略。

  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 表,進(jìn)行 ID 遞增,并同時(shí)獲取上次更新的值。這里注意,current_value = LAST_INSERT_ID(current_value + _increment) 將更新的 ID 賦值給了 LAST_INSERT_ID,否則返回的將是行 id。

  1. <insert timeout="30" id="update" parameterType="Seq"> 
  2.     UPDATE sequence 
  3.     SET 
  4.     current_value = LAST_INSERT_ID(current_value + _increment) 
  5.     WHERE 
  6.     seq_name = #{seqName} 
  7. <selectKey resultType="long" keyProperty="id" order="AFTER"> 
  8.         <![CDATA[SELECT LAST_INSERT_ID() ]]> 
  9. </selectKey> 
  10. </insert> 

最后 Dao 提供服務(wù),需要提醒的是注意數(shù)據(jù)庫的事務(wù)隔離級(jí)別,如果將 getSeq() 方法放到 Service 中有事務(wù)的方法里,將出現(xiàn)問題,因?yàn)閿?shù)據(jù)庫事務(wù)開啟會(huì)創(chuàng)建一張視圖,在事務(wù)沒有提交之前,更新的 ID 還沒有被提交到數(shù)據(jù)庫中,這在多線程并發(fā)操作的情況下,如果事務(wù)里的其他方法導(dǎo)致性能慢了,可能出現(xiàn)兩個(gè)請(qǐng)求獲取到相同的 ID,所以解決方法一是不要將 getSeq() 方法放到有事務(wù)的方法里,另一種就是將 getSeq() 方法的隔離界別為 PROPAGATION_REQUIRES_NEW,實(shí)現(xiàn)開啟新事務(wù),外層事務(wù)不會(huì)影響內(nèi)部事務(wù)的提交。

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

稍復(fù)雜一點(diǎn)的方法

上述的方法的問題,想必大家都知道,就是每次獲取 ID 都要調(diào)用數(shù)據(jù)庫,在高并發(fā)的情況下會(huì)對(duì)數(shù)據(jù)庫產(chǎn)生極大的壓力,我們的改進(jìn)方法也很簡單,就是一次申請(qǐng)一個(gè)段的 ID,然后發(fā)到內(nèi)存里,每次獲取 ID 先從內(nèi)存里取,當(dāng)內(nèi)存中的 ID 段全部被獲取完畢,則再一次調(diào)用數(shù)據(jù)庫重新申請(qǐng)一個(gè)新的 ID 段。同樣有數(shù)據(jù)庫表的設(shè)計(jì),通過 Name 區(qū)分業(yè)務(wù),用 ID 標(biāo)明已經(jīng)申請(qǐng)到的最大值。當(dāng)然如果是分布式架構(gòu),也可以通過增加步長屬性來實(shí)現(xiàn)。

  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 段的內(nèi)存對(duì)象,有兩個(gè)屬性,其中 currentValue 當(dāng)前的使用到的值,endValue 是內(nèi)存申請(qǐng)的最大值。

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

代碼的實(shí)現(xiàn)稍微復(fù)雜一點(diǎn),獲取 ID 會(huì)根據(jù)業(yè)務(wù)標(biāo)識(shí) sequencename,先從內(nèi)存獲取 Step 的 ID 段,如果為 null,則從數(shù)據(jù)庫中讀取當(dāng)前最新的值,并根據(jù)步長計(jì)算 Step,然后返回請(qǐng)求 ID。如果從內(nèi)存中直接獲取到 Step,則直接取 ID,并對(duì) currentValue 進(jìn)行加一。當(dāng) currentValue 的值超過 endValue 時(shí),則更新數(shù)據(jù)庫的 ID,重新計(jì)算 Step。

  1. private Map<String,Step> stepMap = new HashMap<String, Step>(); 
  2.  
  3. public synchronized long get(String sequenceName) { 
  4.     Step step = stepMap.get(sequenceName); 
  5. if(step ==null) { 
  6.         step = new Step(startValue,startValue+blockSize); 
  7.         stepMap.put(sequenceName, step); 
  8.     } else { 
  9. if (step.currentValue < step.endValue) { 
  10. return step.incrementAndGet(); 
  11.         } 
  12.     } 
  13. if (getNextBlock(sequenceName,step)) { 
  14. return step.incrementAndGet(); 
  15.     } 
  16. throw new RuntimeException("No more value."); 
  17.  
  18. private boolean getNextBlock(String sequenceName, Step step) { 
  19. // "select id from sequence_value where name = ?"; 
  20.     Long value = getPersistenceValue(sequenceName); 
  21. if (value == null) { 
  22. try { 
  23. // insert into sequence_value (id,name) values (?,?) 
  24. value = newPersistenceValue(sequenceName); 
  25.         } catch (Exception e) { 
  26. value = getPersistenceValue(sequenceName);  
  27.         } 
  28.     } 
  29. // update sequence_value set id = ?  where name = ? and id = ? 
  30.     boolean b = saveValue(value,sequenceName) == 1; 
  31. if (b) { 
  32.         step.setCurrentValue(value); 
  33.         step.setEndValue(value+blockSize); 
  34.     } 
  35. return b; 

使用該方法獲取 ID 可以減少對(duì)數(shù)據(jù)庫的訪問量,以降低數(shù)據(jù)庫的壓力,但是同樣需要注意,獲取 ID 同樣關(guān)注數(shù)據(jù)庫事務(wù)問題,因?yàn)楫?dāng)系統(tǒng)重啟的時(shí)候,stepMap 為 null,所以會(huì)取數(shù)據(jù)庫查詢當(dāng)前 ID,更計(jì)算更新 Step,然后更新數(shù)據(jù)庫的 ID。如果該方法被放到數(shù)據(jù)庫事務(wù)里,由于其他方法性能慢了,導(dǎo)致查詢之后沒有及時(shí)更新,并發(fā)情況下另一個(gè)線程查詢的時(shí)候,可能會(huì)獲取到該線程未提交的 ID,因而出現(xiàn)兩個(gè)線程獲取到相同的 ID 問題。

本文小結(jié)

訂單號(hào)生成是一個(gè)非常簡單的功能,但是在高并發(fā)的場景下,高性能和高可用就成為了需要關(guān)注的要點(diǎn)。所以,實(shí)際工作中的每一個(gè)小細(xì)節(jié)都值得我們?nèi)ド钏肌?/p>

【本文是51CTO專欄作者張開濤的原創(chuàng)文章,作者微信公眾號(hào):開濤的博客,id:kaitao-1234567】

戳這里,看該作者更多好文

 

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2019-08-15 11:11:38

Java數(shù)據(jù)庫設(shè)計(jì)

2021-07-01 06:58:12

高并發(fā)訂單號(hào)SCM

2025-01-02 09:06:43

2025-11-13 07:46:10

2024-10-14 12:05:56

2024-09-04 08:55:56

2020-10-21 12:10:30

訂單號(hào)Java代碼

2021-12-28 06:55:09

事故訂單號(hào)績效

2025-03-03 00:45:00

2024-10-17 08:26:53

ELKmongodb方案

2010-09-08 16:17:37

SIP協(xié)議棧

2009-10-12 16:50:00

2009-10-19 13:50:57

布線設(shè)計(jì)方案

2012-07-11 10:49:34

鮑爾默Surface

2022-07-05 09:38:47

模型RBACABAC

2012-08-17 11:01:52

設(shè)計(jì)方案

2010-02-25 15:30:47

SDRAMWindows CE

2017-07-10 17:25:40

開發(fā)單號(hào)高可用

2009-10-19 14:39:10

2019-03-13 16:09:47

VMware虛擬化服務(wù)器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

亚洲欧洲av| 国产麻豆日韩欧美久久| 岛国av在线一区| 97在线视频一区| 欧美日本网站| 久久天堂电影网| 国产精品㊣新片速递bt| 免费日本视频一区| 91嫩草视频在线观看| 国产精品一区免费在线| 在线观看日韩国产| 成人短视频在线| 韩国精品免费视频| 国产伦精品一区二区三区视频黑人 | 91免费视频网址| 亚洲一卡二卡三卡四卡无卡网站在线看| 大伊香蕉精品在线品播放| 自拍偷拍欧美视频| 四虎在线精品| 亚洲成色www8888| av黄色在线| 日韩欧美一级二级| 日本www在线观看| 51精品国自产在线| 亚洲综合图区| 亚洲国产精品成人av| 92久久精品| 国产宾馆实践打屁股91| 亚洲精品日韩精品| 成人动漫一区二区在线| 欧美精品第三页| 亚洲欧美综合网| 九色网友自拍视频手机在线| 亚洲黄色有码视频| 黄色小视频在线观看| 一本综合精品| 欧美一区二区三区四区高清| 欧美xxxx黑人又粗又长密月| 欧美另类xxx| 男人日女人下面视频| 国产真实乱对白精彩久久| 香蕉视频在线网址| 国产精品视频九色porn| 调教在线观看| 日韩欧美一区电影| 日韩精品一级| 亚洲伊人第一页| 三级理论午夜在线观看| 这里是久久伊人| 国产综合av| 欧美激情第三页| 欧美a级网站| 国产一区国产精品| 99re热这里只有精品视频| 麻豆影视在线| 国产精品1区2区| 欧美一级二区| 中文字幕乱码在线播放| 男男视频亚洲欧美| 97久久精品人搡人人玩| 91亚洲国产成人久久精品| 精品欧美国产| 午夜久久中文| 国产精品亚洲аv天堂网| 东方欧美亚洲色图在线| 羞羞视频在线免费看| 免费不卡在线观看av| 激情亚洲网站| 老头吃奶性行交视频| 日韩一区二区在线看| 久久中文字幕二区| 欧美精品aaaa| 中文字幕亚洲欧美| 精品亚洲成av人在线观看| 久久久久久久久免费视频| 国产欧美最新羞羞视频在线观看| 亚洲欧洲精品一区二区三区不卡| 青草综合视频| 国产精品50p| 主播福利视频一区| 国产在线乱码一区二区三区| 自由的xxxx在线视频| 樱桃成人精品视频在线播放| 屁屁影院在线观看| 国产精品视频最多的网站| 亚洲制服丝袜在线| 久久综合88| 水莓100在线视频| 91精品在线影院| 精品福利一区二区| 一本色道88久久加勒比精品| www.国产精品.com| 精品久久久久久亚洲国产300 | 国产精品豆花视频| 日韩欧美小视频| 26uuu成人| 久久综合电影一区| 成人免费小视频| 日本久久精品| 午夜影院免费在线| 成人av在线不卡| 国产免费观看久久| 蜜桃成人av| 日本综合在线| 久无码久无码av无码| 97av在线视频| 欧美精三区欧美精三区| 欧美xxxxhdvideosex| 国产自产在线视频| 国产精品亚洲аv天堂网| 91精品国模一区二区三区| 国产精品一二三在| 久久久久久久久久久久久久久久久久| 麻豆av在线免费观看| www亚洲成人| 亚洲精品美女久久7777777| 欧美一级bbbbb性bbbb喷潮片| 欧美性猛交xxxxx免费看| av在线下载| 国产91在线视频观看| 国产啪精品视频网站| 色av吧综合网| 国产欧美91| 日本综合精品一区| 尤物yw193can在线观看| 午夜免费一区二区| 一区二区冒白浆视频| 91亚洲永久免费精品| 精品国产一区二区三区久久狼黑人| 欧美日韩午夜| 岳的好大精品一区二区三区| 蜜桃视频www网站在线观看| 黄色av网站在线| 婷婷国产在线| 人善交video高清| jizz国产| 欧美亚洲爱爱另类综合| 欧美视频第一页| 国产亚洲一区| 欧洲一区二区在线| 久久久免费精品| 韩日成人在线| 亚洲电影在线一区二区三区| 日本韩国一区| 日韩电影免费观看中文字幕| 日韩一级不卡| 欧美精品日本| 亚洲激情在线| 久久久777| 嫩草视频在线观看| 导航艳情国产电影| aa在线免费观看| 综合激情丁香| 福利h视频在线| 国产在线一二| 色网在线观看| 国产精品视频一区二区三区| 99国产精品久久一区二区三区| 第四色中文综合网| 色无极亚洲影院| 免费视频最近日韩| 国产女主播一区| 亚洲成人在线免费| 欧美精品高清| 国产精品亚洲综合在线观看| 成人aaaa| 国产精品性做久久久久久| 国产欧美一区二区在线观看| 午夜激情综合网| 久久蜜桃精品| 久久精品亚洲精品国产欧美| 亚洲婷婷综合久久一本伊一区| 欧美日韩中文另类| 中文字幕免费国产精品| 国产欧美韩国高清| 日本视频一区在线观看| 超碰97人人射妻| 2021av在线| 欧美午夜在线播放| 秋霞国产午夜精品免费视频| 综合亚洲深深色噜噜狠狠网站| 欧美男人的天堂一二区| 欧美丰满老妇厨房牲生活| 免费久久一级欧美特大黄| 污网站免费看| 久久精品女人天堂av免费观看| 亚洲成av人片乱码色午夜| 国产日产亚洲精品系列| 日韩欧美国产综合| 国产在线视频91| 高清成人av| 91蜜桃臀久久一区二区| 激情综合色丁香一区二区| 7777精品伊人久久久大香线蕉的| 性欧美xxxx视频在线观看| 免费观看日韩毛片| 日本午夜精品久久久久| 无需播放器的av| 成人av地址| 伊人色综合久久天天|