什么是數(shù)據(jù)庫主鍵 ID 生成策略?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司,提供成都做網(wǎng)站、成都網(wǎng)站制作,網(wǎng)頁設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務;可快速的進行網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴展;專業(yè)做搜索引擎喜愛的網(wǎng)站,是專業(yè)的做網(wǎng)站團隊,希望更多企業(yè)前來合作!
前言:
系統(tǒng)唯一 ID 是我們在設(shè)計一個系統(tǒng)的時候常常會遇見的問題,下面介紹一些常見的 ID 生成策略。
● Sequence ID
● UUID
● GUID
● COMB
● Snowflake
最開始的自增 ID 為了實現(xiàn)分庫分別的需求,會在自增的前提下,使用不同起點,但需要做數(shù)據(jù)庫拓展時,極其麻煩。 比如剛開始時,我們設(shè)計某個系統(tǒng)的數(shù)據(jù)庫時,這個數(shù)據(jù)庫中會有 10 個表,那么我們對于每個表的內(nèi)容都需要不同的 ID 我們就可以使用不同不長自增的形式,比如,第一張表的是 1、11、21、31。。。 第二張表是 2、12、22、32。。。 第三張表是 3、13、23、33。。。 第十張表就是 10、20、30。。。 但是這樣的問題就是,如果有一天我發(fā)現(xiàn)這個系統(tǒng)的 10 張表已經(jīng)不夠用了,我想要再添加一張表,那么這時的主鍵應該怎么分配呢? 另外,如果對于多個數(shù)據(jù)庫的數(shù)據(jù)希望合并,但是對于這種簡單的生成 ID 方式,重復的可能性很大,所以幾乎一定會發(fā)生重復這種情況。 顯然,如果使用之前的方法的可擴展性會比較差。
相比自增 ID,UUID 生成唯一主鍵更加方便(數(shù)據(jù)量非常大的情況下,存在重復的可能),但由于 UUID 的無序性,性能不如自增 ID,字符串儲存,儲存空間大,查詢效率低。關(guān)鍵:使用 uuid 的缺點是查詢效率低啊!
COMB 相對于 UUID,增加了生成 ID 的有序性,插入與查詢效率都有所提高。 這篇文章有簡單的分析。
Sonwflake 是 Twitter 主鍵生成策略,可以看做是 COMB 的一種改進,用 64 位的長整型代替 128 位的字符串。ID 構(gòu)成:第一位 0 + 41 位的時間前綴 + 10 位的節(jié)點標識 + 12 位的 sequence 避免并發(fā)的數(shù)字。
第一部分:Sequence ID
數(shù)據(jù)庫自增長序列或字段,最常見的方式。由數(shù)據(jù)庫維護,數(shù)據(jù)庫唯一。
優(yōu)點:
簡單,代碼方便,性能可以接受。
數(shù)字 ID 天然排序,對分頁或者需要排序的結(jié)果很有幫助。
缺點:
不同數(shù)據(jù)庫語法和實現(xiàn)不同,數(shù)據(jù)庫遷移的時候或多數(shù)據(jù)庫版本支持的時候需要處理。
在單個數(shù)據(jù)庫或讀寫分離或一主多從的情況下,只有一個主庫可以生成。有單點故障的風險。
在性能達不到要求的情況下,比較難于擴展。
如果遇見多個系統(tǒng)需要合并或者涉及到數(shù)據(jù)遷移會相當痛苦。
分表分庫的時候會有麻煩。
優(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ù)庫操作的負載。
第二部分:UUID
npm 管理 https://www.npmjs.com/package/uuid
常見的方式,128 位??梢岳脭?shù)據(jù)庫也可以利用程序生成,一般來說全球唯一。
UUID 是 128 位的全局唯一標識符,通常由 32 字節(jié)的字符串表示。它可以保證時間和空間的唯一性,也稱為 GUID,全稱為:UUID ―― Universally Unique IDentifier,Python 中叫 UUID。
它通過 MAC 地址、時間戳、命名空間、隨機數(shù)、偽隨機數(shù)來保證生成 ID 的唯一性。
UUID 主要有五個算法,也就是五種方法來實現(xiàn)。
(1)、uuid1()
――基于時間戳。由 MAC 地址、當前時間戳、隨機數(shù)生成。可以保證全球范圍內(nèi)的唯一性,但 MAC 的使用同時帶來安全性問題,局域網(wǎng)中可以使用 IP 來代替 MAC。
(2)、uuid2()
基于分布式計算環(huán)境 DCE(Python 中沒有這個函數(shù))。算法與 uuid1 相同,不同的是把時間戳的前 4 位置換為 POSIX 的 UID。實際中很少用到該方法。
(3)、uuid3()
基于名字的 MD5 散列值。通過計算名字和命名空間的 MD5 散列值得到,保證了同一命名空間中不同名字的唯一性,和不同命名空間的唯一性,但同一命名空間的同一名字生成相同的 uuid。
(4)、uuid4()
基于隨機數(shù)。由偽隨機數(shù)得到,有一定的重復概率,該概率可以計算出來。
(5)、uuid5()
基于名字的 SHA-1 散列值。算法與 uuid3 相同,不同的是使用 Secure Hash Algorithm 1 算法。
優(yōu)點:
簡單,代碼方便。
全球唯一,在遇見數(shù)據(jù)遷移,系統(tǒng)數(shù)據(jù)合并,或者數(shù)據(jù)庫變更等情況下,可以從容應對。
缺點:
沒有排序,無法保證趨勢遞增。
UUID 往往是使用字符串存儲,查詢的效率比較低。
存儲空間比較大,如果是海量數(shù)據(jù)庫,就需要考慮存儲量的問題。
傳輸數(shù)據(jù)量大
不可讀。
優(yōu)化方案:
為了解決 UUID 不可讀,可以使用 UUID to Int64 的方法。
第三部分: GUID
GUID:是微軟對 UUID 這個標準的實現(xiàn)。UUID 還有其它各種實現(xiàn),不止 GUID 一種。優(yōu)缺點同 UUID。
第四部分: COMB
COMB(combine)型是數(shù)據(jù)庫特有的一種設(shè)計思想,可以理解為一種改進的 GUID,它通過組合 GUID 和系統(tǒng)時間,以使其在索引和檢索事有更優(yōu)的性能。
數(shù)據(jù)庫中沒有 COMB 類型,它是 Jimmy Nilsson 在他的 “The Cost of GUIDs as Primary Keys” 一文中設(shè)計出來的。\
COMB 數(shù)據(jù)類型的基本設(shè)計思路是這樣的:既然 UniqueIdentifier 數(shù)據(jù)因毫無規(guī)律可言造成索引效率低下,影響了系統(tǒng)的性能,那么我們能不能通過組合的方式,保留 UniqueIdentifier 的前 10 個字節(jié),用后 6 個字節(jié)表示 GUID 生成的時間(DateTime),這樣我們將時間信息與 UniqueIdentifier 組合起來,在保留 UniqueIdentifier 的唯一性的同時增加了有序性,以此來提高索引效率。
優(yōu)點:
解決 UUID 無序的問題,在其主鍵生成方式中提供了 Comb 算法 (combined guid/timestamp)。保留 GUID 的 10 個字節(jié),用另 6 個字節(jié)表示 GUID 生成的時間 (DateTime)。
性能優(yōu)于 UUID。
第五部分: Twitter 的 snowflake 算法
snowflake 是 Twitter 開源的分布式 ID 生成算法,結(jié)果是一個 long 型的 ID。其核心思想是:使用 41bit 作為毫秒數(shù),10bit 作為機器的 ID(5 個 bit 是數(shù)據(jù)中心,5 個 bit 的機器 ID),12bit 作為毫秒內(nèi)的流水號(意味著每個節(jié)點在每毫秒可以產(chǎn)生 4096 個 ID),最后還有一個符號位,永遠是 0。snowflake 算法可以根據(jù)自身項目的需要進行一定的修改。比如估算未來的數(shù)據(jù)中心個數(shù),每個數(shù)據(jù)中心的機器數(shù)以及統(tǒng)一毫秒可以能的并發(fā)數(shù)來調(diào)整在算法中所需要的 bit 數(shù)。
優(yōu)點:
不依賴于數(shù)據(jù)庫,靈活方便,且性能優(yōu)于數(shù)據(jù)庫。
ID 按照時間在單機上是遞增的。
缺點:
在單機上是遞增的,但是由于涉及到分布式環(huán)境,每臺機器上的時鐘不可能完全同步,也許有時候也會出現(xiàn)不是全局遞增的情況。
六、使用
這個使用起來是真的方便:
npm install uuid --save
然后就可以使用啦!
const uuidv1 = require(‘uuid/v1‘); console.log(‘隨機uuid字符串‘, uuidv1());
這樣,我們就可以打印出來 uuid 字符串了。 每次的都不一樣。
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。