分佈式 原理的核心應該算是一致系統設計,而不是一種技術
分佈式唯一單號的設計都必須有一定的格式,純隨機無法實現唯一單號, 格式可以解決分佈式問題
GUID/UUID 工具生成, 用到了
當前日期和時間,UUID的第一個部分與時間有關,如果你在生成一個UUID之後,過幾秒後又生成了一個UUID,則第一個部分不同,其餘相同。
時鐘序列。
全局唯一的IEEE機器識別號,如果有網卡,從網卡MAC地址獲得,沒有網卡以其他方式獲得。—(mac地址這部分可以解決分佈式問題,不通機器因爲這部分不同,所以不同機器生成單號肯定不同 )
UUID的唯一缺陷在於生成的結果穿會比較長。關於UUID這個標準使用最普遍的是微軟的GUID(Globals Ujique Identifiers
SnowFlake https://blog.csdn.net/li396864285/article/details/54668031
在分佈式系統中不同機器產生的id必須不同.Snowflake算法核心把時間戳,工作機器id,序列號(毫秒級時間41位+機器ID 10位+毫秒內序列12位)組合在一起。
會員團隊 > 單號生成組件 > image2021-1-28_11-56-57.png
機器id 解決了分佈式問題
mysql , redis 自增
最終由一臺機器,一個線程實現的,固定的就是一個特殊隱藏格式"空"
總結來說”分佈式“ 嚴格 唯一單號生的條件有3點
1 有固定格式 機器標識 (記作“機器標識”) + 通過線程安全方式生成的唯一標識(這裏記作“隨機數”) + 不同標識段有有分割符(包含隱形分割符如:機器標識長度固定,那麼機器分割符之後爲空的方式也算固定分割符, 機器1&abc, 和機器1abc, 這2種效果一樣)
2有唯一機器標識,(myqsql, redis 這種也可以說是有標識,空標識,因爲最終就一臺機器)
3 單機生成標識中 隨機數生成必須線程安全
方式1 (嚴格唯一) 單號最終組生成的機器:業務機器
格式: yyyyMMssSSS+ redis 自增(key 爲MinuteOfHour, 過期時間 1分鐘)
機器標識:隱形空(統一redis 機器)
隨機數標識:redis 自增num(key 爲MinuteOfHour, 過期時間 1分鐘)
弊端: redis 可用性依賴性高:業務服務需要接入redis
方式2:(嚴格唯一) 單號最終組生成的機器:業務機器
格式:jvm 機器編號 +( yyyyMMssSSS+ 線程安全生成一秒鐘的唯編號)
機器標識:jvm 機器編號
隨機數標識:( yyyyMMssSSS+ 線程安全生成一秒鐘的唯編號)
弊端: 每臺機器都要手動配置機器編號
方式3:(嚴格唯一)單號最終組生成的機器: 統一單號生成服務
格式:: yyyyMMssSSS+ redis 自增(key 爲調用方編號+MinuteOfHour, 過期時間 1分鐘)
機器標識: 機器編號隱形空(統一redis 機器)
隨機數標識: redis 自增(key 爲調用方編號+MinuteOfHour, 過期時間 1分鐘)
弊端: 單號服務要保證搞可用
方式4:(嚴格唯一)單號最終組生成的機器: 統一單號生成服務, 或者業務本身都可以
格式 : 任意編號標識 + 通過記錄唯一id置換編號 (也可以抽象的說所有的數據都不重複的格式)
機器標識:機器編號隱形空 (可以認爲是存儲單號庫的倉庫 mysql等)
隨機數標識: 存儲單號庫 提前已經去重
解釋一下:單號倉庫要提前生成一批去重之後的唯一編號,業務喜通通過唯一id (分表的可以再做擴展), 換取倉庫種的唯一編號
弊端:要維護一套單號倉庫
方式5:(不嚴格唯一) 單號最終組生成的機器:業務機器----
格式:: yyyyMMssSSS+ uid + 一位英文字符+ 2位 隨機字符(從26個英文字母+10個阿拉伯數字中隨機)
機器標識:無
隨機數標識: yyyyMMssSSS+ uid + 一位英文字符+ 2位 隨機字符
弊端: 同一個用戶的單號有重複的可能)
最終選擇方案2:
理由:
1 目前的需求需要嚴格的單號唯一 (排除方案5)
2 單號生成依賴外部服務,服務的穩定性無法保證(排除3, 4)
3 建立單號庫 接入代價過大 (排除方案 4)
4 目前公司的redis 服務本身穩定性沒有保障,每次請求redis 獲取單號也有網絡開銷 (排除方案2)
方案2 具體到業務細節
唯一單號3個條件如下: 單號最終組生成的機器:業務機器
格式:yyyyMMddHHmmss(14) + 機器編號(8位)+ 隨機編碼(4位)
機器標識:系統啓動的時候 通過http 訪問統一的機器編碼服務
隨機數標識:機器本地使用線程安全方式獲取4位唯一編碼 (1秒內)
功能更實現做的工作
提供一個機器編碼管理工具,爲機器生成唯一機器編碼服務,
提供一個springboot-start,接入方引入pom文件就完成了接入