[轉]【分布式系統】唯一ID生成策略總結

文章目錄

    • 全局唯一id介紹
      • ? ? 全局唯一id特點:
    • 常見全局唯一id生成策略
      • ? ? 1、數據庫自增長序列或字段生成id
      • ? ? 2、UUID
      • ? ? 3、Redis生成ID
      • ? ? 4、zookeeper生成ID
      • ? ? 5、Twitter的snowflake算法

全局唯一id介紹

? ? 系統唯一id是我們在設計階段常常遇到的問題。在復雜的分布式系統中,幾乎都需要對大量的數據和消息進行唯一標識。在設計初期,我們需要考慮日后數據量的級別,如果可能會對數據進行分庫分表,那么就需要有一個全局唯一id來標識一條數據或記錄。生成唯一id的策略有多種,但是每種策略都有它的適用場景、優點以及局限性。

? ? 全局唯一id特點:

  1. 全局唯一性:不能出現重復的ID號,既然是唯一標識,這是最基本的要求;
  2. 趨勢遞增:在MySQL InnoDB引擎中使用的是聚集索引,由于多數RDBMS使用B-tree的數據結構來存儲索引數據,在主鍵的選擇上面我們應該盡量使用有序的主鍵保證寫入性能;
  3. 單調遞增:保證下一個ID一定大于上一個ID,例如事務版本號、IM增量消息、排序等特殊需求;
  4. 信息安全:如果ID是連續的,惡意用戶的扒取工作就非常容易做了,直接按照順序下載指定URL即可;如果是訂單號就更危險了,競對可以直接知道我們一天的單量。所以在一些應用場景下,會需要ID無規則、不規則;
  5. 高可用性:同時除了對ID號碼自身的要求,業務還對ID號生成系統的可用性要求極高,想象一下,如果ID生成系統癱瘓,這就會帶來一場災難。所以不能有單點故障;
  6. 分片支持:可以控制ShardingId。比如某一個用戶的文章要放在同一個分片內,這樣查詢效率高,修改也容易;
  7. 長度適中

常見全局唯一id生成策略

在這里插入圖片描述

? ? 1、數據庫自增長序列或字段生成id

? ? 最常見的一種生成id方式。利用數據庫本身來進行設置,在全數據庫內保持唯一。

? ? 【優點】

  1. 非常簡單。利用現有數據庫系統的功能實現,成本小,代碼簡單,性能可以接受。
  2. 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();

? ? 【優點】

  1. 非常簡單,本地生成,代碼方便,API調用方便
  2. 性能非高。生成的id性能非常好,沒有網絡消耗,基本不會有性能問題。
  3. 全球唯一。在數據庫遷移、系統數據合并、或者數據庫變更的情況下,可以 從容應對。

? ? 【缺點】

  1. 存儲成本高。UUID太長,16字節128位,通常以36長度的字符串表示,很多場景不適用。如果是海量數據庫,就需要考慮存儲量的問題。
  2. 信息不安全。基于MAC地址生成UUID的算法可能會造成MAC地址泄露,這個漏洞曾被用于尋找梅麗莎病毒的制作者位置。
  3. 不適用作為主鍵,ID作為主鍵時在特定的環境會存在一些問題,比如做DB主鍵的場景下,UUID就非常不適用。UUID往往是使用字符串存儲,查詢的效率比較低。
  4. UUID是無序的。不是單調遞增的,而現階段主流的數據庫主鍵索引都是選用的B+樹索引,對于無序長度過長的主鍵插入效率比較低。
  5. 傳輸數據量大。
  6. 不可讀。

? ? 【部分優化方案】

? ? 為了解決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進行累加。

? ? 【優點】

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

? ? 【缺點】

  1. 如果系統中沒有Redis,還需要引入新的組件,增加系統復雜度。

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

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

? ? 【優點】

  1. 穩定性高,不依賴于數據庫等第三方系統,以服務的方式部署,穩定性更高,生成ID的性能也是非常高的。
  2. 靈活方便,可以根據自身業務特性分配bit位。
  3. 單機上ID單調自增,毫秒數在高位,自增序列在低位,整個ID都是趨勢遞增的。

