數據庫分表分庫(Sharding-Sphere)

本文原創,使用本文請注明出處。

本文總結較為淺顯,有興趣的同學可直接參考官方文檔

背景

????????為解決關系型數據庫面對海量數據由于數據量過大而導致的性能問題時,將數據進行分片是行之有效的解決方案,而將集中于單一節點的數據拆分并分別存儲到多個數據庫或表,稱為分庫分表。 分庫可以有效分散高并發量,分表雖然無法緩解并發量,但僅跨表仍然可以使用數據庫原生的ACID事務。而一旦跨庫,涉及到事務的問題就會變得無比復雜。

????????分庫分表一般有兩種拆分方式。按照業務拆分的方式稱為垂直拆分。

????????例如,根據業務的不同將訂單庫拆成兩個相同的數據庫,稱之為垂直拆分。垂直拆分可以緩解數據量和訪問量帶來的問題,但無法根治,如果垂直拆分之后的訂單數量依然超過單節點所能承載的閾值,則需要水平拆分來進一步處理。 將一個表中的數據按照一定的業務規則拆分至不同表和數據庫中,稱之為水平拆分。例如,原來的訂單數據在order_ds.t_order表中,如果按照訂單的user_id將訂單拆分為2個庫,再按照訂單的order_id在每個庫中分成4個表,那么拆分的結果則是order_ds_0.t_order_0,order_ds_0.t_order_1,order_ds_0.t_order_2,order_ds_0.t_order_3,order_ds_1.t_order_0,order_ds_1.t_order_1,order_ds_1.t_order_2,order_ds_1.t_order_3。 這只是簡單的水平拆分案例,在實際使用中,將庫和表拆分的更加分散也是十分常見的。

????????雖然數據分片解決了性能問題,但也額外的引入了其他問題。面對如此散亂的分庫分表之后的數據,應用開發和運維人員對數據庫的操作變得異常繁重就是其中的重要挑戰之一。他們需要知道什么樣的數據需要從哪個具體的數據庫的分表中去獲取。透明化分庫分表所帶來的影響,讓使用方盡量像使用一個數據庫一樣使用水平拆分之后的數據庫,是分庫分表中間件的主要功能。

分片的概念

分片鍵

用于分片的數據庫字段,是將數據庫(表)水平拆分的關鍵字段。例:訂單表訂單ID分片尾數取模分片,則訂單ID為分片字段。SQL中如果無分片字段,將執行全路由,性能較差,支持多分片字段。

分片算法

通過分片算法將數據分片,支持通過等號、BETWEEN和IN分片。分片算法需要應用方開發者自行實現,可實現的靈活度非常高。

目前提供4種分片算法。由于分片算法和業務實現緊密相關,因此并未提供內置分片算法,而是通過分片策略將各種場景提煉出來,提供更高層級的抽象,并提供接口讓應用開發者自行實現分片算法。

精確分片算法

對應PreciseShardingAlgorithm,用于處理使用單一鍵作為分片鍵的=與IN進行分片的場景。需要配合StandardShardingStrategy使用。

范圍分片算法

對應RangeShardingAlgorithm,用于處理使用單一鍵作為分片鍵的BETWEEN AND進行分片的場景。需要配合StandardShardingStrategy使用。

復合分片算法

對應ComplexKeysShardingAlgorithm,用于處理使用多鍵作為分片鍵進行分片的場景,多分片鍵邏輯較復雜,需要應用開發者自行處理其中的復雜度。需要配合ComplexShardingStrategy使用。

Hint分片算法

對應HintShardingAlgorithm,用于處理使用Hint行分片的場景。需要配合HintShardingStrategy使用。

分片策略

包含分片鍵和分片算法,由于分片算法的獨立性,將其獨立抽離。真正可用于分片操作的是分片鍵 + 分片算法,也就是分片策略。目前提供5種分片策略。

標準分片策略

對應StandardShardingStrategy。提供對SQL語句中的=, IN和BETWEEN AND的分片操作支持。StandardShardingStrategy只支持單分片鍵,提供PreciseShardingAlgorithm和RangeShardingAlgorithm兩個分片算法。PreciseShardingAlgorithm是必選的,用于處理=和IN的分片。RangeShardingAlgorithm是可選的,用于處理BETWEEN AND分片,如果不配置RangeShardingAlgorithm,SQL中的BETWEEN AND將按照全庫路由處理。

