ID作為業務的唯一標識,在資料設計中屢見不鮮,例如:
•商品—— product_id
•訂單—— order_id
•訊息—— message_id
這些標識往往就是資料庫的主鍵,My會在資料庫的主鍵,My會在資料庫的主鍵,My會在資料庫的主鍵,My會在資料庫的主鍵,My會在資料庫主鍵是建立叢集索引,這個索引直接指向資料位址。相比普通索引指向聚集索引,減少了一次索引查詢,速度很快。訊息、訂單類似業務一般會有按照時間倒序查詢資料的需求,一種做法是在時間列上建立索引,更好的是依賴ID本身的插入有序性。所以,分散式ID需要滿足兩個核心條件:
•全域唯一
•時間趨勢有序
可能有人會說了,直接用MySQL的auto_increment不就行了麼。在創業初期的時候我也會選擇這個方案,簡單、有效率、快速──新創公司還是得快速迭代,盡快出產品,而且產品經常變,花太多時間搞出的牛逼架構說不定不太用得上,浪費了寶貴的時間。但這個方案是存在一些問題的:
•影響並行插入-B記錄依賴A記錄的主鍵,需要等到A記錄插入成功,拿到A.id,才能插入B記錄
•資料復原難度— —資料誤刪或遺失後,由於日誌中沒有ID,無法直接確定資料關聯性
•影響分庫分錶-由於ID要插入後才知道,不能根據業務的主鍵進行分庫分錶
所以,在業務穩定後,一定要抽出時間來還早期的技術債。
常見方案
使用資料庫的auto_increment來產生唯一ID
優點
•簡單,使用已有功能,開發量小
•ID步長固定
可用
•即使按照不同auto_increment起點擴展多個主庫,雖然提高了可用性,但卻不能保證ID的嚴格有序
•每次都需要訪問數據庫,容易到達性能天花板
批量拉取ID,逐一分配
此方案也是將ID資料存入資料庫,ID服務每次從資料庫中拉取N個ID,並將目前已用ID最大值更新為原始資料+N,ID服務每次接到ID產生請求時就從這N個ID中依序回傳。
優點
•批量獲取,不用每次訪問資料庫,資料庫壓力小
缺點
•整個服務還是單點
•服務宕機重啟會造成不連續度
ID 增加一套備用服務,主服務掛了漂移到備用服務上,可以採用vip + keepalived或增加proxy。 uuid優點•本地產生ID,沒有單點問題,沒有效能瓶頸缺點•無法保證遞增有序•長久以來,作為主鍵效能低•不能保證遞增有序
•長久合約,作為主鍵效能低度snowflake是twitter開源的分散式ID產生演算法,其核心思想是:一個long型的ID,使用其中41bit作為毫秒數,10bit作為機器編號,12bit作為毫秒內序號。這個演算法單機每秒內理論上最多可以產生1000*(2^12),也就是400W的ID,完全能滿足業務的需求。
借鏡snowflake的思想,結合各公司的業務邏輯和並發量,可以實現自己的分散式ID產生演算法。
優點
•時間在高位,趨勢遞增
•實現簡單,不依賴其它服務,方便擴展
缺點
•沒有全局時鐘,單機絕對有序,但從整個集群來看,是趨勢
•沒有全局時鐘,單機絕對有序,但從整個集群來看,是趨勢有趨勢序的
注意事項
•由於ID常作為分庫分錶的標識,所以需要這些ID有一定的隨機性,不至於分庫後的數據不均勻,可以在每個毫秒開始時序號不從1開始,二是從0-9中的任意一個開始