天天看點

高并發情況下分布式全局ID

1、高并發情況下,生成分布式全局id政策

2、利用全球唯一UUID生成訂單号優缺點

3、基于資料庫自增或者序列生成訂單号

4、資料庫叢集如何考慮資料庫自增唯一性

5、基于Redis生成生成全局id政策

6、Twitter的Snowflake算法生成全局id

7、基于Zookeeper生成全局id

高并發情況下,生成分布式全局id政策

1、注意幂等性且全局唯一性

2、注意安全性,不能被猜疑

3、趨勢遞增性

訂單号命名規則:比如“業務編碼 + 時間戳 + 機器編号[前4位] + 随機4位數 + 毫秒數”。

利用全球唯一UUID生成訂單号

UUID基本概念:

UUID是指在一台機器上生成的數字,它保證對在同一時空中的所有機器都是唯一的。

UUID組成部分:目前日期和時間+時鐘序列+随機數+全局唯一的IEEE機器識别号

全局唯一的IEEE機器識别号:如果有網卡,從網卡MAC位址獲得,沒有網卡以其他方式獲得。

UUID優缺點:

優點:

簡單,代碼友善

生成ID性能非常好,基本不會有性能問題

全球唯一,在遇見資料遷移,系統資料合并,或者資料庫變更等情況下,可以從容應對

缺點:

沒有排序,無法保證趨勢遞增

UUID往往是使用字元串存儲,查詢的效率比較低

存儲空間比較大,如果是海量資料庫,就需要考慮存儲量的問題。

傳輸資料量大

UUID不需要聯網生成,redis需要。

基于資料庫自增方式

實作思路:利用資料庫自增或者序列号方式實作訂單号

注意:在資料庫叢集環境下,預設自增方式存在問題,因為都是從1開始自增,可能會存在重複,應該設定每台不同資料庫自增的間隔方式不同。

簡單,代碼友善,性能可以接受。

數字ID天然排序,對分頁或者需要排序的結果很有幫助。

不同資料庫文法和實作不同,資料庫遷移的時候或多資料庫版本支援的時候需要處理。

在性能達不到要求的情況下,比較難于擴充。

在單個資料庫或讀寫分離或一主多從的情況下,隻有一個主庫可以生成。有單點故障的風險。

分表分庫的時候會有麻煩。

資料庫叢集如何考慮資料庫自增唯一性

在資料庫叢集環境下,預設自增方式存在問題,因為都是從1開始自增,可能會存在重複,應該設定每台節點自增步長不同。

查詢自增的步長

SHOW VARIABLES LIKE 'auto_inc%'

修改自增的步長

SET @@auto_increment_increment=10;    

修改起始值

SET @@auto_increment_offset=5;

假設有兩台mysql資料庫伺服器

節點①自增 1 3 5 7 9 11 ….

節點②自增 2 4 6 8 10 12 ….

注意:在最開始設定好了每台節點自增方式步長後,确定好了mysql叢集數量後,無法擴充新的mysql,不然生成步長的規則可能會發生變化。

MySQL1    1 2 3

MySQL2    1 2 3

  方法1   讀寫分離

  方法2  設定自增步長        需要提前設定好步長  否則如果新增一台MySQL就麻煩了

             如果想提高擴充性 采用UUID方式作為主鍵

基于Redis生成生成全局id政策

因為Redis是單線的,天生保證原子性,可以使用Redis的原子操作 INCR和INCRBY來實作

不依賴于資料庫,靈活友善,且性能優于資料庫。

如果系統中沒有Redis,還需要引入新的元件,增加系統複雜度。

需要編碼和配置的工作量比較大。

注意:在Redis叢集情況下,同樣和Redis一樣需要設定不同的增長步長,同時key一定要設定有效期

可以使用Redis叢集來擷取更高的吞吐量。假如一個叢集中有5台Redis。可以初始化每台Redis的值分别是1,2,3,4,5,然後步長都是5。各個Redis生成的ID為:

A:1,6,11,16,21

B:2,7,12,17,22

C:3,8,13,18,23

D:4,9,14,19,24

E:5,10,15,20,25

比較适合使用Redis來生成每天從0開始的流水号。比如訂單号=日期+當日自增長号。可以每天在Redis中生成一個Key,使用INCR進行累加。

如果生成的訂單号超過自增增長的話,可以采用字首+自增+并且設定有效期

目前日期-5位自增

統一時間 最多生成10w-1個不重複的

假設雙十一 每秒99w訂單

高并發情況下分布式全局ID

 補零:

高并發情況下分布式全局ID

 加上字首:

高并發情況下分布式全局ID

 Redis如果做叢集,會産生重複的問題!

 redis 的key的失效時間問題!

   24h  第二天時間變了 不會重複了哦

Twitter的snowflake(雪花)算法  (跟UUID一樣不用聯網)

snowflake是Twitter開源的分布式ID生成算法,結果是一個long型的ID。其核心思想是:

高位随機+毫秒數+機器碼(資料中心+機器id)+10位的流水号碼

Github位址: https://github.com/twitter-archive/snowflake

Snowflake 原理:

snowflake生産的ID是一個18位的long型數字,二進制結構表示如下(每部分用-分開):

0 - 00000000 00000000 00000000 00000000 00000000 0 - 00000 - 00000 - 00000000 0000

第一位未使用,接下來的41位為毫秒級時間(41位的長度可以使用69年,從1970-01-01 08:00:00),然後是5位datacenterId(最大支援2^5=32個,二進制表示從00000-11111,也即是十進制0-31),和5位workerId(最大支援2^5=32個,原理同datacenterId),是以datacenterId*workerId最多支援部署1024個節點,最後12位是毫秒内的計數(12位的計數順序号支援每個節點每毫秒産生2^12=4096個ID序号).所有位數加起來共64位,恰好是一個Long型(轉換為字元串長度為18).單台機器執行個體,通過時間戳保證前41位是唯一的,分布式系統多台機器執行個體下,通過對每個機器執行個體配置設定不同的datacenterId和workerId避免中間的10位碰撞。最後12位每毫秒從0遞增生産ID,再提一次:每毫秒最多生成4096個ID,每秒可達4096000個。