1. 程式人生 > >淺談分布式數據庫

淺談分布式數據庫

base uic 形式 業界 trac 最佳實踐 iam 沒有 繼續

文章集中整理總結mysql分庫分表開源產品,分布式數據庫的設計,以及實際應用案例等相關內容,部分附上本文作者實際應用過程中的理解。

本文感謝sjdbcmycat姜承堯,林濤等文章提供的精彩介紹。

1、先拋出兩個問題

問題一、當mysql單表數據量爆炸時,你怎麽辦?
問題二、當你的數據庫無法承受高強度io時你怎麽辦?


2、 基本概念

2.1 談數據庫分片需要首先確定以下概念

? 1) 單庫,就是一個庫
技術分享圖片

? 2) 分片(sharding),分片解決擴展性問題,屬於水平拆分,引入分片,就引入了數據路由分區鍵的概念。分表解決的是數據量過大的問題,分庫解決的是數據庫性能瓶頸的問題。

技術分享圖片

? 3) 分組(group),分組解決可用性問題,分組通常通過主從復制(replication)的方式實現。(各種可用級別方案單獨介紹)
技術分享圖片

? 4) 互聯網公司數據庫實際軟件架構是(大數據量下):又分片,又分組(如下圖)

技術分享圖片


3、 分片

3.1 水平拆分,垂直拆分都是什麽?

技術分享圖片

分區表?1)若不走分區鍵很容易出現全表鎖,並發上來後簡直是災難。2)自己分庫分表,自己掌控業務場景、訪問模式,可控。mysql分區表官方介紹是針對myisam做的優化,你知道他怎麽玩的?分半天還是一個ibdata是不是很尷尬

3.2 為什麽分表?

? 關系型數據庫在大於一定數據量的情況下檢索性能會急劇下降。在面對互聯網海量數據情況時,所有數據都存於一張表,顯然會輕易超過數據庫表可承受的數據量閥值

。這個單表可承受的數據量閥值,需根據數據庫和並發量的差異,通過實際測試獲得。

水平拆分如果能預估規模,越早做成本越低。

2.3 為什麽分庫?

? 單純的分表雖然可以解決數據量過大導致檢索變慢的問題,但無法解決過多並發請求訪問同一個庫,導致數據庫響應變慢的問題。所以通常水平拆分都至少要采用分庫的方式,用於一並解決大數據量和高並發的問題。這也是部分開源的分片數據庫中間件只支持分庫的原因。

3.4 分布式事務?

? 但分表也有不可替代的適用場景。最常見的分表需求是事務問題。同在一個庫則不需考慮分布式事務,善於使用同庫不同表可有效避免分布式事務帶來的麻煩。目前強一致性的分布式事務由於性能問題,導致使用起來並不一定比不分庫分表快。目前采用最終一致性的柔性事務居多。分表的另一個存在的理由是,過多的數據庫實例不利於運維管理。

mysql本身?
消息補償?
2PC?

3.5 小結

? 綜上所述,最佳實踐是合理地配合使用分庫+分表。

3.6 如何自己實現分庫分表?

? 1) dao層,首先通過分區鍵算出庫名表名(如shardKey%shardNum 算出來表index如y,然後y/(shardNum/sourceNum)=x,y是表下標,x是庫下標)。
? 2) 把source從spring容器中拿出來,把表名當參數傳進去,拼成分片後的sql。
? 3) 思路大概是(select … from order where … -> 先拿到db_x的source 然後 select … from order_y where …)

你想這麽幹?你已經成功了。當然淘寶和當當的架構師也是這麽幹的。

3.7 SO,不需要我們親自動手,其實你需要做的只是按照實際需求挑選而已。

技術分享圖片

3.8 重點介紹兩個產品,先不說具體配置,只說思想

? 1) sharding-jdbc(所處位置,通用數據訪問層,部署在客戶端的jar包,用於將用戶的SQL路由到指定的數據庫中)

盜一波圖

技術分享圖片
技術分享圖片
技術分享圖片
技術分享圖片
技術分享圖片

? 2) jproxy

jproxy是什麽?

? jproxy提供MariaDB, MySQL等數據庫的統一接入訪問,擁有流量過載保護,數據自動拆分,可配置路由規則,數據無縫遷移等功能。
? 應用場景:數據需要分庫分表,自動擴容的應用。

技術分享圖片

為什麽分片都是2的n次方?a % (2^n) 等價於 a & (2^n - 1) 其中一個原因就是位運算

擴容? 虛擬桶。 極限就是一片一庫。

演變過程 cobar->mycat->jproxy

mycat是什麽?

? 簡單的說,就是:一個徹底開源的,面向企業應用開發的“大數據庫集群”。支持事務、ACID、可以替代Mysql的加強版數據庫,一個的數據庫中間件產品。
- 其優勢具有:
1) 基於阿裏開源的Cobar產品而研發,Cobar的穩定性、可靠性、優秀的架構和性能
2) 擁有眾多成熟的使用案例
3) 強大的團隊(其參與者都是5年以上資深軟件工程師、架構師、DBA等)
4) 開源,創新,持續更新

盜一波圖

技術分享圖片


4、 分組

4.1 為什麽分組?

? 分組解決可用性問題

mysql的ha 網洛上的都是vip漂移實現的

盜一波圖

技術分享圖片
技術分享圖片

方案一:MYSQL主從復制(單活)
技術分享圖片
技術分享圖片

方案二:雙主(單活),failover比單主簡單
技術分享圖片
技術分享圖片

