Ⅰ 生成19位不重復的純數字隨機ID方法之一
在設計隨機ID生成方法之前,我通常會考慮這么幾個問題:
1、長度多長,是否定長?
2、是否要求純數字?
3、是否有分布式的要求?
4、業務量是多大?每毫秒至少要求幾個序列號?
以上問題是基於常見的隨機ID演算法提出的,例如UUID,雪花演算法等。隨機ID的生成常常會涉及到時間戳,MAC地址,ip地址的提取,因此會有第3問和第4問。生成隨機數的方法有很多,我們需要根據業務場景來設計合適自己的。
本文的業務場景是,線下業務員手動生成訂單時,需要隨機生成訂單號,原先的.Net老系統直接調取了公司統一封裝的UUID包,但是做Java改造時發現沒有Java版本,所以只能自己設計。場景具備以下特點:
1、要求與老系統邏輯保持不變,訂單號必須是19位定長的純數字
2、沒有專門的自增序列表可以用
3、業務量小。並發很低
4、不是單機,涉及分布式環境
按照通常的做法,我先取了13 位的currentMillis,再取系統ip,ip保留最後兩段共6位,不足6位用0補齊。這么做的原因是在同一環境下,ip的前兩段通常是相同的,保留下來沒有太大的意義,而且長度的限制擺在這。
這樣算下來,時間戳+ip 剛好19位,同一毫秒只能有一筆訂單。很顯然這樣的重復幾率有點太大了。但是又不能超過長度,最後我選定的方法是,舍棄時間戳的第一位,留一位用來做序列。12位的時間戳會在30年左右重復,以當前的業務場景來看是符合要求的。
那麼最後這個id的生成方式就變成了 12位時間戳 + 6位ip + 1位自增序列。雖然是分布式環境,但是序列並沒有分布式,而是維護在了本地。原因很簡單,序列的目的是讓同一機器同一毫秒下不出現重復訂單號即可,因此本地自增是完全可行的。而且重啟後重新從0開始問題也不大。只要一毫秒落地的訂單不超過10筆就完全沒問題。
這樣的做法顯然不是特別優雅,特別是截取一位時間戳的操作可能會被吐槽。但是在這特定的條件和業務場景下,這也是我能想出的比較好的辦法了。後續有新的想法,我會在這里補充。