序言:
文章內(nèi)容輸出來(lái)源:拉勾教育Java高薪訓(xùn)練營(yíng)。
本篇文章是學(xué)習(xí)課程中的一部分課后筆記
一、分庫(kù)分表介紹
1.遇到的問(wèn)題
- 用戶(hù)請(qǐng)求量太大
單服務(wù)器TPS、內(nèi)存、IO都是有上限的,需要將請(qǐng)求打散分布到多個(gè)服務(wù)器 - 單庫(kù)數(shù)據(jù)量太大
單個(gè)數(shù)據(jù)庫(kù)處理能力有限;單庫(kù)所在服務(wù)器的磁盤(pán)空間有限;單庫(kù)上的操作IO有瓶頸 - 單表數(shù)據(jù)量太大
查詢(xún)、插入、更新操作都會(huì)變慢,在加字段、加索引、機(jī)器遷移都會(huì)產(chǎn)生高負(fù)載,影響服務(wù)
2.解決方案
- 垂直拆分
-
垂直分庫(kù)
微服務(wù)架構(gòu)時(shí),業(yè)務(wù)切割得足夠獨(dú)立,數(shù)據(jù)也會(huì)按照業(yè)務(wù)切分,保證業(yè)務(wù)數(shù)據(jù)隔離,大大提
升了數(shù)據(jù)庫(kù)的吞吐能力
垂直分庫(kù).png -
垂直分表
表中字段太多且包含大字段的時(shí)候,在查詢(xún)時(shí)對(duì)數(shù)據(jù)庫(kù)的IO、內(nèi)存會(huì)受到影響,同時(shí)更新數(shù)
據(jù)時(shí),產(chǎn)生的binlog文件會(huì)很大,MySQL在主從同步時(shí)也會(huì)有延遲的風(fēng)險(xiǎn)
垂直分表.png
-
- 水平拆分
-
水平分庫(kù)
將單張表的數(shù)據(jù)切分到多個(gè)服務(wù)器上去,每個(gè)服務(wù)器具有相應(yīng)的庫(kù)與表,只是表中數(shù)據(jù)集合
不同。 水平分庫(kù)分表能夠有效的緩解單機(jī)和單庫(kù)的性能瓶頸和壓力,突破IO、連接數(shù)、硬件
資源等的瓶頸
水平分庫(kù).png -
水平分表
針對(duì)數(shù)據(jù)量巨大的單張表(比如訂單表),按照規(guī)則把一張表的數(shù)據(jù)切分到多張表里面去。
但是這些表還是在同一個(gè)庫(kù)中,所以庫(kù)級(jí)別的數(shù)據(jù)庫(kù)操作還是有IO瓶頸。
水平分表.png
-
3.分庫(kù)分表規(guī)則
水平分庫(kù)規(guī)則
不跨庫(kù)、不跨表,保證同一類(lèi)的數(shù)據(jù)都在同一個(gè)服務(wù)器上面。
數(shù)據(jù)在切分之前,需要考慮如何高效的進(jìn)行數(shù)據(jù)獲取,如果每次查詢(xún)都要跨越多個(gè)節(jié)點(diǎn),就需要謹(jǐn)
慎使用。-
水平分表規(guī)則
RANGE
時(shí)間:按照年、月、日去切分。例如order_2020、order_202005、order_20200501
地域:按照省或市去切分。例如order_beijing、order_shanghai、order_chengdu
大?。簭?到1000000一個(gè)表。例如1000001-2000000放一個(gè)表,每100萬(wàn)放一個(gè)表HASH
用戶(hù)ID取模
不同的業(yè)務(wù)使用的切分規(guī)則是不一樣,就上面提到的切分規(guī)則,舉例如下:站內(nèi)信
用戶(hù)維度:用戶(hù)只能看到發(fā)送給自己的消息,其他用戶(hù)是不可見(jiàn)的,這種情況下是按照
用戶(hù)ID hash分庫(kù),在用戶(hù)查看歷史記錄翻頁(yè)查詢(xún)時(shí),所有的查詢(xún)請(qǐng)求都在同一個(gè)庫(kù)內(nèi)-
用戶(hù)表
范圍法:以用戶(hù)ID為劃分依據(jù),將數(shù)據(jù)水平切分到兩個(gè)數(shù)據(jù)庫(kù)實(shí)例,如:1到1000W在
一張表,1000W到2000W在一張表,這種情況會(huì)出現(xiàn)單表的負(fù)載較高
按照用戶(hù)ID HASH盡量保證用戶(hù)數(shù)據(jù)均衡分到數(shù)據(jù)庫(kù)中
用戶(hù)表.png- 流水表
時(shí)間維度:可以根據(jù)每天新增的流水來(lái)判斷,選擇按照年份分庫(kù),還是按照月份分庫(kù),
甚至也可以按照日期分庫(kù)
- 流水表
4.分庫(kù)分表其他情況
- 主鍵選擇
UUID:本地生成,不依賴(lài)數(shù)據(jù)庫(kù),缺點(diǎn)就是作為主鍵性能太差
SNOWFLAKE:百度UidGenerator、美團(tuán)Leaf、基于SNOWFLAKE算法實(shí)現(xiàn) - 數(shù)據(jù)一致性
強(qiáng)一致性:XA協(xié)議
最終一致性:TCC、saga、Seata - 數(shù)據(jù)庫(kù)擴(kuò)容
成倍增加數(shù)據(jù)節(jié)點(diǎn),實(shí)現(xiàn)平滑擴(kuò)容
成倍擴(kuò)容以后,表中的部分?jǐn)?shù)據(jù)請(qǐng)求已被路由到其他節(jié)點(diǎn)上面,可以清理掉 - 業(yè)務(wù)層改造
基于代理層方式:Mycat、Sharding-Proxy、MySQL Proxy
基于應(yīng)用層方式:Sharding-jdbc - 分庫(kù)后面臨的問(wèn)題
- 事務(wù)問(wèn)題:一次投遞需要插入兩條記錄,且分布在不同的服務(wù)器上,數(shù)據(jù)需要保障一致性。
- 跨庫(kù)跨表的join問(wèn)題:
- 全局表(字典表):基礎(chǔ)數(shù)據(jù)/配置數(shù)據(jù),所有庫(kù)都拷貝一份
- 字段冗余:可以使用字段冗余就不用join查詢(xún)了
- 系統(tǒng)層組裝:可以在業(yè)務(wù)層分別查詢(xún)出來(lái),然后組裝起來(lái),邏輯較復(fù)雜
- 額外的數(shù)據(jù)管理負(fù)擔(dān)和數(shù)據(jù)運(yùn)算壓力:數(shù)據(jù)庫(kù)擴(kuò)容、維護(hù)成本變高
二、ShardingSphere簡(jiǎn)介
1.ShardingSphere
Apache ShardingSphere是一款開(kāi)源的分布式數(shù)據(jù)庫(kù)中間件組成的生態(tài)圈。它由Sharding-JDBC、
Sharding-Proxy和Sharding-Sidecar(規(guī)劃中)這3款相互獨(dú)立的產(chǎn)品組成。 他們均提供標(biāo)準(zhǔn)化的數(shù)據(jù)分片、分布式事務(wù)和數(shù)據(jù)庫(kù)治理功能,可適用于如Java同構(gòu)、異構(gòu)語(yǔ)言、容器、云原生等各種多樣化的應(yīng)用場(chǎng)景。