? ? 【缺點】

  1. 強依賴機器時鐘,如果機器上時鐘回撥,會導致發號重復或者服務會處于不可用狀態。

  2. ID可能不是全局遞增。在單機上是遞增的,但是由于涉及到分布式環境,每臺機器上的時鐘不可能完全同步,也許有時候也會出現不是全局遞增的情況。


---------------------
作者:夢 * 蝶
來源:CSDN
原文:https://blog.csdn.net/LZ15932161597/article/details/113397226
版權聲明:本文為作者原創文章,轉載請附上博文鏈接!
內容解析By:CSDN,CNBLOG博客文章一鍵轉載插件

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/284438.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284438.shtml
英文地址,請注明出處:http://en.pswp.cn/news/284438.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

shell在一個大文件找出想要的一段字符串操作技巧

昨天端午,晚上的時候接了一個電話,我朋友的公司,數據庫被兩個工作沒多久的phper給弄壞了,具體就是把一個字段值,給全表弄成一個了名字了,當然這個是可以配置了禁止全表更新數據庫,這下可急壞了,…

CentOS7安裝EPEL源

CentOS7安裝EPEL [lijiayuncentos-*** ~]$ yum install epel-release已加載插件:fastestmirror, langpacks您需要 root 權限執行此命令。[lijiayuncentos-*** ~]$ su密碼:[rootcentos-*** lijiayun]# yum install epel-release已加載插件:fas…

超全的開源Winform UI庫,滿足你的一切桌面開發需求!

本文有dotnet9站長整理 網址:https://dotnet9.com/本站曾介紹過一款Winform開源控件庫HZHControls,Winform在大家心中的地位還是挺高的,今天小編再分享一款新鮮出爐的 Winform UI庫——SunnyUI,一起跟 Dotnet9 往下看吧。項目名稱…

告別國外 IDE,阿里 螞蟻自研 IDE 研發框架 OpenSumi 正式開源

經歷近 3 年時間,在阿里集團及螞蟻集團共建小組的努力下,OpenSumi 作為國內首個強定制性、高性能,兼容 VS Code 插件體系的 IDE 研發框架,今天正式對外開源。 一 OpenSumi 是什么? OpenSumi 是一款面向垂直領域&#…

window-memcache技術隨筆

memcached.exe軟件放置到非中文,非空格的目錄,把MSVCR71.DLL文件放在memcached.exe同目錄下啟動,控制面板中打開window功能-Telnet客戶端memcache服務方法一:管理員身份打開黑窗口 d:(mem的所在盤)cd memmemcached.exe -p 11211方法二: 安裝為Windows的系統服務memcached.exe -…

將不確定變為確定~老趙寫的CodeTimer是代碼性能測試的利器

首先,非常感謝趙老大的CodeTimer,它讓我們更好的了解到代碼執行的性能,從而可以讓我們從性能的角度來考慮問題,有些東西可能我們認為是這樣的,但經理測試并非如何,這正應了我之前的那名話:“機器…

聊聊 C++ 中的幾種智能指針(下)

一:背景 上一篇我們聊到了C 的 auto_ptr ,有朋友說已經在 C 17 中被棄用了,感謝朋友提醒,今天我們來聊一下 C 11 中引入的幾個智能指針。unique_ptrshared_ptrweak_ptr看看它們都怎么玩。二:三大智能指針詳解 1. uniq…

iOS回顧筆記( 02 ) -- 由九宮格布局引發的一系列“慘案”

iOS回顧筆記( 02 ) -- 由九宮格布局引發的一系列“慘案” 前言(扯幾句淡先) 回顧到學習UI過程中的九宮格布局時,發現當時學的東西真是不少。 這個階段最大的特點就是:知識點繁多且瑣碎。 我們的目標就是要將…

【GlobalMapper精品教程】007:如何加載谷歌衛星影像?

