前幾天研究資料庫分表分庫的問題,其中有乙個關鍵的地方就是生成唯一鍵的問題,假如資料表有1億條資料,而且還在不斷的增加,這裡我們就需要考慮到分表分庫,假設我們採用hash或者是使用者取模求餘的方法將這個表拆分成10個表,每個表的結構相同,其中有乙個主鍵id,那麼10個表中的id需要唯一不同,在單錶的時候,使用資料表自增長是沒有問題的。當分成10個表後,就無法用到資料庫自增長了。
當到這裡的時候突然發現oracle資料庫的序列真是好東西,在剛剛接觸的時候還很鬱悶這種設計真是沒有mysql獲sqlserver中的方便
目前做唯一id的做法基本有三種
1.使用uuid來實現,快速不重複,只是生成的id沒有規則
2.使用外部的id分發中心來實現,生存的id簡短有規則,缺點是依賴於單點
3.在資料庫中做乙個計數表來做,有點類是於oracle中的序列
以下內容大部分來自於網路:
uuid的目的,是讓分布式系統中的所有元素,都能有唯一的辨識資訊,而不需要通過**控制端來做辨識資訊的指定。如此一來,每個人都可以建立不與其它人衝突的uuid。在這樣的情況下,就不需考慮資料庫建立時的名稱重複問題。
一組uuid,是由一串16位組(亦稱128位)的16進製數字所構成,是故uuid理論上的總數為216 x 8=2128,約等於3.4 x 1038。也就是說若每納秒產生1兆個uuid,要花100億年才會將所有uuid用完。
uuid的標準型式包含32個16進製數字,以連字型大小分為五段,形式為8-4-4-4-12的36個字元。示例:
550e8400-e29b-41d4-a716-446655440000
snowflake是twitter開源的一款獨立的適用於分布式環境的id生成伺服器。生成的id是64bits,同時滿足高效能(>10k ids/s),低延遲(<2ms)和高可用。與mongodb objectid類似這裡生成的id也是時間上有序的。編碼方式也和objectid類似,如下:
0 41 51 64
+-----------+------+------+
|time |pc |inc |
+-----------+------+------+
mongodb中每一條記錄都有乙個』id』字段用來唯一標示本記錄。如果使用者插入資料時沒有顯示提供』id』字段,那麼系統會自動生成乙個。objectid一共12bytes,設計的時候充分考慮了分布式環境下使用的情況,所以能保證在乙個分布式mongodb集群中唯一。objectid格式如下:
0 4 7 9 12
+--------+------+----+------+
|time |pc |pid |inc |
+--------+------+----+------+
最後生成的仍然是乙個用16進製表示的串,如47cc67093475061e3d95369d
。這裡mongodb的objectid相對uuid有個很大的優點就是objectid是時間上有序的。另外還有objectid本身也包含了很多其它有用的資訊,通過直接解碼objectid即可直接獲得這些資訊。
這個是flickr在遇到生成全域性id問題時採用的辦法。利用了資料庫中auto_increment的特性和mysql特有的replace info
命令,專門乙個資料庫例項用來產生id。大致的過程是這樣的:
create table `tickets64` (
`id` bigint(20) unsigned not null auto_increment,
`stub` char(1) not null default '',
primary key (`id`),
unique key `stub` (`stub`)
) engine=myisam
+-------------------+------+
| id | stub |
+-------------------+------+
| 72157623227190423 | a |
+-------------------+------+
replace into tickets64 (stub) values ('a');
select last_insert_id();
另外為了防止這個ticket server單點故障,可以設定兩個ticket server例項。其中乙個產生奇數id,另乙個產生偶數id。
ticketserver1:
auto-increment-increment = 2
auto-increment-offset = 1
ticketserver2:
auto-increment-increment = 2
auto-increment-offset = 2
應用交替請求兩個server,這樣不僅壓力減小一半,故障風險也降低一半。不過這裡也有個問題,就是當一台機器故障時,另一台正常機器產生的id將會領先故障機器一截,可能會造成不再是時間上有序的id。按照flickr的說法,這並不影響他們的應用。
instagram要將其中儲存的分片到多個postgresql中,其中生成id的方案和mongodb objectid類似。整個id的長度為64bits,設定為這個長度是為了優化在redis中的儲存。id的編碼格式如下:
id的生成邏輯用pl/pgsql語言寫到postgresql資料庫中,當每次插入資料時由資料庫自動計算生成。
分布式ID生成方案
系統唯一id是設計乙個系統的時候常常會遇到的問題,也常常為這個問題而糾結。生成id的方法有很多,適應不同的場景 需求以及效能要求。所以有些比較複雜的系統會有多個id生成的策略。1 全域性唯一性 不能出現重複的id號,既然是唯一標識,這是最基本的要求 2 粗略有序 如果在分布式環境中做到完全有序,需要...
細聊分布式ID生成方法
幾乎所有的業務系統,都有生成乙個記錄標識的需求,例如 訊息標識 message id 訂單標識 order id 帖子標識 tiezi id 這個記錄標識往往就是資料庫中的唯一主鍵,資料庫上會建立聚集索引 cluster index 即在物理儲存上以這個字段排序。這個記錄標識上的查詢,往往又有分頁或...
分布式全域性ID生成方案
1 背景 分布式架構下,唯一序列號生成是我們在設計乙個系統,尤其是資料庫使用分庫分表的時候常常會遇見的問題。當分成若干sharding表後,如何能夠快速拿到乙個唯一序列號,是經常遇到的問題。在網際網路的業務系統中,涉及到各種各樣的id,如在支付系統中就會有支付id 退款id等。那一般生成id都有哪些...