方案三:雙主配SAN存儲(單活)
技術分享圖片
技術分享圖片

方案四:DRBD 雙主配DRBD (單活)
技術分享圖片
技術分享圖片

方案五:NDB CLUSTER
技術分享圖片

共享存儲? 不需要復制了 更高的一致性

真正的高並發場景,什麽架構都抗不住,老老實實用緩存。

需要大量讀的場景盡量做到最終一致性。

4.2 同步,異步,半同步

1) 異步復制 (mysql默認)

Master將事件寫入binlog,但並不知道Slave是否或何時已經接收且已處理。當Slave準備好才會向Master請求binlog。缺點:不能保證一些事件都能夠被所有的Slave所接收。

2) 同步復制

Master提交事務,直到事務在所有的Slave都已提交,此時才會返回客戶端,事務執行完畢。缺點:完成一個事務可能會有很大的延遲。

3) 半同步復制

半同步復制工作的機制處於同步和異步之間,Master的事務提交阻塞,只要一個Slave已收到該事務的事件且已記錄。它不會等待所有的Slave都告知已收到,且它只是接收,並不用等其完全執行且提交。

半同步復制的步驟:
i.當Slave主機連接到Master時,能夠查看其是否處於半同步復制的機制。

ii.當Master上開啟半同步復制的功能時,至少應該有一個Slave開啟其功能。此時,一個線程在Master上提交事務將受到阻塞,直到得知一個已開啟半同步復制功能的Slave已收到此事務的所有事件,或等待超時。

iii.當一個事務的事件都已寫入其relay-log中且已刷新到磁盤上,Slave才會告知已收到。

iv.如果等待超時,也就是Master沒被告知已收到,此時Master會自動轉換為異步復制的機制。當至少一個半同步的Slave趕上了,Master與其Slave自動轉換為半同步復制的機制。

v.半同步復制的功能要在Master,Slave都開啟,半同步復制才會起作用;否則,只開啟一邊,它依然為異步復制。

4.3 ha方案

4.3.1 MHA

4.3.2 MMM


5、 應用案例

5.1 記錄一次mongo遷移mysql的過程(分庫分表使用jproxy)

mongo怎麽了?跟分片無關的部分簡單說。

? mongo很好,只是業界並沒有成熟的MongoDB運維經驗,jd too。
像高並發的系統 訂單和庫存 商品 還是拿nosql把,高並發的寫,也不會打掛他,比如hbase,頂多GC頻繁點,但是也是可用的。
一致性完全可以CAS搞定,而不是mysql的排他鎖。

  • 遷移數據庫的一個方案
    1) 中心化(統一入口)
    2) 雙寫(先同步寫mysql如果發生異常改異步,盡量避免服務不可用)
    3) 倒庫(jproxy支持通過遊標形式全量遍歷庫-逐個表操作,可以利用其異步同步數據)
    4) 數據校驗
    5) 切庫提供服務

技術分享圖片

去mongo+優化方案(此處引入了分片的概念)

技術分享圖片
技術分享圖片

壓測與性能

技術分享圖片
技術分享圖片
技術分享圖片
技術分享圖片
技術分享圖片

去mongo任務線

類型任務備註影線系統風險
design 海關遷移方案設計評審
design 分庫分表技術選型 jproxy
apply 申請遷移相關應用(輔助系統) 跑批任務
apply 申請mysql集群 dbs系統
apply 申請jproxy集群 直接找接口人
apply 申請es集群 esm傑斯
coding trace表服務中心化 soa center
coding 涉及trace業務邏輯梳理,全部切換中心接口 接口完全適配 platform
verify 回歸測試,並線上走單驗證一段時間 先預發後正式
coding 實現mysql版本共2個表sql映射文件 基於自主研發的generator center
verify mysql版本sql映射文件單元測試 基於自主研發的generator center
coding trace表實現基於jproxy的分庫分表 128個庫(主) 1主3從 center
coding es分別按照商家id分片,保稅區id分片,異步寫,讀開放jsf 2套集群4套索引 es
coding 中心接口加入代理層,可利用開關切換讀mongo/mysql/es center
coding 異步補償mongo,mysql,es功能開發 基於jmq platform
coding 代理層實現mongo和mysql版本互為主被雙寫(mongo主),異步寫es 雙11後mysql主 center
verify 線上開雙寫(包括es) 兩套es集群
coding 倒庫功能開發,數據校驗功能開發 reactor config
verify 倒庫,並進行數據校驗 校驗規則(特殊字段不校驗)
verify 對中心接口進行壓測 線上,壓測環境隔離(jsf別名)
coding 優化配置(mysql調整最大連接數,es使用filterCache)
verify 對中心接口進行壓測
verify 升級後架構正式上線
verify 監控切換mysql之後的接口性能
verify 監控切換mysql之後對相關依賴系統的影響
todo 停mongo寫
todo 繼續遷移海關mongo中其他表(以上均為trace表)
todo 徹底下線mongo數據庫服務器,只保留mysql服務器

5.2 記錄一次異構具有復雜分片規則數據庫的過程

5.2.1 難點

? 交易庫存復雜的分片規則,數據量大,更新頻繁,一致性保證。

回到本源,緩存+隊列

技術分享圖片

5.2.2 不跑題,我們就說分片部分,如何接手一個復雜分片規則的數據庫?

參考案例如何異構一個數十億級別的數據庫

有多復雜?? 6000+表,28個庫,4套分片規則。(解決方案 sharding-jdbc)

淺談分布式數據庫