“Global Mapper支持所有OGC標準數據源類型,例如用于流式柵格地圖的WMS / WMTS,用于矢量數據集的WFS和用于為指定區域下載單個數據文件的WCS。預先切片的圖像和地形數據集也可以使用OSM(OpenStreetMaps)、TMS(Tiled Map Service)和Google Maps瓦片架構支持。您只需要選擇適當…

LVS/keepalived配置

LVS/DR keepalived配置注意:前面雖然我們已經配置過一些操作,但是下面我們使用keepaliave操作和之前的操作是有些沖突的,所以若是之前配置過DR,請首先做如下操作:dr上執行:$ipv -Cifconfig eth0:0 down前…

Mysql清空表(truncate)與刪除表中數據(delete)的區別

2019獨角獸企業重金招聘Python工程師標準>>> 為某基于wordpress搭建的博客長久未除草,某天升級的時候發現已經被插入了幾萬條垃圾留言,如果一條條刪除那可真是累人的活。遂考慮直接進入mysql直接清空表或者刪除表中數據。 本文記錄一下這2種操…

[轉]云原生到底是什么?

📋 個人簡介 💖 作者簡介:大家好,我是阿牛😜 📝 個人主頁:館主阿牛🔥 🎉 支持我:點贊👍收藏??留言📝 💬格言&#xf…

【GlobalMapper精品教程】008:如何根據指定區域(shp、kml、cad)下載衛星影像?

本文講解在Globalmapper中根據指定的范圍(shp、kml、cad等格式)進行在線衛星影像的下載方法。 文章目錄 一、根據shp范圍下載谷歌影像1. 加載谷歌影像2. 加載shp矢量范圍3. 根據范圍導出影像二、根據kml范圍下載谷歌影像1. 生成研究區范圍kml2. 根據kml范圍下載影像三、根據CAD…

膛目結舌的代碼技巧!一看就是冷暴力~~~~

你見過哪些令你膛目結舌的代碼技巧? 代碼世界有很多令人大呼小叫的技巧!有的代碼像魔術師一樣巧妙地隱藏了自己,有的像魔法師一樣讓你眼花繚亂,還有的像瑜伽大師一樣靈活自如。它們讓我們驚嘆不已,讓我們覺得自己仿佛置…

聯合線程

聯合線程實際上就是把多線程又聯合成了一個線程,但這里還是要比單線程靈活很多,比如說,我可以讓一個線程到運行到某一個條件再聯合其他線程。當前線程與其他線程聯合在一起,又一種讓出cpu,而且直到別個線程運行完&…

Kafka學習征途:不再依賴ZK的KRaft

【Kafka】| 總結/Edison Zhou1新的KRaft架構在Kafka 2.8之前,Kafka重度依賴于Zookeeper集群做元數據管理和集群的高可用(即所謂的共識服務)。在Kafka 2.8之后,引入了基于Raft協議的KRaft模式,支持取消對Zookeeper的依賴…

探索java世界中的日志奧秘

java日志簡單介紹 對于一個應用程序來說日志記錄是必不可少的一部分。線上問題追蹤,基于日志的業務邏輯統計分析等都離不日志。JAVA領域存在多種日志框架,目前常用的日志框架包括Log4j,Log4j 2,Commons Logging,Slf4j&…

nginx的負載均衡集群

針對域名:vim /usr/local/nginx/conf/vhosts/lb.conf //自定義名稱upstream xrc { //別名server 192.168.0.1:80 weight2; //包含的主機server,負載均衡里面的機器server 192.168.0.2:80 weight1; //權重weight}server {li…

英語名言警句100句

1、寧為百夫長,勝作一書生。——楊炯 Better be a centurion than a scholar. 2、我是閑暇為所有中最的。——蘇格拉底 I am the most leisure of all. 3、立志不堅,終不濟事。——朱熹 If you are not determined, you will not help. 4、人學始知道&am…

RabbitMQ細說之開篇

前言關于消息中間件的應用場景,小伙伴們應該都耳熟能詳了吧,比如經常提到的削峰填谷、分布式事務、異步業務處理、大數據分析等等,分布式消息隊列成為其中比較關鍵的橋梁,也就意味著小伙伴們得掌握相關技能;當下相對比…