分佈式系統唯一ID設計

目錄

1 概述

2 分佈式唯一ID特點

3 分佈式唯一ID傳統方案

3.1 UUID

3.2 數據庫生成

3.3 Redis生成ID

3.4 利用zookeeper生成唯一ID

3.5 snowflake(雪花算法)方案


1 概述

      在複雜分佈式系統中,往往需要對大量的數據和消息進行唯一標識如在金融、電商、支付、等產品的系統中,數據日漸增長,對數據分庫分表後需要有一個唯一ID來標識一條數據或消息,數據庫的自增ID顯然不能滿足需求,此時一個能夠生成全局唯一ID的系統是非常必要的。

2 分佈式唯一ID特點

  • 全局唯一性:不能出現重複的ID號,既然是唯一標識,這是最基本的要求。
  • 趨勢遞增:在MySQL InnoDB引擎中使用的是聚集索引,由於多數RDBMS使用B-tree的數據結構來存儲索引數據,在主鍵的選擇上面我們應該儘量使用有序的主鍵保證寫入性能
  • 單調遞增:保證下一個ID一定大於上一個ID,例如事務版本號、IM增量消息、排序等特殊需求。
  • 運行效率:ID簡短,查詢效率快
  • 信息安全:如果ID是連續的,惡意用戶的扒取工作就非常容易做了,直接按照順序下載指定URL即可;如果是訂單號就更危險了,競對可以直接知道我們一天的單量。所以在一些應用場景下,會需要ID無規則、不規則。

3 分佈式唯一ID傳統方案

3.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。

優點:

  • 代碼實現簡單。
  • 本機生成,沒有性能問題
  • 因爲是全球唯一的ID,所以遷移數據容易

缺點:

  • 不易於存儲:UUID太長,16字節128位,通常以36長度的字符串表示,很多場景不適用。
  • 信息不安全:基於MAC地址生成UUID的算法可能會造成MAC地址泄露,這個漏洞曾被用於尋找梅麗莎病毒的製作者位置。
  • 每次生成的ID是無序的,無法保證趨勢遞增

3.2 數據庫生成

這個方案就是利用了MySQL的主鍵自增auto_increment,默認每次ID加1。

優點:

  • 數字化,id遞增
  • 查詢效率高
  • 具有一定的業務可讀

缺點:

  • 存在單點問題,如果mysql掛了,就沒法生成iD了
  • 數據庫壓力大,高併發抗不住

3.3 Redis生成ID

      利用redis的incr原子性操作自增,比較適合使用Redis來生成每天從0開始的流水號。比如訂單號=日期+當日自增長號。

優點:

  • 不依賴於數據庫,靈活方便,且性能優於數據庫。
  • 數字ID天然排序,對分頁或者需要排序的結果很有幫助。

缺點:

  • 如果系統中沒有Redis,還需要引入新的組件,增加系統複雜度。
  • 需要編碼和配置的工作量比較大。

3.4 利用zookeeper生成唯一ID

       zookeeper主要通過其znode數據版本來生成序列號,可以生成32位和64位的數據版本號,客戶端可以使用這個版本號來作爲唯一的序列號。

      很少會使用zookeeper來生成唯一ID。主要是由於需要依賴zookeeper,並且是多步調用API,如果在競爭較大的情況下,需要考慮使用分佈式鎖。因此,性能在高併發的分佈式環境下,也不甚理想。

3.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位,非常靈活。

缺點:

  • 強依賴機器時鐘,如果機器上時鐘回撥,會導致發號重複或者服務會處於不可用狀態

 

參考:

1、通俗易懂:如何設計能支撐百萬併發的數據庫架構?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章