[转]【分布式系统】唯一ID生成策略总结
文章目錄
-
- 全局唯一id介紹
-
- ? ? 全局唯一id特點:
- 常見全局唯一id生成策略
-
- ? ? 1、數據庫自增長序列或字段生成id
- ? ? 2、UUID
- ? ? 3、Redis生成ID
- ? ? 4、zookeeper生成ID
- ? ? 5、Twitter的snowflake算法
全局唯一id介紹
? ? 系統唯一id是我們在設計階段常常遇到的問題。在復雜的分布式系統中,幾乎都需要對大量的數據和消息進行唯一標識。在設計初期,我們需要考慮日后數據量的級別,如果可能會對數據進行分庫分表,那么就需要有一個全局唯一id來標識一條數據或記錄。生成唯一id的策略有多種,但是每種策略都有它的適用場景、優點以及局限性。
? ? 全局唯一id特點:
常見全局唯一id生成策略
? ? 1、數據庫自增長序列或字段生成id
? ? 最常見的一種生成id方式。利用數據庫本身來進行設置,在全數據庫內保持唯一。
? ? 【優點】
? ? 【缺點】
? ? 1. 強依賴DB。不同數據庫語法和實現不同,數據庫遷移的時候、多數據庫版本支持的時候、或分表分庫的時候需要處理,會比較麻煩。當DB異常時整個系統不可用,屬于致命問題。
? ? 2. 單點故障。在單個數據庫或讀寫分離或一主多從的情況下,只有一個主庫可以生成。有單點故障的風險。
? ? 3. 數據一致性問題。配置主從復制可以盡可能的增加可用性,但是數據一致性在特殊情況下難以保證。主從切換時的不一致可能會導致重復發號。
? ? 4. 難于擴展。在性能達不到要求的情況下,比較難于擴展。ID發號性能瓶頸限制在單臺MySQL的讀寫性能。
? ? 【部分優化方案】
? ? 針對主庫單點, 如果有多個Master庫,則每個Master庫設置的起始數字不一樣,步長一樣,可以是Master的個數。比如:Master1 生成的是 1,4,7,10,Master2生成的是2,5,8,11 Master3生成的是 3,6,9,12。這樣就可以有效生成集群中的唯一ID,也可以大大降低ID生成數據庫操作的負載。
? ? 2、UUID
? ? 常見的生成id方式,利用程序生成。
? ? UUID (Universally Unique Identifier) 的目的,是讓分布式系統中的所有元素,都能有唯一的辨識資訊,而不需要透過中央控制端來做辨識資訊的指定。如此一來,每個人都可以建立不與其它人沖突的 UUID。在這樣的情況下,就不需考慮數據庫建立時的名稱重復問題。
? ? UUID的標準形式包含32個16進制數字,以連字號分為五段,形式為8-4-4-4-12的36個字符,示例:550e8400-e29b-41d4-a716-446655440000,到目前為止業界一共有5種方式生成UUID,詳情見IETF發布的UUID規范 A Universally Unique IDentifier (UUID) URN Namespace。
? ?在Java中我們可以直接使用下面的API生成UUID:
UUID uuid = UUID.randomUUID(); String s = UUID.randomUUID().toString();? ? 【優點】
? ? 【缺點】
? ? 【部分優化方案】
? ? 為了解決UUID不可讀, 可以使用UUID to Int64的方法 。
? ? 為了解決UUID無序的問題, NHibernate在其主鍵生成方式中提供了Comb算法(combined guid/timestamp)。保留GUID的10個字節,用另6個字節表示GUID生成的時間(DateTime)。
? ? 3、Redis生成ID
? ? 當使用數據庫來生成ID性能不夠要求的時候,我們可以嘗試使用Redis來生成ID。這主要依賴于Redis是單線程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作 INCR和INCRBY來實現。
? ? 可以使用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
? ? 這個負載到哪臺機器上需要提前設定好,未來很難做修改。但是3-5臺服務器基本能夠滿足,都可以獲得不同的ID。步長和初始值一定需要事先設定好。使用Redis集群也可以防止單點故障的問題。
? ? 比較適合使用Redis來生成日切流水號。比如訂單號=日期+當日自增長號。可以每天在Redis中生成一個Key,使用INCR進行累加。
? ? 【優點】
? ? 【缺點】
如果系統中沒有Redis,還需要引入新的組件,增加系統復雜度。。
需要編碼和配置的工作量比較大。
Redis單點故障,影響序列服務的可用性。
? ? 4、zookeeper生成ID
? ? zookeeper主要通過其znode數據版本來生成序列號,可以生成32位和64位的數據版本號,客戶端可以使用這個版本號來作為唯一的序列號。
? ? 很少會使用zookeeper來生成唯一ID。主要是由于需要依賴zookeeper,并且是多步調用API,如果在競爭較大的情況下,需要考慮使用分布式鎖。因此,性能在高并發的分布式環境下,也不甚理想。
? ? 5、Twitter的snowflake算法
? ? snowflake(雪花算法)是Twitter開源的分布式ID生成算法,結果是一個long型的ID。這種方案把64-bit分別劃分成多段,分開來標示機器、時間等。如圖:
? ? 其核心思想是:使用41bit作為毫秒數,10bit作為機器的ID(5個bit是數據中心,5個bit的機器ID),12bit作為毫秒內的流水號(意味著每個節點在每毫秒可以產生 4096 個 ID),最后還有一個符號位,永遠是0。具體實現的代碼可以參看github。
? ? snowflake算法可以根據自身項目的需要進行一定的修改。比如估算未來的數據中心個數,每個數據中心的機器數以及統一毫秒可以能的并發數來調整在算法中所需要的bit數。
? ? 【優點】
? ? 【缺點】
強依賴機器時鐘,如果機器上時鐘回撥,會導致發號重復或者服務會處于不可用狀態。
ID可能不是全局遞增。在單機上是遞增的,但是由于涉及到分布式環境,每臺機器上的時鐘不可能完全同步,也許有時候也會出現不是全局遞增的情況。
---------------------
作者:夢 * 蝶
來源:CSDN
原文:https://blog.csdn.net/LZ15932161597/article/details/113397226
版權聲明:本文為作者原創文章,轉載請附上博文鏈接!
內容解析By:CSDN,CNBLOG博客文章一鍵轉載插件
總結
以上是生活随笔為你收集整理的[转]【分布式系统】唯一ID生成策略总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 各代移动网络性能
- 下一篇: java随机抽题系统_为什么要使用考试系