微服務存儲實現3—分庫分表
分庫分表
1 查詢分離利用Elasticserach作為查詢庫,可以解決業務數據沒終止狀態,不方便進行冷熱分離時,數據量的緩存與查詢效率低的問題。但是ES存在一定的延時,深度分頁不能自由跳頁,會有丟失數據的可能性。此外,當主庫的數據量非常大時,寫操作會變慢。同時由于需要將主庫更新后的數據同步到查詢庫,在采用異步完成數據的同步更新時,存在一定的延時。
針對于主庫寫操作越來越慢,我們這里介紹另外一種方案,分庫分表。關于分庫分表將從拆分存儲時的技術選型、分表分庫的實現思路、分表分庫存在哪些不足為切入點進行介紹。
拆分存儲的技術選型:
拆分存儲常用的技術解決方案目前主要分為4種:MySQL的分區技術、NoSQL、NewSQL、基于MySQL的分表分庫。
MySQL的分區技術主要體現在文件存儲層File System,它可以將一張表中的不同行放到不同的存儲文件,但是有以下幾個缺陷:
Mysql的實例只有一個,分區技術僅僅分攤了存儲,但是無法分攤請求的負載。分區對于用戶來說是透明的,用戶在實際操作時可能會跨分區,進而導致系統性能受到影響。
NoSQL數據庫比較典型的就是MongoDB. MongoDB的分片功能從并發性和數據量可以滿足一般大數據量的需求。但是需要注意下面三點:
1 約束考量:MongoDB 不是關系型數據庫而是文檔型數據庫,它的每一行數據記錄是一個結構靈活可變的JSON. 對于存儲非常重要的字段就不能使用這種數據庫,比如要存儲的一行記錄涉及到金額,那么這行數據缺少了該字段在mongoDB 中也是可以存儲的。當然MongoDB 3.2版之后可以支持schema Validation(模式驗證),可以制定一些約束規則。
2 業務功能考量: 涉及到支持事務與并發控制這些不是MongoDb的強項。而這些在MySQL上進行了多年的實踐。且大部分的Nosql存在類似復雜功能支持的問題。
3 穩定性考量:MySQl的運維已被人們熟悉,穩定性也沒有問題。MangoDB的穩定性無法保證。
NewSQL是一款比較新型的數據庫,比如TiDB,但是穩定性和擴展性不如MySQL優秀。
從上面的介紹來看,選則基于MySQL的分庫分表比較穩妥。
MYSQL的分庫是將一個大的數據庫拆分成多個小數據庫。分表是將一張大的表拆分成幾張表。分庫分表對于第三方的依賴較少,邏輯靈活可控。它本身不需要非常復雜的底層處理,也不需要重新做數據庫,只是根據不同邏輯使用不同SQL語句和數據源而已。
關于分庫分表有三個通用技術需要實現:
1 SQL組合:因為關聯的表名是動態的,所以需要根據邏輯組裝動態的SQL。比如要根據訂單ID獲取相關的詳細數據,select 語句應該針對From哪一張表。
2 數據庫路由:因為數據庫名也是動態的,所以需要通過不同的邏輯使用不同的數據庫。比如根據訂單ID獲取數據時,需要直到連接哪個數據庫.
3 執行結果合并,有些需求需要通過多個分庫執行后再合并數據集。
關于以上問題,可以通過一些中間件進行解決,這些中間件大體上分為了兩種模式,Proxy模式,Client模式
Proxy模式是將SQL組合,數據庫路由,執行結果合并等功能全部放在了一個代理服務中。將分庫分表的邏輯放在了其它服務中,對業務代碼來說無侵入。比較常用的中間件有MyCat、KingShard、Atlas、cobar.
Client模式是客戶端一邊實現分庫分表的邏輯,另一邊通過引用一個jar, 在jar中處理SQL組合、數據庫路由,執行結果合并。zebra、Sharding-JDBC、TSharding.
| 模式 | 中間件 | 廠家 | 語言 | 優點 | 缺點 |
| Proxy | MyCat | Java |
多語言 資源消耗解耦,不需要消耗客戶端的資源 升級方便 |
多一層服務調用,線上調試困難 增加了運維成本 |
|
| KingShard | Go | ||||
| Atlas | 360 | C | |||
| cobar | 阿里 | JAva | |||
| Client | zebra | 美團 | Java |
少一層服務調用,代碼靈活可控 減少了運維成本 |
單語言,升級不方便 |
| Sharding-JDBC | ApacheShardingSphere | Java | |||
| TSharding | 蘑菇街 | Java |
分表分庫實現思路一般需要考慮如下五點:
使用什么字段分片?
選擇分片字段時,需要考慮所選字段的值不會變,讓數據盡可能均勻分布在不同的表或者庫、跨庫查詢盡可能少
分片的策略是什么?
目前通用的分片策略有三種:根據范圍分片、根據Hash值分片(進行取模值,模一般為2的n次方)、根據Hash值和范圍分片。
業務代碼如何修改?
針對于微服務的分表分庫,其影響面基本只為該表所在的服務,而單體架構涉及很多關聯查詢,如果需要進行分庫分表則修改的代碼會非常多。
互聯網架構中基本不使用外鍵(外鍵用于建立表與表之間的關系,以保證數據的完整性和一致性)
分庫分表之后,盡量避免跨庫和跨表查詢。
歷史數據如何遷移?
基本思路:舊架構保持執行,存量數據直接遷移,binlog監聽增量數據, 通過canal通知遷移程序遷移數據,等到新的數據庫擁有全量數據并且校驗通過后切換流量到新架構。
未來的擴容方案?
1)分片策略是否可以讓新表數據的遷移源只有一個舊表,而不是多個舊表?這就是前面建議使用2n分表的原因——以后每次擴容都能擴為2倍,都是把原來一張表的數據拆分到兩張表中。
2)數據遷移。需要把舊分片的數據遷移到新的分片上。
分庫分表的缺點:
1 復雜查詢慢:很多查詢需要跨訂單數據庫進行,然后再組合結果集,這樣的查詢比較慢。業界的普遍做法是前面提到的查詢分離。
2 短時流量大爆發:分表分庫可以解決數據量大的問題,但是如果瞬時流量非常大,數據庫可能撐不住。

浙公網安備 33010602011771號