分散式ID-入門瞭解
阿新 • • 發佈:2018-10-31
分散式ID-入門瞭解
1. 概念:
在分散式系統中,經常需要對大量的資料、訊息、http請求等進行唯一標識,就需要不能出現的ID。 網際網路應用中,某個表可能要佔用很大的物理儲存空間,為了解決該問題,使用資料庫分片技術。將一個數據庫進行拆分,通過資料庫中介軟體連線。 如果資料庫中該表選用ID自增策略,則可能產生重複的ID,此時應該使用分散式ID生成策略來生成ID。 例如:比如下訂單需求,因資料庫訂單表已經分片,若用主鍵自增,分片後的各個表會產生重複ID。所以這個系統需要滿足以下需求: 全域性唯一:不能出現重複ID。 高可用:ID生成系統是基礎系統,被許多關鍵系統呼叫,一旦宕機,會造成嚴重影響。
2.解決方式:
1.UUID(本地生成32位的ID,不需要進行遠端呼叫,時延低,效能高;ID過長,沒有排序) 2.Flicker方案(採用了MySQL自增長ID的機制,可靠性高,有序;系統擴容困難,資料庫壓力大) 3.TDDL序列生成方式(阿里的分庫分表中介軟體,有全域性資料庫ID的生成方式;強依賴資料庫,資料庫異常時整個系統不可用) 4.Redis(可產生自增序號;主鍵產生需強依賴Redis) 5.Oracle(可產生與表無關的序列;只有Oracle資料庫才能使用) 6.Snowflake演算法(有序,效能高,可調整bit位劃分; 依賴機器時鐘,如果機器時鐘回撥,會導致重複ID生成。 在單機上是遞增的,但是由於涉及到分散式環境,每臺機器上的時鐘不可能完全同步,有時候會出現不是全 局遞增的情況。) ***推薦使用雪花演算法,時鐘問題可百度解決!!! 主要原因: 業務需求:業務要求生成的ID要有遞增趨勢,全域性唯一,並且為數字。 系統考慮:第三種方案效能高,穩定性高,對外部資源依賴少。 依據實際業務需求和系統規劃,對演算法進行區域性調整,可使用 發號器snowflake方案。
3.Snowflake演算法:
開源的twitter( 非官方中文慣稱:推特。是國外的一個網站,是一個社交網路及微部落格服務)的snowflake演算法。 * <p>名稱:IdWorker.java</p> * <p>描述:分散式自增長ID</p> * <pre> * Twitter的 Snowflake JAVA實現方案 * </pre> * 核心程式碼為其IdWorker這個類實現,其原理結構如下,我分別用一個0表示一位,用—分割開部分的作用: * 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000 * 在上面的字串中,第一位為未使用(實際上也可作為long的符號位),接下來的41位為毫秒級時間, * 然後5位datacenter(資料中心)標識位,5位機器(也叫程序)ID(並不算識別符號,實際是為執行緒標識), * 然後12位該毫秒內的當前毫秒內的計數,加起來剛好64位,為一個Long型。 * 這樣的好處是,整體上按照時間自增排序,並且整個分散式系統內不會產生ID碰撞(由datacenter和機器ID作區分), * 並且效率較高,經測試,snowflake每秒能夠產生26萬ID左右,完全滿足需要。 * 64位二進位制ID (42(毫秒)+5(機器ID)+5(業務編碼)+12(重複累加序列號))-->生成後會轉為十進位制的long型別整數 【使用】: (1)工具類IdWorker.java拷貝到common工具類工程; (2)在service工程的spring配置檔案中新增配置(每個節點的程序和資料資料不能一樣,若一樣ID可能會重複); <bean id="idWorker" class="util.IdWorker"> <!-- 程序 ID 取值:0~31 --> <constructor-arg index="0" value="0"></constructor-arg> <!-- 資料中心 ID 取值:0~31 --> <constructor-arg index="1" value="0"></constructor-arg> </bean> (3)生成。 @Autowired private IdWorker idWorker; long orderId = idWorker.nextId(); **直接用: IdWorker idWorker = new IdWorker(); long orderId = idWorker.nextId();