- Sharding-JDBC:被定位為輕量級(jí)Java框架,在Java的JDBC層提供的額外服務(wù),以jar包形式使用。
- Sharding-Proxy:被定位為透明化的數(shù)據(jù)庫(kù)代理端,提供封裝了數(shù)據(jù)庫(kù)二進(jìn)制協(xié)議的服務(wù)端版
本,用于完成對(duì)異構(gòu)語(yǔ)言的支持。 - Sharding-Sidecar:被定位為Kubernetes或Mesos的云原生數(shù)據(jù)庫(kù)代理,以DaemonSet的形式代
理所有對(duì)數(shù)據(jù)庫(kù)的訪(fǎng)問(wèn)。

2.Sharding-JDBC
Sharding-JDBC定位為輕量級(jí)Java框架,在Java的JDBC層提供的額外服務(wù)。 它使用客戶(hù)端直連數(shù)據(jù)庫(kù),以jar包形式提供服務(wù),無(wú)需額外部署和依賴(lài),可理解為增強(qiáng)版的JDBC驅(qū)動(dòng),完全兼容JDBC和各種ORM框架的使用。
- 適用于任何基于Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
- 基于任何第三方的數(shù)據(jù)庫(kù)連接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
-
支持任意實(shí)現(xiàn)JDBC規(guī)范的數(shù)據(jù)庫(kù)。目前支持MySQL,Oracle,SQLServer和PostgreSQL。
jdbc.png
Sharding-JDBC主要功能:
- 數(shù)據(jù)分片
分庫(kù)、分表
讀寫(xiě)分離
分片策略
分布式主鍵 - 分布式事務(wù)
標(biāo)準(zhǔn)化的事務(wù)接口
XA強(qiáng)一致性事務(wù)
柔性事務(wù) - 數(shù)據(jù)庫(kù)治理
配置動(dòng)態(tài)化
編排和治理
數(shù)據(jù)脫敏
可視化鏈路追蹤
Sharding-JDBC內(nèi)部結(jié)構(gòu):

