無論咱們用什麼方法生成的id,都應該知足如下幾個條件:git
第一 , 必須是惟一,能夠全局惟一,或者同一種業務內惟一也能夠。github
第二, 必須按時間遞增(這個須要解釋嗎)。redis
第三,儘可能使用數字類型的,其次才考慮字符串型的。緣由很簡單,數字不須要使用編碼(utf-8,gbk等)翻譯。直接能夠保存到數據庫,而字符串必須使用編碼翻譯後才能使用。算法
第四, 在id裏面儘可能能看出id是何時生成的。數據庫
關於惟一性id生成討論幾種方案:分佈式
第一種,首選方案,數據庫id自動生成,理由是沒有任何難度,你們都會用。可是這隻能在前期使用,性能
(1) 當系統負載大了,數據庫性能降低就會考慮更換別的方法了。測試
(2) 若是有分庫分表的話,也是不能用了,須要想別的辦法替代。ui
第二種, uuid。編碼
這個方案只能說能夠用,能保證惟一 ,用起來簡單,可是用了以後處理有點麻煩,由於不能按時間遞增生成,保存到數據庫的時候對數據庫的性能有影響,至少主鍵索引若是是btree的話,確定會有影響,不過能夠把數據庫主鍵索引改爲hash,具體沒有測試過,按理來講應該是會影響比較小了。有誰測試過了能夠留言說下效果。
第三種,redis。
Redis是單線程的,因此也能夠用來生成全局惟一的ID,利用redis對數字的原子自增操做(Redis的 INCR和INCRBY)。
第四種, twitter的snowflake。
snowflake是Twitter開源的分佈式ID生成算法,結果是一個long型的ID。其核心思想是:使用41bit做爲毫秒數,10bit做爲機器的ID(5個bit是數據中心,5個bit的機器ID),12bit做爲毫秒內的流水號(意味着每一個節點在每毫秒能夠產生 4096 個 ID),最後還有一個符號位,永遠是0。具體實現的代碼能夠參看https://github.com/twitter/snowflake。
這種方法能夠保證生成惟一,遞增,數字型的id, 惟一的問題就是生成的id直接看不出是何時生成的。
第五種, snowflake 變種。
(1) 由於long型的十進制只有19位長度,若是咱們要數字型的,又要遞增,又要能從id裏面看出時間,就只有下面這種方法了。
年2位 | 月2位 | 日2位 | 時分4位 | 數據中心id2位 | 機器id2位 | 取納秒的最後5位 | |
18 | 01 | 01 | 1113 | 12 | 15 | 12345 |
這種方法有必定問題,會有重複的id,由於long型長度的限制,咱們時間只能精確到分鐘,一分鐘有60秒,就是60000毫秒, 而後咱們的最後5位最多隻有10萬個數。若是同一臺機器有在同一毫秒內生成多個的話,就可能會出現重複的了。 不過這應該能知足多數需求了。請求量很少的話,這徹底夠用了。
( 2 ) 不少時候,19位長度不夠使用,要超過19長度,咱們就只有用字符串來實現了。字符串就比較方便了,能夠任意生成知足咱們須要的id或者訂單號了。
年月日 | 時分秒 | 毫秒最後3位 | 納秒最後6位 | 數據中心id2位 | 機器id2位 | 擴展id | 擴展id |
180101 | 121315 | 876 | 532524 | 10 | 22 |
這種方法除了不是數字型的id,幾乎沒有別的缺點了,甚至還能夠再加幾位表示具體的服務的id到裏面。能夠自由擴展,甚至想加具體的業務id均可以。
1801011213158765325241022 最後大概是像這樣的。每毫秒鐘能夠生成十萬個不一樣的id。