復合分片策略

對應ComplexShardingStrategy。復合分片策略。提供對SQL語句中的=, IN和BETWEEN AND的分片操作支持。ComplexShardingStrategy支持多分片鍵,由于多分片鍵之間的關系復雜,因此并未進行過多的封裝,而是直接將分片鍵值組合以及分片操作符交于算法接口,完全由應用開發者實現,提供最大的靈活度。

行表達式分片策略

對應InlineShardingStrategy。使用Groovy的表達式,提供對SQL語句中的=和IN的分片操作支持,只支持單分片鍵。對于簡單的分片算法,可以通過簡單的配置使用,從而避免繁瑣的Java代碼開發,如:?t_user_${u_id % 8}?表示t_user表按照u_id按8取模分成8個表,表名稱為t_user_0到t_user_7。

Hint分片策略

對應HintShardingStrategy。通過Hint而非SQL解析的方式分片的策略。

不分片策略

對應NoneShardingStrategy。不分片的策略。

Hint

對于分片字段非SQL決定,而由其他外置條件決定的場景,可使用SQL Hint靈活的注入分片字段。例:內部系統,按照員工登錄ID分庫,而數據庫中并無此字段。SQL Hint支持通過Java API和SQL注釋(待實現)兩種方式使用。

實踐

首先建立兩個相同單命名不同的庫


然后在項目中(本文使用spring boot框架)

引入maven依賴

基于Java編碼的分庫規則配置(DataConfig.java)

查詢語句(更新語句同理)

當執行查詢或更新語句時,系統會根據DataConfig中的配置路由到對應的庫下面的表中,“platformId”、“orderId”是路由的關鍵,“platformId”、“orderId”作為分片鍵,必須是唯一的。

分布式主鍵的概念

實現動機

? ? ? ?傳統數據庫軟件開發中,主鍵自動生成技術是基本需求。而各個數據庫對于該需求也提供了相應的支持,比如MySQL的自增鍵,Oracle的自增序列等。 數據分片后,不同數據節點生成全局唯一主鍵是非常棘手的問題。同一個邏輯表內的不同實際表之間的自增鍵由于無法互相感知而產生重復主鍵。 雖然可通過約束自增主鍵初始值和步長的方式避免碰撞,但需引入額外的運維規則,使解決方案缺乏完整性和可擴展性。

????????目前有許多第三方解決方案可以完美解決這個問題,如UUID等依靠特定算法自生成不重復鍵,或者通過引入主鍵生成服務等。 但也正因為這種多樣性導致了Sharding-Sphere如果強依賴于任何一種方案就會限制其自身的發展。

基于以上的原因,Sharding-Sphere最終采用以接口來實現對于生成主鍵的訪問,而將底層具體的主鍵生成實現分離出來。

默認分布式主鍵生成器

采用snowflake算法實現,生成的數據為64bit的長整型數據。

其二進制表示形式包含四部分,從高位到低位分表為:1bit符號位(為0),41bit時間位,10bit工作進程位,12bit序列位。

該算法保證不同進程的主鍵肯定是不同的,同一個進程首先是通過時間位保證不重復,如果時間相同則是通過序列位保證。 同時由于時間位是單調遞增的,且各個服務器如果大體做了時間同步,那么生成的主鍵在分布式環境可以認為是總體有序的,這就保證了對索引字段的插入的高效性。例如MySQL的Innodb存儲引擎的主鍵。

在數據庫中應該用大于等于64bit的數字類型的字段來保存該值,比如在MySQL中應該使用BIGINT。

類名稱:io.shardingjdbc.core.keygen.DefaultKeyGenerator

時間位(41bit)

從2016年11月1日零點到現在的毫秒數,時間可以使用到2156年,滿足大部分系統的要求。

工作進程位(10bit)

該標志在Java進程內是唯一的,如果是分布式應用部署應保證每個進程的工作進程Id是不同的。該值默認為0,可通過調用靜態方法DefaultKeyGenerator.setWorkerId("xxxx")設置。

序列位(12bit)

該序列是用來在同一個毫秒內生成不同的Id。如果在這個毫秒內生成的數量超過4096(2的12次方),那么生成器會等待到下個毫秒繼續生成。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,208評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,746評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,477評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,960評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,200評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,726評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,617評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,807評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,049評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,432評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,769評論 2 372

推薦閱讀更多精彩內容