初始化過(guò)程:
- 根據(jù)配置的信息生成Configuration對(duì)象
- 通過(guò)Factory會(huì)將Configuration對(duì)象轉(zhuǎn)化為Rule對(duì)象
- 通過(guò)Factory會(huì)將Rule對(duì)象與DataSource對(duì)象封裝
- Sharding-JDBC使用DataSource進(jìn)行分庫(kù)分表和讀寫(xiě)分離操作
3.Sharding-Proxy
harding-Proxy是ShardingSphere的第二個(gè)產(chǎn)品,定位為透明化的數(shù)據(jù)庫(kù)代理端,提供封裝了數(shù)據(jù)庫(kù)
二進(jìn)制協(xié)議的服務(wù)端版本,用于完成對(duì)異構(gòu)語(yǔ)言的支持。
目前先提供MySQL版本,它可以使用任何兼容MySQL協(xié)議的訪(fǎng)問(wèn)客戶(hù)端(如:MySQL Command Client, MySQL Workbench等操作數(shù)據(jù),對(duì)DBA更加友好。
- 向應(yīng)用程序完全透明,可直接當(dāng)做MySQL使用
- 適用于任何兼容MySQL協(xié)議的客戶(hù)端

Sharding-Proxy使用過(guò)程:
- 下載Sharding-Proxy的最新發(fā)行版;
- 解壓縮后修改conf/server.yaml和以config-前綴開(kāi)頭的文件,進(jìn)行分片規(guī)則、讀寫(xiě)分離規(guī)則配置
編輯%SHARDING_PROXY_HOME%\conf\config-xxx.yaml
編輯%SHARDING_PROXY_HOME%\conf\server.yaml - 引入依賴(lài)jar
如果后端連接MySQL數(shù)據(jù)庫(kù),需要下載MySQL驅(qū)動(dòng), 解壓縮后將mysql-connector-java-
5.1.48.jar拷貝到${sharding-proxy}\lib目錄。
如果后端連接PostgreSQL數(shù)據(jù)庫(kù),不需要引入額外依賴(lài)。 - Linux操作系統(tǒng)請(qǐng)運(yùn)行bin/start.sh,Windows操作系統(tǒng)請(qǐng)運(yùn)行bin/start.bat啟動(dòng)Sharding-Proxy。
使用默認(rèn)配置啟動(dòng): start.sh
配置端口啟動(dòng):start.sh ${port} - 使用客戶(hù)端工具連接。如: mysql -h 127.0.0.1 -P 3307 -u root -p root
若想使用Sharding-Proxy的數(shù)據(jù)庫(kù)治理功能,則需要使用注冊(cè)中心實(shí)現(xiàn)實(shí)例熔斷和從庫(kù)禁用功能。
Sharding-Proxy默認(rèn)提供了Zookeeper的注冊(cè)中心解決方案。只需按照配置規(guī)則進(jìn)行注冊(cè)中心的配置,即可使用。
注意事項(xiàng):
- Sharding-Proxy 默認(rèn)不支持hint,如需支持,請(qǐng)?jiān)赾onf/server.yaml中,將props的屬性proxy.hint.enabled設(shè)置為true。在Sharding-Proxy中,HintShardingAlgorithm的泛型只能是
String類(lèi)型。 - Sharding-Proxy默認(rèn)使用3307端口,可以通過(guò)啟動(dòng)腳本追加參數(shù)作為啟動(dòng)端口號(hào)。如:
bin/start.sh 3308 - Sharding-Proxy使用conf/server.yaml配置注冊(cè)中心、認(rèn)證信息以及公用屬性。
- Sharding-Proxy支持多邏輯數(shù)據(jù)源,每個(gè)以"config-"做前綴命名yaml配置文件,即為一個(gè)邏輯數(shù)
據(jù)源。





