日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

[转]【分布式系统】唯一ID生成策略总结

發(fā)布時間:2023/12/4 windows 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转]【分布式系统】唯一ID生成策略总结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

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

全局唯一id介紹

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

? ? 全局唯一id特點:

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

    ? ? 1、數(shù)據(jù)庫自增長序列或字段生成id

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

    ? ? 【優(yōu)點】

  • 非常簡單。利用現(xiàn)有數(shù)據(jù)庫系統(tǒng)的功能實現(xiàn),成本小,代碼簡單,性能可以接受。
  • ID號單調(diào)遞增。可以實現(xiàn)一些對ID有特殊要求的業(yè)務(wù),比如對分頁或者排序結(jié)果這類需求有幫助。
  • ? ? 【缺點】

    ? ? 1. 強依賴DB。不同數(shù)據(jù)庫語法和實現(xiàn)不同,數(shù)據(jù)庫遷移的時候、多數(shù)據(jù)庫版本支持的時候、或分表分庫的時候需要處理,會比較麻煩。當(dāng)DB異常時整個系統(tǒng)不可用,屬于致命問題。

    ? ? 2. 單點故障。在單個數(shù)據(jù)庫或讀寫分離或一主多從的情況下,只有一個主庫可以生成。有單點故障的風(fēng)險。

    ? ? 3. 數(shù)據(jù)一致性問題。配置主從復(fù)制可以盡可能的增加可用性,但是數(shù)據(jù)一致性在特殊情況下難以保證。主從切換時的不一致可能會導(dǎo)致重復(fù)發(fā)號。

    ? ? 4. 難于擴展。在性能達不到要求的情況下,比較難于擴展。ID發(fā)號性能瓶頸限制在單臺MySQL的讀寫性能。

    ? ? 【部分優(yōu)化方案】

    ? ? 針對主庫單點, 如果有多個Master庫,則每個Master庫設(shè)置的起始數(shù)字不一樣,步長一樣,可以是Master的個數(shù)。比如:Master1 生成的是 1,4,7,10,Master2生成的是2,5,8,11 Master3生成的是 3,6,9,12。這樣就可以有效生成集群中的唯一ID,也可以大大降低ID生成數(shù)據(jù)庫操作的負(fù)載。

    ? ? 2、UUID

    ? ? 常見的生成id方式,利用程序生成。

    ? ? UUID (Universally Unique Identifier) 的目的,是讓分布式系統(tǒng)中的所有元素,都能有唯一的辨識資訊,而不需要透過中央控制端來做辨識資訊的指定。如此一來,每個人都可以建立不與其它人沖突的 UUID。在這樣的情況下,就不需考慮數(shù)據(jù)庫建立時的名稱重復(fù)問題。

    ? ? UUID的標(biāo)準(zhǔn)形式包含32個16進制數(shù)字,以連字號分為五段,形式為8-4-4-4-12的36個字符,示例:550e8400-e29b-41d4-a716-446655440000,到目前為止業(yè)界一共有5種方式生成UUID,詳情見IETF發(fā)布的UUID規(guī)范 A Universally Unique IDentifier (UUID) URN Namespace。

    ? ?在Java中我們可以直接使用下面的API生成UUID:

    UUID uuid = UUID.randomUUID(); String s = UUID.randomUUID().toString();

    ? ? 【優(yōu)點】

  • 非常簡單,本地生成,代碼方便,API調(diào)用方便
  • 性能非高。生成的id性能非常好,沒有網(wǎng)絡(luò)消耗,基本不會有性能問題。
  • 全球唯一。在數(shù)據(jù)庫遷移、系統(tǒng)數(shù)據(jù)合并、或者數(shù)據(jù)庫變更的情況下,可以 從容應(yīng)對。
  • ? ? 【缺點】

  • 存儲成本高。UUID太長,16字節(jié)128位,通常以36長度的字符串表示,很多場景不適用。如果是海量數(shù)據(jù)庫,就需要考慮存儲量的問題。
  • 信息不安全。基于MAC地址生成UUID的算法可能會造成MAC地址泄露,這個漏洞曾被用于尋找梅麗莎病毒的制作者位置。
  • 不適用作為主鍵,ID作為主鍵時在特定的環(huán)境會存在一些問題,比如做DB主鍵的場景下,UUID就非常不適用。UUID往往是使用字符串存儲,查詢的效率比較低。
  • UUID是無序的。不是單調(diào)遞增的,而現(xiàn)階段主流的數(shù)據(jù)庫主鍵索引都是選用的B+樹索引,對于無序長度過長的主鍵插入效率比較低。
  • 傳輸數(shù)據(jù)量大。
  • 不可讀。
  • ? ? 【部分優(yōu)化方案】

    ? ? 為了解決UUID不可讀, 可以使用UUID to Int64的方法 。

    ? ? 為了解決UUID無序的問題, NHibernate在其主鍵生成方式中提供了Comb算法(combined guid/timestamp)。保留GUID的10個字節(jié),用另6個字節(jié)表示GUID生成的時間(DateTime)。

    ? ? 3、Redis生成ID

    ? ? 當(dāng)使用數(shù)據(jù)庫來生成ID性能不夠要求的時候,我們可以嘗試使用Redis來生成ID。這主要依賴于Redis是單線程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作 INCR和INCRBY來實現(xiàn)。

    ? ? 可以使用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

    ? ? 這個負(fù)載到哪臺機器上需要提前設(shè)定好,未來很難做修改。但是3-5臺服務(wù)器基本能夠滿足,都可以獲得不同的ID。步長和初始值一定需要事先設(shè)定好。使用Redis集群也可以防止單點故障的問題。

    ? ? 比較適合使用Redis來生成日切流水號。比如訂單號=日期+當(dāng)日自增長號。可以每天在Redis中生成一個Key,使用INCR進行累加。

    ? ? 【優(yōu)點】

  • 不依賴于數(shù)據(jù)庫,靈活方便,且性能優(yōu)于數(shù)據(jù)庫。
  • 數(shù)字ID天然排序,對分頁或者需要排序的結(jié)果很有幫助。
  • ? ? 【缺點】

  • 如果系統(tǒng)中沒有Redis,還需要引入新的組件,增加系統(tǒng)復(fù)雜度。

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

  • Redis單點故障,影響序列服務(wù)的可用性。

  • ? ? 4、zookeeper生成ID

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

    ? ? 很少會使用zookeeper來生成唯一ID。主要是由于需要依賴zookeeper,并且是多步調(diào)用API,如果在競爭較大的情況下,需要考慮使用分布式鎖。因此,性能在高并發(fā)的分布式環(huán)境下,也不甚理想。

    ? ? 5、Twitter的snowflake算法

    ? ? snowflake(雪花算法)是Twitter開源的分布式ID生成算法,結(jié)果是一個long型的ID。這種方案把64-bit分別劃分成多段,分開來標(biāo)示機器、時間等。如圖:

    ? ? 其核心思想是:使用41bit作為毫秒數(shù),10bit作為機器的ID(5個bit是數(shù)據(jù)中心,5個bit的機器ID),12bit作為毫秒內(nèi)的流水號(意味著每個節(jié)點在每毫秒可以產(chǎn)生 4096 個 ID),最后還有一個符號位,永遠是0。具體實現(xiàn)的代碼可以參看github。

    ? ? snowflake算法可以根據(jù)自身項目的需要進行一定的修改。比如估算未來的數(shù)據(jù)中心個數(shù),每個數(shù)據(jù)中心的機器數(shù)以及統(tǒng)一毫秒可以能的并發(fā)數(shù)來調(diào)整在算法中所需要的bit數(shù)。

    ? ? 【優(yōu)點】

  • 穩(wěn)定性高,不依賴于數(shù)據(jù)庫等第三方系統(tǒng),以服務(wù)的方式部署,穩(wěn)定性更高,生成ID的性能也是非常高的。
  • 靈活方便,可以根據(jù)自身業(yè)務(wù)特性分配bit位。
  • 單機上ID單調(diào)自增,毫秒數(shù)在高位,自增序列在低位,整個ID都是趨勢遞增的。
  • ? ? 【缺點】

  • 強依賴機器時鐘,如果機器上時鐘回?fù)?#xff0c;會導(dǎo)致發(fā)號重復(fù)或者服務(wù)會處于不可用狀態(tài)。

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


  • ---------------------
    作者:夢 * 蝶
    來源:CSDN
    原文:https://blog.csdn.net/LZ15932161597/article/details/113397226
    版權(quán)聲明:本文為作者原創(chuàng)文章,轉(zhuǎn)載請附上博文鏈接!
    內(nèi)容解析By:CSDN,CNBLOG博客文章一鍵轉(zhuǎn)載插件

    總結(jié)

    以上是生活随笔為你收集整理的[转]【分布式系统】唯一ID生成策略总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。