1.介紹
今天作了一個功能,生成訂單流水號,固然這其實這並非一個很難的功能,最直接的方式就是日期+主機Id+隨機字符串來拼接一個流水號。可是今天有個我認爲比較優雅方式來實現。我要介紹是日期+ long(商家Id+訂單類型+主機ID+AtomicInteger),什麼意思呢,前面的日期保持不變,後面的將商家Id,訂單的類型,主機的Id,AtomicInteger,經過移位與或運算「保存」到一個long類型裏面。爲何要這麼作?java
- 不想把相關信息直接暴露出去。
- 經過流水號能夠快速獲得相關業務信息,快速定位問題。
- 使用AtomicInteger可提升併發量,下降了衝突。
2.原理解釋
前面的生成日期就不須要講了,直接講解如何經過移位和與或操做獲得long值。
先來看張圖:git

這是一個我設計的long存儲形式,你們能夠格局自身業務來自行設計,什麼業務數據佔的位數。如今來詳細解釋下。github
- 符號位,這個不用過的介紹,你們都知道2進制第一位都是符號位,0表示正數1表示負數
- 當前秒數,表述的是當前是當天的第多少秒,天天最多有86400秒,最多佔17位
- 商家Id佔14位,因爲業務涉及到商戶,訂單也是歸爲每一個商戶下面的,假定咱們的最多有9999家商戶,9999佔位是14位,因此咱們商戶Id佔14位,你們根據自身業務的量來決定長度。
- 訂單類型,假定咱們的訂單類型還停留在10種之內,因此咱們保留4位,最多支持類型16種,你們一樣的根據業務的量來決定
- 服務器的Id,假定服務器數量在10臺之內,因此咱們保留4位,最多支持16臺服務器,你們一樣的根據自身服務器的數量來決定。,
- 剩下的24位所有留給AtomicInteger,設計上我這裏的qps能夠達到2的24方。這個其實已經很大了。你們根據上面的設計留下來的數量當AtomicInteger位數,其實能夠知足大部分業務需求了。
介紹了具體的原理,如今要上代碼了。服務器
3.show code

運行測試結果:併發


源代碼:https://github.com/applenele/DeepJavaWeb/blob/master/javabasics/src/main/java/com/smallcode/utils/SerialNumberUtil.javaapp