1. 程式人生 > >分散式ID-入門瞭解

分散式ID-入門瞭解

分散式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();