這裏的博客版本都不會被更新維護。查看最新的版本請移步: http://neojos.com
全稱Universally Unique Identifier
,UUID
佔128bit
,也就是16個英文字符的長度(16byte
),須要強調的是,它的生成無需中心處理程序。html
UUID
被用來標識URN(Uniform Resource Names)
,對於Transaction ID
以及其餘須要惟一標誌的場景均可以使用它。java
UUID
是空間和時間上的惟一標識,它長度固定,內部中包含時間信息。若是服務器時間存在不一樣步的狀況,UUID
可能會出現重複。node
UUID
構成基本格式,由6部分組成:mysql
time-low - time-mide - time-high-and-version - clock-seq-and-reserved & clock-seq-low - node
一個URN
示例:f81d4fae-7dec-11d0-a765-00a0c91e6bf6
。sql
由於UUID
佔128bit
,16進制數佔4bit
,因此轉換成16進制0-f
的字符串總共有32位。組成的各個部分具體由幾位16進製表示,請查閱 Namespace Registration Template
mongodb
由於UUID
太長且無序,致使其不適合作MySQL
的主鍵索引。並且MySQL
自帶的auto-increment
功能,選擇bigint
的話也只佔用64bit
。數組
All indexes other than the clustered index are known as secondary indexes. InInnoDB
, each record in a secondary index contains the primary key columns for the row, as well as the columns specified for the secondary index.InnoDB
uses this primary key value to search for the row in the clustered index.If the primary key is long, the secondary indexes use more space, so it is advantageous to have a short primary key.緩存
MongoDB's ObjectId
ObjectId
由佔4-byte
的時間戳、3-byte
的機器標識、2-byte
的進程ID
以及3-byte
的計數組成,總共仍是佔用96bit
。服務器
這些ID
組成包括時間、機器標識、隨機數,在UUID
生成時還使用到MAC
地址。這些參數中時間是關鍵,保證集羣服務器的時鐘準確很是重要。分佈式
Twitter Snowflake
Twitter Snowflake
生成的ID
佔64bit
,跟bigint
大小一致。由41 bit
毫秒精度的時間戳、10bit
的機器ID
以及12 bit
的序列號組成(計數每4096就從新開始一輪),剩下的1 bit
奉獻給將來。
做者修改了它的原始設定,將剩下的1 bit
給了時間戳。使用機器MAC
地址的HASH
值做爲當前機器的ID
。
服務全局保存最近一次生成ID
的時間戳lastTimestamp
,做爲生成新ID
的判斷依據,避免時間回溯。詳細代碼請參照[1]
。
// Block and wait till next millisecond private long waitNextMillis(long currentTimestamp) { while (currentTimestamp == lastTimestamp) { currentTimestamp = timestamp(); } return currentTimestamp; }
同時將sequence
也聲明爲全局變量,每間隔4096次就從新開始計數。主要用於應對:當時間戳相同時保證生成的ID
是不一樣的。
if (currentTimestamp == lastTimestamp) { sequence = (sequence + 1) & maxSequence; if(sequence == 0) { // Sequence Exhausted, wait till next millisecond. currentTimestamp = waitNextMillis(currentTimestamp); } } else { // reset sequence to start with zero for the next millisecond sequence = 0; }
Database Ticket Servers
該方式經過中心的DB
服務來生成惟一自增ID
,但DB
服務的寫操做會成爲系統的瓶頸。若是後臺是單個DB
服務的話,存在單點問題。
參考Flickr
的方法,後臺使用兩個DB
來生成ID
,其中auto-increment
一個按照奇數步長增加,另外一個按照偶數步長增加。MySQL
內部使用REPLACE
來實現,經過一條衝突的記錄,來持續生成自增的主鍵ID
。
REPLACE
makes sense only if a table has aPRIMARY KEY
orUNIQUE
index. Otherwise, it becomes equivalent toINSERT
, because there is no index to be used to determine whether a new row duplicates another.
結合Twitter Snowflake
對ID
作以下調整:41-bit
的毫秒時間戳、13-bit
的數據邏輯分區以及10-bit
的自增序列。自增序列對1024取餘,每一個分區每毫秒內能生成1024
個自增ID
。
Flickr
中各個數據表按照不一樣的步長增加,當須要分表的時候就會存在巨複雜的數據遷移問題。爲了解決這個問題,便引入了邏輯分區Shard ID
。經過邏輯上的Shard
,將數據分散在不一樣的數據表中。這樣後續的分庫分表均可以經過操做邏輯上Shard
來實現,將DB
從具體的實現中解脫出來。
關於獲取MySQL
自增ID
,代碼沒法批量獲取插入的所有自增ID
列表,MySQL
只會返回第一條記錄的自增ID
。由於自增ID
是連續的,因此能夠經過計算的方式來計算出ID
列表。
If you insert multiple rows using a singleINSERT
statement,LAST_INSERT_ID()
returns the value generated for the first inserted row only. The reason for this is to make it possible to reproduce easily the sameINSERT
statement against some other server.
關於Shard
能夠查看本地緩存BigCache
,頗有參考意義(我以爲)。
文中介紹了ID
的兩種生成方式,核心的區別在於:整個系統的ID
是否支持單調遞增。Twitter Snowflake
以及UUID
能夠保證生成的數據惟一,但多臺服務器的話,沒法保證生成的數據有序。而Ticket Servers
經過結合MySQL
的auto-increment
解決了這個問題。
參考文章: