03.08 高併發下如何生成唯一訂單號?

用戶133749265


高併發下如何生成唯一訂單號(唯一主鍵),有幾個方案和大家分享一下。

利用數據庫生成

先說最笨的方法,利用數據庫的自增長序列生成,數據庫內唯一;數據庫生成唯一主鍵,別的系統過來取;

  • 優點:理解起來最容易,用起來也最容易。

  • 缺點:也非常明顯了,每種數據庫的實現不同,如果數據庫需要遷移的話比較麻煩;最大的問題是性能問題,因為題目中提到了【高併發下】,所以使用這個方法估計會很難滿足性能需求。

利用Redis/MongoDB/zookeeper生成

Redis的單線程的,利用incr和increby;MongoDB的ObjectId;ZK通過znode數據版本;都可以生成全局的唯一標識碼。

  • 優點:性能高於數據庫;可以使用集群部署。

  • 缺點:需要引入對應的組件,增加系統的複雜度。

UUID

這個是分佈式架構中,生成唯一標識碼最常用的算法。UUID有基於MAC地址的,加上時間和時鐘序列的,也有基於偽隨機數的,基於加密哈希的。

  • 優點:本地生成,不需要第三方組件,生成比較簡單,性能好。

  • 缺點:長度長,不利於存儲,並且沒有排序,是個字符串,不利於查詢。解決無序問題,可參考Comb算法(combined guid/timestamp)。

Snowflake

Twitter開源,基於zk,41位時間戳(毫秒數)+10位機器的ID+12位毫秒內的流水號+1位符號位(永遠是0)。

  • 優點:性能不錯,單機內遞增。

  • 缺點:依賴zk;依賴於機器時鐘,分佈式環境內可能會不是全局遞增。

UidGenerator

百度開源,基於snowflake算法。

Leaf

美團開源。

  • 優點:能保證全局唯一性、高可用、趨勢遞增(不太安全,比如洩露公司訂單數量)、單調遞增等。

  • 缺點:依然會依賴第三方組件,zk或數據庫。

我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。


會點代碼的大叔


生成全局唯一ID有以下幾種方式:

時間戳+用戶ID+隨機數

這其實並不是真正意義上的全局唯一ID,但是在併發量不高的場景中已經夠用了。其中時間戳可以是毫秒級別

UUID

這種方式比較方便,有現成可用的JAR包,但是也有缺點:ID可讀性不好,而且會造成索引樹頻繁頁分裂,影響數據庫性能和空間使用


數據庫序列表

維護一張序列表。考慮到性能問題,不必每次生成ID都去操作數據庫,可以設置一定的步長比如1000,每次從表中拿1000個序列號,從每臺服務器內存中線性去取


Redis

維護一個序列號鍵值對,利用Redis自增的原子性,生成序列號


Snowflake

同一毫秒可以產生ID數量4194304個,優點是完全內存操作性能好,缺點是依賴於系統時鐘一致性。如果某臺機器的系統時鐘回撥,有可能造成ID衝突,或者ID亂序


總結

最重要的還是根據項目的場景,尤其是併發量,選擇最合適的方法


敬請關注

請點擊關注按鈕【IT徐胖子】會持續為大家奉獻互聯網和技術乾貨內容,感謝支持


IT徐胖子


由於是高併發情況,所以不建議使用數據庫自增ID,可以參考如下方案:

1、redis自增id

2、UUID

3、時間戳+隨機數

4、Twitter的snowflake算法

5、利用zookeeper生成唯一id,性能不如redis

6、MongoDB的ObjectId,和snowflake算法類似


為夢想衝刺


互聯網快速發展的今天,各類商城平臺不計其數,商城及支付平臺都有訂單系統,訂單系統裡有一個關鍵元素就是訂單號,訂單號要具備全局唯一性。另外一方面,在分佈式系統中也需要各種各樣的ID,同樣要求全局唯一性。

訂單號生成方案

在一般項目中,我們要生成訂單號可選的方案很多,比如說:

1、數據庫自增長ID

  • 優點:藉助數據庫實現,無需代碼實現;

  • 缺點:不能做水平分表,因為ID可能會重複;高併發場景下生成效率低速度慢;

2、時間戳 + 隨機數

  • 優點:實現起來簡單

  • 缺點:即使在相同的時間戳下隨機數依舊存在重複的可能

3、會員ID + 時間戳

  • 優點:同一時間內,同個用戶不會存在兩個訂單號

  • 缺點:會員ID洩露,存在一定風險

4、GUID、UUID

  • 優點:簡單

  • 缺點:生成的訂單號不友好、索引效率低下

高併發場景下生成的訂單號存在重複的可能

所謂的高併發是指在較短時間段內服務器需要並行處理的請求數很多。在高併發場景下,同一秒可能會生成很多訂單號,這樣一來訂單號就存在重複的可能性。

另外一方面,如果是多線程或者分佈式環境下同一秒生成的重複訂單可能性更大!

高併發、分佈式環境下生成訂單號的方案

1、利用Redis原子遞增來實現(推薦)

因為Redis本身就是單線程的,再借助其原子操作INCR、INCRBY完全可以生成全局唯一的ID,而且速度快。

2、時間戳 + 多個隨機數 + 樂觀鎖

3、GUID轉換為數字


以上就是我的觀點,對於這個問題大家是怎麼看待的呢?歡迎在下方評論區交流 ~ 我是科技領域創作者,十年互聯網從業經驗,歡迎關注我瞭解更多科技知識!

網絡圈


你可以看一下你淘寶的訂單號。

年月日+用戶id(補0)+用戶今日訂單數量(補0)

絕對不會重複


樓上升官樓下發財


用戶ID+時間(精確到秒);

用戶ID+該用戶訂單總數;


不定時思考人生


雪花算法足夠了。我這邊兩個業務線都是用的雪花算法 完全能保證唯一。


termination


考慮下分庫分表情況吧


IT大法好


隊列


分享到:


相關文章: