分佈式系統全局惟一ID生成

一 什麼是分佈式系統惟一ID

在複雜分佈式系統中,每每須要對大量的數據和消息進行惟一標識。node

如在金融、電商、支付、等產品的系統中,數據日漸增加,對數據分庫分表後須要有一個惟一ID來標識一條數據或消息,數據庫的自增ID顯然不能知足需求,此時一個可以生成全局惟一ID的系統是很是必要的。算法

2、分佈式系統惟一ID的特色

 

  1. 全局惟一性:不能出現重複的ID號,既然是惟一標識,這是最基本的要求。
  2. 趨勢遞增:在MySQL InnoDB引擎中使用的是彙集索引,因爲多數RDBMS使用B-tree的數據結構來存儲索引數據,在主鍵的選擇上面咱們應該儘可能使用有序的主鍵保證寫入性能。
  3. 單調遞增:保證下一個ID必定大於上一個ID,例如事務版本號、IM增量消息、排序等特殊需求。
  4. 信息安全:若是ID是連續的,惡意用戶的扒取工做就很是容易作了,直接按照順序下載指定URL便可;若是是訂單號就更危險了,競對能夠直接知道咱們一天的單量。因此在一些應用場景下,會須要ID無規則、不規則。

同時除了對ID號碼自身的要求,業務還對ID號生成系統的可用性要求極高,想象一下,若是ID生成系統癱瘓,這就會帶來一場災難。數據庫

由此總結下一個ID生成系統應該作到以下幾點:安全

  1. 平均延遲和TP999延遲都要儘量低(TP90就是知足百分之九十的網絡請求所須要的最低耗時。TP99就是知足百分之九十九的網絡請求所須要的最低耗時。同理TP999就是知足千分之九百九十九的網絡請求所須要的最低耗時);
  2. 可用性5個9(99.999%);
  3. 高QPS。

補充:QPS和TPS

QPS:Queries Per Second意思是「每秒查詢率」,是一臺服務器每秒可以相應的查詢次數,是對一個特定的查詢服務器在規定時間內所處理流量多少的衡量標準。
TPS:是TransactionsPerSecond的縮寫,也就是事務數/秒。它是軟件測試結果的測量單位。一個事務是指一個客戶機向服務器發送請求而後服務器作出反應的過程。客戶機在發送請時開始計時,收到服務器響應後結束計時,以此來計算使用的時間和完成的事務個數服務器

3、分佈式系統惟一ID的實現方案

1.UUID

UUID(Universally Unique Identifier)的標準型式包含32個16進制數字,以連字號分爲五段,形式爲8-4-4-4-12的36個字符,示例:550e8400-e29b-41d4-a716-446655440000,到目前爲止業界一共有5種方式生成UUID,詳情見IETF發佈的UUID規範 A Universally Unique IDentifier (UUID) URN Namespace。網絡

優勢:數據結構

  • 性能很是高:本地生成,沒有網絡消耗。

缺點:併發

  • 不易於存儲:UUID太長,16字節128位,一般以36長度的字符串表示,不少場景不適用。
  • 信息不安全:基於MAC地址生成UUID的算法可能會形成MAC地址泄露,這個漏洞曾被用於尋找梅麗莎病毒的製做者位置。
  • ID做爲主鍵時在特定的環境會存在一些問題,好比作DB主鍵的場景下,UUID就很是不適用

2.數據庫生成

以MySQL舉例,利用給字段設置auto_increment_increment和auto_increment_offset來保證ID自增,每次業務使用下列SQL讀寫MySQL獲得ID號。分佈式

 

這種方案的優缺點以下:高併發

優勢:

  • 很是簡單,利用現有數據庫系統的功能實現,成本小,有DBA專業維護。
  • ID號單調自增,能夠實現一些對ID有特殊要求的業務。

缺點:

  • 強依賴DB,當DB異常時整個系統不可用,屬於致命問題。配置主從複製能夠儘量的增長可用性,可是數據一致性在特殊狀況下難以保證。主從切換時的不一致可能會致使重複發號。
  • ID發號性能瓶頸限制在單臺MySQL的讀寫性能。

3.Redis生成ID

當使用數據庫來生成ID性能不夠要求的時候,咱們能夠嘗試使用Redis來生成ID。

這主要依賴於Redis是單線程的,因此也能夠用生成全局惟一的ID。能夠用Redis的原子操做 INCR和INCRBY來實現。

比較適合使用Redis來生成天天從0開始的流水號。好比訂單號=日期+當日自增加號。能夠天天在Redis中生成一個Key,使用INCR進行累加。

優勢:

1)不依賴於數據庫,靈活方便,且性能優於數據庫。

2)數字ID自然排序,對分頁或者須要排序的結果頗有幫助。

缺點:

1)若是系統中沒有Redis,還須要引入新的組件,增長系統複雜度。

2)須要編碼和配置的工做量比較大。

4.利用zookeeper(分佈式應用程序協調服務)生成惟一ID

zookeeper主要經過其znode數據版原本生成序列號,能夠生成32位和64位的數據版本號,客戶端可使用這個版本號來做爲惟一的序列號。

不多會使用zookeeper來生成惟一ID。主要是因爲須要依賴zookeeper,而且是多步調用API,若是在競爭較大的狀況下,須要考慮使用分佈式鎖。所以,性能在高併發的分佈式環境下,也不甚理想。

5.snowflake(雪花算法)方案

這種方案大體來講是一種以劃分命名空間(UUID也算,因爲比較常見,因此單獨分析)來生成ID的一種算法,這種方案把64-bit分別劃分紅多段,分開來標示機器、時間等,好比在snowflake中的64-bit分別表示以下圖(圖片來自網絡)所示:

41-bit的時間能夠表示(1L<<41)/(1000L*3600*24*365)=69年的時間,10-bit機器能夠分別表示1024臺機器。若是咱們對IDC劃分有需求,還能夠將10-bit分5-bit給IDC,分5-bit給工做機器。這樣就能夠表示32個IDC,每一個IDC下能夠有32臺機器,能夠根據自身需求定義。12個自增序列號能夠表示2^12個ID,理論上snowflake方案的QPS約爲409.6w/s,這種分配方式能夠保證在任何一個IDC的任何一臺機器在任意毫秒內生成的ID都是不一樣的。

這種方式的優缺點是:

優勢:

  • 毫秒數在高位,自增序列在低位,整個ID都是趨勢遞增的。
  • 不依賴數據庫等第三方系統,以服務的方式部署,穩定性更高,生成ID的性能也是很是高的。
  • 能夠根據自身業務特性分配bit位,很是靈活。

缺點:

  • 強依賴機器時鐘,若是機器上時鐘回撥,會致使發號重複或者服務會處於不可用狀態。
相關文章
相關標籤/搜索