原文連接:何曉東 博客html
文章起源於 康神交流羣的 panda大佬和boss li關於發號器的一些交流,特此感謝讓咱們學到了新知識。
在分佈式系統中,常常須要對大量的數據、消息、http 請求等進行惟一標識,例如:對於分佈式系統,服務間相互調用須要惟一標識,調用鏈路分析,日誌追蹤的時候須要使用這個惟一標識。此時須要一個全局惟一的 ID。mysql
持久化git
要知足長期全局惟一,持久化是必須的,確定不能讓已經使用的再次產生一遍,同時須要強一致性。可用選擇存儲在 Redis 或者 Etcd 中。
高可用github
這個時候須要提供發號器服務的機器主從同步,可以在主服務器宕機的時候,自動選擇從服務器,切換過程當中,發號器生成的 ID 可能不連續,服務正常就能夠。
其餘特性算法
主要是看具體業務了,須要認證和權限控制都是可選的,可用在請求層限制來源 IP,只容許固定的 IP 訪問。
UUID 是 Universally Unique Identifier 的縮寫,它是在必定的範圍內(從特定的名字空間到全球)惟一的機器生成的標識符,UUID 是16字節128位長的數字,一般以36字節的字符串表示,好比:3F2504E0-4F89-11D3-9A0C-0305E82C3301。sql
UUID經由必定的算法機器生成,爲了保證 UUID 的惟一性,規範定義了包括網卡 MAC 地址、時間戳、名字空間(Namespace)、隨機或僞隨機數、時序等元素,以及從這些元素生成 UUID 的算法。UUID 的複雜特性在保證了其惟一性的同時,意味着只能由計算機生成。數據庫
優缺點: 本地生成,性能高,延遲低,位數長,不適用看成索引字段,同時是無序的,難以根據特徵分析趨勢。segmentfault
snowflake是twitter開源的分佈式ID生成算法,其核心思想爲,一個long型的ID:
41bit做爲毫秒數 - 10bit做爲機器編號 - 12bit做爲毫秒內序列號
算法單機每秒內理論上最多能夠生成1000*(2^12),也就是400W的ID,
服務器
優缺點: 整個 ID 都是自增的,這個很是適合查看趨勢,同時生成不依賴於第三方系統,可靠性很高,可調整性也很高。缺點就是嚴重依賴機器時鐘。異步
字段設置 auto_increment_increment
和 auto_increment_offset
來保證 ID 自增,每次業務使用下列 SQL 讀寫 MySQL 獲得 ID。
begin; REPLACE INTO Tickets64 (stub) VALUES ('a'); SELECT LAST_INSERT_ID(); commit;
爲了保證高可用,須要有多臺 MySQL 機器,也須要爲每臺機器設置不一樣的自增起始值和步長,例如:
# TicketServer1: auto-increment-increment = 2 auto-increment-offset = 1 # TicketServer2: auto-increment-increment = 2 auto-increment-offset = 2
優缺點: 簡單可靠,成本很小,由專業 DBA 進行維護就能夠的。ID 單調遞增,有合適的業務是最好的。缺點就是強依賴於數據庫,修改起點和步長優勢困難,同時也須要額外保證數據庫的穩定可用。每次請求都去額外讀寫數據庫的狀況下,形成數據庫壓力很大,須要消耗不少資源。
以上就是最經常使用的三種全局惟一 ID 生成方案,採用較多的是類 snowflake 的方案,若是請求數列不是很高,能夠調低時間的精度等,靈活性很高。生成的 ID 時間趨勢自增,甚至能夠用來作索引字段,佔用空間較小。後期對數據進行分析的時候也很方便。
類 snowflake 的方案,會採用請求時生成的方式,沒法提早生成。
基於 MySQL 的發號器,或者 uuid 模式的,可用提早生成一大批數據,根據業務去定生成數量,放到內存,MQ 或者 Redis List中,業務申請惟一 ID 的時候,直接從其中彈一個出來。同時加一個異步定時任務,固定時間計算一下隊列中剩餘的惟一 ID 數量,數量不足時及時的再次生成一大批,加入到備選隊列。
Go snowflake的demo:
參考文章:
一如既往,推薦幾個 高質量課程,你學到新東西,我賺點佣金,你們都是贏家。