JAVA互聯網架構分庫分表分佈式下如何實現ID全局唯一性

編程語言 Java 信息安全 MySQL Java耕耘者 Java耕耘者 2017-11-03

分庫分表:

跨庫的問題

分佈式事務問題

查詢數據結果集合並

全局唯一性ID保證

要求:

1、全局唯一性:不能出現重複的id號(基本的要求)。

2、信息安全:防止惡意用戶規矩id的規則來獲取數據。混淆效果

3、數據遞增:保證我下一個ID一定大於上一個ID。

當前201709122030 下一個:201709122031 下一個:201709122032

互斥關係:信息安全、數據遞增規律

CREATE TABLE `tl_id` (

`id` varchar(255) NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

業界分案:

UUID:

通用唯一識別碼 16個字節128位的長數字、

組成部分:當前日期和時間序列+全局的唯一性網卡mac地址

執行任務數:10000

------------------------

所有線程共耗時:38.305 s

併發執行完耗時:449.0 ms

單任務平均耗時:3.8305 ms

單線程最小耗時:0.0 ms

單線程最大耗時:193.0 ms

總結:

優點

缺點

代碼實現簡單、不佔用寬帶、數據遷移不受影響

無序、無法保證趨勢遞增(要求3)字符存儲、傳輸、查詢慢、不可讀

Snowflake雪花算法

國外的twitter分佈式下iD生成算法

1bit+41bit+10bit+10+bit=62bit

高位隨機+毫秒數+機器碼(數據中心+機器id)+10的流水號

國內:

保證數據的唯一性就行了 IDC機房。總結:

優點

缺點

代碼實現簡單、不佔用寬帶、數據遷移不受影響、低位趨勢遞增

強以來時鐘(多臺服務器時間一定要一樣)、無序無法保證趨勢遞增(要求3)

水平切分方式

  • 範圍法

  • 哈希法

水平切分後碰到的問題

  • 通過uid屬性查詢能直接定位到庫,通過非uid屬性查詢不能定位到庫。

非uid屬性查詢的典型業務

  • 用戶側,前臺訪問,單條記錄的查詢,訪問量較大,服務需要高可用,並且對一致性的要求較高。

  • 運營側,後臺訪問,根據產品、運營需求,訪問模式各異,基本上是批量分頁的查詢,由於是內部系統,訪問量很低,對可用性的要求不高,對一致性的要求也沒這麼嚴格。

用戶側與運營側架構設計思路

  • 針對用戶側,應該採用“建立非uid屬性到uid的映射關係”的架構方案。

  • 針對運營側,應該採用“前臺與後臺分離”的架構方案。

用戶前臺側,“建立非uid屬性到uid的映射關係”最佳實踐

  • 索引表法:數據庫中記錄login_name->uid的映射關係。

  • 緩存映射法:緩存中記錄login_name->uid的映射關係。

  • login_name生成uid。

  • login_name基因融入uid。

運營後臺側,“前臺與後臺分離”最佳實踐

  • 前臺、後臺系統web/service/db分離解耦,避免後臺低效查詢引發前臺查詢抖動。

  • 可以採用數據冗餘的設計方式。

  • 可以採用“外置索引”(例如ES搜索系統)或者“大數據處理”(例如HIVE)來滿足後臺變態的查詢需求。

“1對多”類業務,在架構上,採用元數據與索引數據分離的架構設計方法

  • 帖子服務,元數據滿足uid和tid的查詢需求。

  • 搜索服務,索引數據滿足複雜搜索尋求。

對於元數據的存儲,在數據量較大的情況下,有三種常見的切分方法:

  • tid切分法,按照tid分庫,同一個用戶發佈的帖子落在不同的庫上,通過 - uid來查詢要遍歷所有庫。

  • uid切分法,按照uid分庫,同一個用戶發佈的帖子落在同一個庫上,需要通過索引表或者緩存來記錄tid與uid的映射關係,通過tid來查詢時,先查到uid,再通過uid定位庫。

  • 基因法,按照uid分庫,在生成tid里加入uid上的分庫基因,保證通過uid和tid都能直接定位到庫。

在數據庫架構設計過程中,除了水平切分,至少還會遇到這樣一些問題:

  • 可用性:不管是主庫實例,還是從庫實例,如果數據庫實例掛了,如何不影響數據的讀和寫。

  • 讀性能:互聯網業務大多是讀多寫少的業務,如果提升數據庫的讀性能是架構設計中必須考慮的問題。

  • 一致性:數據一旦冗餘,就可能出現一致性問題,如何解決主庫與從庫之間的不一致,如何解決數據庫與緩存之間的不一致,也是需要重點設計的。

  • 擴展性:如何在不停服務的情況下擴充數據表的屬性,實施數據遷移,實施存儲引擎的切換,架構設計上都是十分有講究的。

  • 分佈式SQL語句:單庫情況下,所有SQL語句的執行都沒問題問題,一旦實施了水平切分,如何實現SQL的集函數,分頁,非patition key上的查詢都成了大問題。

Mysql:

JAVA互聯網架構分庫分表分佈式下如何實現ID全局唯一性

奇數跟我們偶數 遞增步長2

適合小型互聯網公司、比如可以知道我們一定生成的ID數量 五萬的訂單量

一年1千8百萬

Mysql一張表500萬

如果公司每天訂單量5萬的數據 我們用mysql設置步長位100的話可以用27年

只能為100庫 公司來到風投了 每天的訂單量50萬100萬的時候

總結:

優點

缺點

代碼實現方便、性能不錯、數字排序、可讀性很強

受限數據庫、擴展麻煩、插入數據庫才能拿到ID、單點故障的問題

主從同步的時候:電商下單->支付 insert master db select 數據 因為數據同步延遲導致查不到這個數據。加cache(不是最好的解決方式)數據要求比較嚴謹的話查master主庫。

CREATE TABLE `tl_num` (

`id` bigint(11) NOT NULL AUTO_INCREMENT,

KEY (`id`) USING BTREE

) ENGINE=InnoDB auto_increment=1 DEFAULT CHARSET=utf8;

Redis:

JAVA互聯網架構分庫分表分佈式下如何實現ID全局唯一性

執行任務數:10000

------------------------

所有線程共耗時:136.587 s

併發執行完耗時:1.515 s

單任務平均耗時:13.6587 ms

單線程最小耗時:1.0 ms

單線程最大耗時:254.0 ms

總結:

優點

缺點

不依賴數據、靈活方便、性能優於數據庫的、沒有單點故障(高可用)

需要佔用網絡資源、性能要比本地生成慢、需要增加插件

相關推薦

推薦中...