分散式情況下產生資料庫唯一ID的解決方案

伊谢尔伦
發布: 2016-11-21 14:25:56
原創
1262 人瀏覽過

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中的任意一個開始

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!