ShardingSphere之Sharding-JDBC分庫(kù)分表然眼、讀寫分離
一、數(shù)據(jù)切分概念
? ? ? 關(guān)系型數(shù)據(jù)庫(kù)在單機(jī)存儲(chǔ)容量葵腹、連接數(shù)高每、處理能力上都是有限的,容易成為整個(gè)系統(tǒng)的瓶頸践宴。當(dāng)單表的數(shù)據(jù)量達(dá)到一定的數(shù)量和容量時(shí)鲸匿,由于查詢維度較多,即使添加從庫(kù)阻肩、優(yōu)化索引带欢,做很多操作時(shí)性能也仍然會(huì)下降嚴(yán)重。
? ? ? 數(shù)據(jù)庫(kù)分布式核心概念其實(shí)就是數(shù)據(jù)切分烤惊,以及切分后的數(shù)據(jù)定位乔煞、聚合歸并。數(shù)據(jù)切分也就是將數(shù)據(jù)分散到多個(gè)表或多個(gè)庫(kù)柒室,從而使單庫(kù)單表的數(shù)據(jù)量變小渡贾,通過(guò)對(duì)表或庫(kù)的擴(kuò)容(增加分表、增加分庫(kù)雄右、增加主機(jī))空骚,來(lái)緩解單一數(shù)據(jù)庫(kù)的性能壓力纺讲,從而能提升對(duì)數(shù)據(jù)庫(kù)操作的性能。
? ? ? 數(shù)據(jù)切分囤屹,可以分為垂直切分和水平切分熬甚。
1、垂直切分
? ? ? 垂直切分可分為 垂直分庫(kù)和垂直分表肋坚。?
? ? ? 垂直分庫(kù)根據(jù)業(yè)務(wù)耦合度则涯,將關(guān)聯(lián)度低的不同表存儲(chǔ)到不同的數(shù)據(jù)庫(kù)中,每個(gè)庫(kù)中的數(shù)據(jù)表是不同的冲簿,專庫(kù)專用粟判。與大系統(tǒng)拆分為小系統(tǒng)類似,按業(yè)務(wù)進(jìn)行獨(dú)立劃分峦剔,像目前的微服務(wù)架構(gòu)下档礁,每個(gè)微服務(wù)都是負(fù)責(zé)不同的業(yè)務(wù),可以使用單獨(dú)的一個(gè)庫(kù)吝沫, 公車項(xiàng)目中的系統(tǒng)管理支撐類業(yè)務(wù)庫(kù)呻澜、工作流支撐類業(yè)務(wù)庫(kù)、公車調(diào)度類業(yè)務(wù)庫(kù)惨险、GIS相關(guān)庫(kù)羹幸,這就是屬于垂直分庫(kù)。
? ? ? 垂直分表是基于數(shù)據(jù)庫(kù)表的”列”進(jìn)行切分辫愉,某個(gè)表字段較多栅受,可以新建一張擴(kuò)展表,將不經(jīng)常用或字段長(zhǎng)度較大的字段拆分出去到擴(kuò)展表中恭朗。在字段很多的情況下(例如一個(gè)大表有幾十上百個(gè)字段)屏镊,絕大部分字段如果都是存儲(chǔ)后不會(huì)有改動(dòng),只有少數(shù)幾個(gè)字段屬于熱點(diǎn)字段頻繁的讀寫痰腮,此時(shí)就適合將熱點(diǎn)字段拆分到擴(kuò)展表中 與大表關(guān)聯(lián)而芥, 熱點(diǎn)字段所在的表字段少,讀寫性能高膀值。另外通過(guò)”大表拆小表”棍丐,也能避免跨頁(yè)問(wèn)題,MySQL底層是通過(guò)數(shù)據(jù)頁(yè)或者叫數(shù)據(jù)塊存儲(chǔ)的沧踏,innodb存儲(chǔ)引擎的頁(yè)塊大小默認(rèn)為16K歌逢,但如果表中一行的數(shù)據(jù)長(zhǎng)度超過(guò)了16k,就會(huì)出現(xiàn)行溢出悦冀,溢出的行是存放在另外的地方趋翻,存放該溢出數(shù)據(jù)的頁(yè)叫uncompresse blob page。所以一條記錄占用空間過(guò)大會(huì)導(dǎo)致跨頁(yè),讀取時(shí)就會(huì)造成額外的性能開銷踏烙。
? ? ? 關(guān)于垂直分表师骗,在公車二期數(shù)據(jù)庫(kù)評(píng)審時(shí)討論過(guò) 申請(qǐng)單表字段比較多,將熱點(diǎn)字段拆分到擴(kuò)展表讨惩。
優(yōu)點(diǎn):
解決業(yè)務(wù)系統(tǒng)層面的耦合辟癌,業(yè)務(wù)清晰
高并發(fā)場(chǎng)景下,垂直切分一定程度的提升IO荐捻、數(shù)據(jù)庫(kù)連接數(shù)黍少、單機(jī)硬件資源的瓶頸
缺點(diǎn):
分庫(kù)后表無(wú)法跨庫(kù)join,只能通過(guò)接口聚合方式解決处面,提升了開發(fā)的復(fù)雜度
分布式事務(wù)處理復(fù)雜(借助第三方成熟的分布式事務(wù)框架處理厂置,比如目前采用seata AT模式)
依然存在單表數(shù)據(jù)量過(guò)大的問(wèn)題(需要水平切分)? 公車二期垂直分庫(kù)后,比如調(diào)度業(yè)務(wù)庫(kù)中依然存在單表數(shù)據(jù)量 會(huì)隨著系統(tǒng)運(yùn)行快速增長(zhǎng)魂角,導(dǎo)致最終單表過(guò)大昵济。
2、水平切分
當(dāng)應(yīng)用難以再細(xì)粒度的垂直切分野揪,或切分后數(shù)據(jù)量行數(shù)巨大访忿,存在單庫(kù)讀寫、存儲(chǔ)性能瓶頸斯稳,此時(shí)就需要進(jìn)行水平切分海铆。
水平切分分為庫(kù)內(nèi)分表和分庫(kù)分表,是根據(jù)表內(nèi)數(shù)據(jù)內(nèi)在的邏輯關(guān)系挣惰,將同一個(gè)表按不同的條件分散到多個(gè)數(shù)據(jù)庫(kù)或多個(gè)表中卧斟,每個(gè)表中只包含一部分?jǐn)?shù)據(jù),從而使得單個(gè)表的數(shù)據(jù)量變小通熄,達(dá)到分布式的效果唆涝。
優(yōu)點(diǎn):
解決單庫(kù)單表數(shù)據(jù)量過(guò)大、高并發(fā)的性能瓶頸唇辨,提升系統(tǒng)穩(wěn)定性和負(fù)載能力
應(yīng)用端改造較小,不需要拆分業(yè)務(wù)模塊
缺點(diǎn):
同樣存在跨庫(kù)的分布式事務(wù)問(wèn)題
跨庫(kù)的join關(guān)聯(lián)查詢問(wèn)題
數(shù)據(jù)多次擴(kuò)展難度和維護(hù)量極大能耻,比如隨著業(yè)務(wù)的增速赏枚,原來(lái)規(guī)劃的分片數(shù)量不夠,需要擴(kuò)容晓猛,擴(kuò)容后分片增加饿幅,那么就會(huì)影響原有分片策略,會(huì)造成數(shù)據(jù)需要進(jìn)行遷移重新分片戒职。
水平切分后原本在同一個(gè)庫(kù)的同一個(gè)表的數(shù)據(jù)會(huì)被劃分到不同庫(kù)的不同表中栗恩,每個(gè)庫(kù)和表的數(shù)據(jù)都不一樣,但表結(jié)構(gòu)一樣洪燥。
水平切分規(guī)則:
A磕秤、根據(jù)數(shù)值范圍
按照時(shí)間區(qū)間或ID區(qū)間來(lái)切分乳乌。例如:按日期將不同月份或年份的數(shù)據(jù)分散到不同的庫(kù)和表中;再比如按照主鍵值為1~5000000的記錄分到第一個(gè)庫(kù)市咆,5000000~10000000的分到第二個(gè)庫(kù)汉操,以此類推。這種就是按照范圍分片蒙兰。
還有一種方式叫”冷熱數(shù)據(jù)分離”磷瘤,就是將一些使用較少的歷史數(shù)據(jù)遷移到其他庫(kù)中,業(yè)務(wù)功能上只提供熱點(diǎn)數(shù)據(jù)的查詢搜变,也是一種范圍分片的實(shí)踐采缚。
數(shù)值范圍優(yōu)點(diǎn):
單表大小可控
利于水平擴(kuò)展,后期如果想對(duì)整個(gè)分片擴(kuò)容時(shí)挠他,只需要添加節(jié)點(diǎn)即可扳抽,無(wú)需對(duì)其他分片的數(shù)據(jù)進(jìn)行遷移
使用分片字段進(jìn)行范圍查找時(shí),連續(xù)分片可快速定位分片進(jìn)行快速查詢绩社,有效避免跨分片查詢的問(wèn)題摔蓝。
缺點(diǎn):
熱點(diǎn)數(shù)據(jù)成為性能瓶頸。連續(xù)分片可能存在數(shù)據(jù)熱點(diǎn)愉耙,例如按時(shí)間字段分片贮尉,有些分片存儲(chǔ)最近時(shí)間段內(nèi)的數(shù)據(jù),可能會(huì)被頻繁的讀寫朴沿,而有些分片存儲(chǔ)的歷史數(shù)據(jù)猜谚,則很少被查詢
B、根據(jù)數(shù)值取模(或哈希取模)
? ? ? 一般采用hash取模mod的切分方式赌渣,例如:將車輛調(diào)度表魏铅、司機(jī)表、出車任務(wù)表根據(jù) 車輛ID 或者申請(qǐng)單號(hào) 字段切分到多個(gè)庫(kù)或表中坚芜,余數(shù)為0的放到第一個(gè)庫(kù)的第一個(gè)表览芳,余數(shù)為1的放到第二個(gè)庫(kù)的第二個(gè)表,以此類推鸿竖。這樣同一個(gè)申請(qǐng)單 或者 同一個(gè)車輛的數(shù)據(jù)會(huì)分散到同一個(gè)庫(kù)中或表中沧竟,如果查詢條件帶有車輛ID或申請(qǐng)單號(hào)字段時(shí),就可以明確定位到相應(yīng)庫(kù)和表去查詢缚忧。
優(yōu)點(diǎn):
數(shù)據(jù)分片相對(duì)比較均勻悟泵,不容易出現(xiàn)熱點(diǎn)和并發(fā)訪問(wèn)的瓶頸
缺點(diǎn):
后期分片擴(kuò)容時(shí),需要遷移舊的數(shù)據(jù)
容易面臨跨分片查詢的復(fù)雜問(wèn)題闪水。如果頻繁用到的查詢條件中不帶分片鍵時(shí)糕非,將會(huì)導(dǎo)致無(wú)法精確定位數(shù)據(jù)庫(kù)和表,就會(huì)導(dǎo)致全分片路由,向所有分片發(fā)起查詢朽肥,再進(jìn)行結(jié)果歸并禁筏,取最小集返回給應(yīng)用,分庫(kù)反而成為拖累鞠呈。
類比Oracle的分區(qū)表融师。
二、分庫(kù)分表的問(wèn)題匯總
1蚁吝、事務(wù)一致性問(wèn)題
解決方法:
分布式事務(wù)
當(dāng)更新內(nèi)容同時(shí)分布在不同庫(kù)中旱爆,不可避免會(huì)帶來(lái)跨庫(kù)事務(wù)問(wèn)題【阶拢跨分片事務(wù)也是分布式事務(wù)怀伦,沒(méi)有簡(jiǎn)單的方案,可采用成熟的第三方分布式事務(wù)解決方案山林,seata房待。
最終一致性
對(duì)于性能要求很高,但對(duì)一致性要求不高的系統(tǒng)驼抹,不要求系統(tǒng)的實(shí)時(shí)一致性桑孩,只要在允許的時(shí)間段內(nèi)達(dá)到最終一致性即可,可采用事務(wù)補(bǔ)償?shù)姆绞娇蚣健Ec事務(wù)在執(zhí)行中發(fā)生錯(cuò)誤后立即回滾的方式不同流椒,事務(wù)補(bǔ)償是一種事后檢查補(bǔ)救的措施,一些常見的實(shí)現(xiàn)方法有:對(duì)數(shù)據(jù)進(jìn)行對(duì)賬檢查明也,基于日志進(jìn)行對(duì)比宣虾,定期同標(biāo)準(zhǔn)數(shù)據(jù)來(lái)源進(jìn)行同步等等。是否可采用事務(wù)補(bǔ)償還要結(jié)合業(yè)務(wù)系統(tǒng)對(duì)一致性的要求來(lái)考慮温数,如果必須要求強(qiáng)一致性绣硝,就不能使用事務(wù)補(bǔ)償機(jī)制。
比如用戶積分累計(jì)撑刺,如果對(duì)用戶賬戶積分累計(jì)出現(xiàn)錯(cuò)誤失敗了鹉胖,可以降級(jí)處理,先記錄一個(gè)日志够傍,事后跑批對(duì)累計(jì)失敗的進(jìn)行重新處理次员,這種處理方式就叫最終一致性。
2、跨節(jié)點(diǎn)關(guān)聯(lián)查詢 join 問(wèn)題
? ? ? 切分之前,系統(tǒng)中很多列表和詳情頁(yè)所需的數(shù)據(jù)可以通過(guò)sql join來(lái)完成峻凫。而切分之后矮湘,數(shù)據(jù)可能分布在不同的節(jié)點(diǎn)上,此時(shí)join帶來(lái)的問(wèn)題就比較麻煩了,考慮到性能搞挣,盡量避免使用join查詢带迟。
解決方案:
全局表
全部分庫(kù)中存在相同的表和數(shù)據(jù),全局表必須是數(shù)據(jù)量小的囱桨,增長(zhǎng)速度微乎其微的仓犬。
字段冗余
ER關(guān)系
建立關(guān)聯(lián)關(guān)系,使用相同的分片規(guī)則
采用關(guān)聯(lián)關(guān)系舍肠,這樣可以使用相同的分片鍵和策略
數(shù)據(jù)組裝
應(yīng)用層進(jìn)行結(jié)果歸并組裝
3搀继、全局主鍵重復(fù)問(wèn)題
使用自增主鍵模式時(shí),對(duì)于分片后的庫(kù)表翠语,各自自增叽躯,將會(huì)出現(xiàn)主鍵重復(fù)問(wèn)題。
解決方案:
設(shè)定不同起始數(shù)值和步長(zhǎng)肌括;擴(kuò)容時(shí)需要維護(hù)
UUID点骑;字符串類型不利于聚簇索引
雪花分布式自增ID算法;強(qiáng)依賴時(shí)鐘谍夭,時(shí)鐘回?fù)軙r(shí)會(huì)造成ID重復(fù)
業(yè)界開源的雪花算法增強(qiáng)實(shí)現(xiàn)黑滴,比如美團(tuán)的Leaf,百度的UIDGenerator
三紧索、什么時(shí)候考慮切分
1袁辈、能不切分盡量不要切分
并不是所有表都需要進(jìn)行切分,主要還是看數(shù)據(jù)的增長(zhǎng)速度齐板。切分后會(huì)在某種程度上提升業(yè)務(wù)的復(fù)雜度吵瞻,數(shù)據(jù)庫(kù)除了承載數(shù)據(jù)的存儲(chǔ)和查詢外,協(xié)助業(yè)務(wù)更好的實(shí)現(xiàn)需求也是其重要工作之一甘磨。
不到萬(wàn)不得已不用輕易使用分庫(kù)分表這個(gè)大招橡羞,避免”過(guò)度設(shè)計(jì)”和”過(guò)早優(yōu)化”。分庫(kù)分表之前济舆,不要為分而分卿泽,先盡力去做力所能及的事情,例如:升級(jí)硬件滋觉、升級(jí)網(wǎng)絡(luò)签夭、讀寫分離、索引優(yōu)化等等椎侠。當(dāng)數(shù)據(jù)量達(dá)到單表的瓶頸時(shí)候第租,再考慮分庫(kù)分表。
2我纪、數(shù)據(jù)量過(guò)大慎宾,正常運(yùn)維影響業(yè)務(wù)訪問(wèn)
1)對(duì)數(shù)據(jù)庫(kù)備份丐吓,如果單表太大,備份時(shí)需要大量的磁盤IO和網(wǎng)絡(luò)IO趟据。例如1T的數(shù)據(jù)券犁,網(wǎng)絡(luò)傳輸占50MB時(shí)候,需要20000秒才能傳輸完畢汹碱,整個(gè)過(guò)程的風(fēng)險(xiǎn)都是比較高的
2)對(duì)一個(gè)很大的表進(jìn)行DDL修改時(shí)粘衬,MySQL會(huì)鎖住全表,這個(gè)時(shí)間會(huì)很長(zhǎng)咳促,這段時(shí)間業(yè)務(wù)不能訪問(wèn)此表稚新,影響很大。將數(shù)據(jù)表拆分等缀,總量減少枷莉,有助于降低這個(gè)風(fēng)險(xiǎn)。
3)大表會(huì)經(jīng)常訪問(wèn)與更新尺迂,就更有可能出現(xiàn)鎖等待笤妙。將數(shù)據(jù)切分,用空間換時(shí)間噪裕,變相降低訪問(wèn)壓力
3蹲盘、數(shù)據(jù)量快速增長(zhǎng)
以公車調(diào)度申請(qǐng)表為例,該表字段多膳音,數(shù)據(jù)量如果隨著業(yè)務(wù)增速召衔,數(shù)據(jù)量增長(zhǎng)過(guò)快的話,對(duì)該表的幾個(gè)狀態(tài)熱點(diǎn)字段讀寫頻繁祭陷,其他字段幾乎不變苍凛,該表就會(huì)有壓力,可遵循冷熱分離的垂直切分兵志,將熱點(diǎn)字段拆分出去醇蝴。
同樣與調(diào)度申請(qǐng)關(guān)聯(lián),其他車輛調(diào)度表想罕、司機(jī)反饋表悠栓、出車任務(wù)表 都會(huì)隨著業(yè)務(wù)快速發(fā)展,數(shù)據(jù)量快速增長(zhǎng)的情況按价,且數(shù)據(jù)量還大惭适,就需要考慮切分。
4楼镐、安全性和可用性
在業(yè)務(wù)層面上垂直切分癞志,將不相關(guān)的業(yè)務(wù)的數(shù)據(jù)庫(kù)分隔,因?yàn)槊總€(gè)業(yè)務(wù)的數(shù)據(jù)量框产、訪問(wèn)量都不同今阳,不能因?yàn)橐粋€(gè)業(yè)務(wù)把數(shù)據(jù)庫(kù)搞跨而牽連到其他業(yè)務(wù)师溅。利用水平切分,當(dāng)一個(gè)數(shù)據(jù)庫(kù)出現(xiàn)問(wèn)題時(shí)盾舌,不會(huì)影響到100%的用戶,每個(gè)庫(kù)只承擔(dān)業(yè)務(wù)的一部分?jǐn)?shù)據(jù)蘸鲸,這樣整體的可用性就能提高妖谴。
四、分庫(kù)分表實(shí)現(xiàn)方案
能提供分庫(kù)分表的成熟開源解決方案的有兩種形式酌摇,一種是基于中間件膝舅,一種是基于JDBC驅(qū)動(dòng)層的增強(qiáng)代理。
ShardingSphere (Apache頂級(jí)項(xiàng)目)包含 ShardingJDBC窑多、ShardingProxy仍稀、Sharding-Scaling
TSharding(蘑菇街)
Atlas(奇虎360)
Cobar(阿里巴巴)
MyCAT(基于Cobar)
Oceanus(58同城)
Vitess(谷歌)
ShardingJDBC定義為輕量級(jí)Java框架,在Java的JDBC層提供的額外服務(wù)埂息。 它使用客戶端直連數(shù)據(jù)庫(kù)技潘,以jar包形式提供服務(wù),無(wú)需額外部署和依賴千康,可理解為增強(qiáng)版的JDBC驅(qū)動(dòng)享幽,完全兼容JDBC和各種ORM框架。? 像MyBatis拾弃、hibernate這類ORM框架 都是基于JDBC驅(qū)動(dòng)之上進(jìn)行封裝更高級(jí)特性功能值桩。
ShardingSphere官網(wǎng) :https://shardingsphere.apache.org/
ShardingJDBC數(shù)據(jù)分片、讀寫分離
核心概念:
邏輯表:水平拆分的數(shù)據(jù)庫(kù)(表)的相同邏輯和數(shù)據(jù)結(jié)構(gòu)表的總稱豪椿。
真實(shí)表:在分片的數(shù)據(jù)庫(kù)中真實(shí)存在的物理表奔坟。
數(shù)據(jù)節(jié)點(diǎn):數(shù)據(jù)分片的最小單元。由數(shù)據(jù)源名稱和數(shù)據(jù)表組成搭盾,例:ds_0.t_order_0咳秉。
綁定表:指分片規(guī)則一致的主表和子表。
廣播表:指所有的分片數(shù)據(jù)源中都存在的表增蹭,表結(jié)構(gòu)和表中的數(shù)據(jù)在每個(gè)數(shù)據(jù)庫(kù)中均完全一致滴某。適用于數(shù)據(jù)量不大且需要與海量數(shù)據(jù)的表進(jìn)行關(guān)聯(lián)查詢的場(chǎng)景。也就是全局表滋迈。
分片概念:
分片鍵:用于分片的數(shù)據(jù)庫(kù)字段霎奢,將數(shù)據(jù)庫(kù)(表)水平拆分的關(guān)鍵字段。
分片算法:通過(guò)分片算法將數(shù)據(jù)分片饼灿,支持通過(guò)=幕侠、>=、<=碍彭、>晤硕、<悼潭、BETWEEN和IN分片。包括 精確分片算法(=和in)舞箍、范圍分片算法(>=舰褪、<=、>疏橄、<占拍、BETWEEN)、復(fù)合分片算法(多分片鍵)捎迫、Hint分片算法
分片策略:
依據(jù)分片鍵 + 分片算法的結(jié)合晃酒,形成多種分片策略。行表達(dá)式分片策略(單分片鍵)窄绒、標(biāo)準(zhǔn)分片策略(單分片鍵贝次,支持精確分片和范圍分片算法)、復(fù)合分片策略(多分片鍵的分片算法)彰导、Hint分片策略(通過(guò)Hint指定分片值而非從SQL中提取分片值的方式進(jìn)行分片的策略)蛔翅、不分片策略
SQL Hint:對(duì)于分片字段非SQL決定,而由其他外置條件決定的場(chǎng)景螺戳,可使用SQL Hint靈活的注入分片字段搁宾。
內(nèi)核:
解析引擎:對(duì)SQL進(jìn)行詞法解析和語(yǔ)法解析
路由引擎:
根據(jù)解析上下文匹配數(shù)據(jù)庫(kù)和表的分片策略,并生成路由路徑倔幼。 對(duì)于攜帶分片鍵的SQL盖腿,根據(jù)分片鍵的不同可以劃分為單片路由(分片鍵的操作符是等號(hào))、多片路由(分片鍵的操作符是IN)和范圍路由(分片鍵的操作符是BETWEEN)损同。 不攜帶分片鍵的SQL則采用廣播路由翩腐。
改寫引擎:
應(yīng)用層面向邏輯庫(kù)與邏輯表書寫的SQL,并不能夠直接在真實(shí)的數(shù)據(jù)庫(kù)中執(zhí)行膏燃,SQL改寫用于將邏輯SQL改寫為在真實(shí)數(shù)據(jù)庫(kù)中可以正確執(zhí)行的SQL茂卦。 它包括正確性改寫和優(yōu)化改寫兩部分。
執(zhí)行引擎:
負(fù)責(zé)將路由和改寫完成之后的真實(shí)SQL安全且高效發(fā)送到底層數(shù)據(jù)源執(zhí)行组哩。
歸并引擎:
將從各個(gè)數(shù)據(jù)節(jié)點(diǎn)獲取的多數(shù)據(jù)結(jié)果集等龙,組合成為一個(gè)結(jié)果集并正確的返回至請(qǐng)求客戶端,稱為結(jié)果歸并伶贰。分為遍歷歸并蛛砰、排序歸并、分組歸并黍衙、聚合歸并泥畅、分頁(yè)歸并。
讀寫分離概念:
主庫(kù)
添加琅翻、更新以及刪除數(shù)據(jù)操作所使用的數(shù)據(jù)庫(kù)位仁,支持單主庫(kù)柑贞。
從庫(kù)
查詢數(shù)據(jù)操作所使用的數(shù)據(jù)庫(kù),支持多從庫(kù)聂抢。
主從同步
將主庫(kù)的數(shù)據(jù)異步的同步到從庫(kù)的操作钧嘶。由于主從同步的異步性,從庫(kù)與主庫(kù)的數(shù)據(jù)會(huì)短時(shí)間內(nèi)不一致涛浙。主從同步需自行實(shí)現(xiàn)康辑。
負(fù)載均衡策略
通過(guò)負(fù)載均衡策略將查詢請(qǐng)求疏導(dǎo)至不同從庫(kù)。
如何使用ShardingJDBC進(jìn)行水平分片及讀寫分離
應(yīng)用中集成ShardingSphere
第一步:引入依賴
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.1</version>
</dependency>
第二步:加注解
啟動(dòng)類增加@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,DruidDataSourceAutoConfigure.class})注解轿亮,如果使用了druid數(shù)據(jù)的starter的話需要排除DruidDataSourceAutoConfigure.class自動(dòng)裝配,由ShardingSphere記性數(shù)據(jù)源的創(chuàng)建
第三步:配置參數(shù)
配置數(shù)據(jù)源胸墙、數(shù)據(jù)分片規(guī)則我注,參見以下幾種數(shù)據(jù)分片方式的配置
1、單庫(kù)水平分表(含自定義分片算法)
參數(shù)配置:
spring:
? shardingsphere:
?? datasource:
? ?? name: ds0 ? #單個(gè)數(shù)據(jù)源可使用name
? ?? #names:ds0,ds1? 多個(gè)數(shù)據(jù)源使用names迟隅,逗號(hào)分隔
? ?? ds0:? #配置每個(gè)數(shù)據(jù)源的參數(shù)
? ? ?? type: com.alibaba.druid.pool.DruidDataSource? #使用druid數(shù)據(jù)源
? ? ?? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ?? url: jdbc:mysql://127.0.0.1:3306/db_order?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ?? username: root
? ? ?? password: Root@123456
? ? ?? initial-size: 5 # 初始化大小但骨,最小,最大
? ? ?? min-idle: 5
? ? ?? maxActive: 20
? ? ?? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ?? timeBetweenEvictionRunsMillis: 60000
? ? ?? minEvictableIdleTimeMillis: 300000
? ? ?? validationQuery: SELECT x
? ? ?? testWhileIdle: true
? ? ?? testOnBorrow: false
? ? ?? testOnReturn: false
? ? ?? poolPreparedStatements: true
? ? ?? maxPoolPreparedStatementPerConnectionSize: 20
? ? ?? filters: stat,wall,log4j
? ? ?? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
?? sharding:? #定義分表策略
? ?? tables: #可對(duì)多個(gè)表進(jìn)行分表策略配置智袭,固定參數(shù)
? ? ?? t_order: #要分表的邏輯表名
? ? ? ?? actual-data-nodes: ds0.t_order_$->{0..2} #實(shí)際數(shù)據(jù)節(jié)點(diǎn)奔缠,數(shù)據(jù)源名.實(shí)際表名。? 可采用行內(nèi)表達(dá)式簡(jiǎn)化配置吼野,此處會(huì)解析為笛卡爾積的組合結(jié)果
? ? ? ?? table-strategy: #分表策略
? ? ? ? ?? #1校哎、采用單分片鍵的行表達(dá)式分片策略
? ? ? ? ?? #inline:
? ? ? ? ? ?? #sharding-column: user_id #分片鍵
? ? ? ? ? ?? #algorithm-expression: t_order_$->{user_id % 3} #分片算法,采用分片鍵取模瞳步,根據(jù)數(shù)據(jù)表分片個(gè)數(shù)取模
? ? ? ? ?? #2闷哆、采用單分片鍵的標(biāo)準(zhǔn)分片策略
? ? ? ? ?? standard:
? ? ? ? ? ?? sharding-column: user_id #分片鍵
? ? ? ? ? ?? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類 ,支持=和in兩種模式的精確分片
? ? ? ? ? ?? precise-algorithm-class-name: com.jkr.singledbshardingtables.shardingalgorithm.ShardingTablePreciseAlgorithmForUserId
? ? ? ? ? ?? #可選的范圍分片策略单起,也是自定義實(shí)現(xiàn)范圍分片算法抱怔,可搭配精準(zhǔn)分片使用,當(dāng)使用between and時(shí)嘀倒,采用范圍分片策略
? ? ? ? ? ?? #使用場(chǎng)景:當(dāng)分片鍵能夠支持查詢時(shí)使用范圍方式查詢的話屈留,在CUD時(shí)精準(zhǔn)分片,在R時(shí) 可以使用分片鍵的范圍查詢测蘑,此時(shí)如果配置了范圍分片的自定義算法實(shí)現(xiàn)
? ? ? ? ? ?? #則可以使用范圍分片算法進(jìn)行路由灌危,以便于減少路由數(shù)量,在不配置范圍分片算法時(shí)帮寻,使用了between查詢乍狐,實(shí)測(cè)為會(huì)發(fā)生找不到分片規(guī)則的異常
? ? ? ? ? ?? range-algorithm-class-name: com.jkr.singledbshardingtables.shardingalgorithm.ShardingTableRangeAlgorithmForUserId
? ? ? ? ? ? #復(fù)合分片策略,參數(shù)名為
? ? ? ? ?? #complex:
? ? ? ? ? ?? #algorithm-class-name: 需自定義實(shí)現(xiàn)復(fù)合分片算法
? ? ? ? ? ? #Hint分片策略固逗,參數(shù)名為
? ? ? ? ?? #hint:
? ? ? ? ? ?? #algorithm-class-name: 需自定義實(shí)現(xiàn)Hint算法
?
? ? ? ?? key-generator: #主鍵值生成器
? ? ? ? ?? column: id #主鍵列名
? ? ? ? ?? type: SNOWFLAKE #主鍵生成器類型浅蚪,此處為使用雪花算法
? ? ? ? ?? props: #雪花算法的屬性參數(shù)藕帜,先了解雪花算法
? ? ? ? ? ?? worker.id: 123 #工作節(jié)點(diǎn)ID
? ? ? ? ? ?? max.tolerate.time.difference.milliseconds: 300? #最大容忍的時(shí)鐘回?fù)芎撩霐?shù)
自定義精準(zhǔn)分片算法:
/**
* 自定義單分片鍵的精準(zhǔn)分片算法
*
* @author sunyunsheng
* @version 1.0
* @date 2020/11/6
*/
@Slf4j
@Component
publicclassShardingTablePreciseAlgorithmForUserIdimplementsPreciseShardingAlgorithm<Integer>{
?
/**
* 自定義精準(zhǔn)分片算法實(shí)現(xiàn),實(shí)現(xiàn)=和in的方式
* @param availableTagetNames 有效的數(shù)據(jù)表名集合惜傲,實(shí)際數(shù)據(jù)表名
* @param preciseShardingValue 分片鍵對(duì)象洽故,包含邏輯表名,分片鍵名盗誊,分片鍵值
* @return 某個(gè)具體的實(shí)際表名
*/
@Override
publicStringdoSharding(Collection<String>availableTagetNames,PreciseShardingValue<Integer>preciseShardingValue) {
?
IntegeruserId=preciseShardingValue.getValue();
?
//userId取模3
longindex=Math.floorMod(userId.longValue(),availableTagetNames.size());
//userId hash后取模3
longindex2=Math.floorMod(HashUtil.intHash(userId),availableTagetNames.size());
for(StringtableName:availableTagetNames)
? ? ?? {
//如果userId取模3后的值與可用目標(biāo)表名的后綴相等时甚,則返回該數(shù)據(jù)節(jié)點(diǎn)名
if(tableName.endsWith(StrUtil.toString(index)))
? ? ? ? ?? {
log.debug("精準(zhǔn)分片算法,當(dāng)前分片鍵值為:"+userId+",路由的目標(biāo)表名稱為:"+tableName);
returntableName;
? ? ? ? ?? }
? ? ?? }
?
return"t_order_0";
?? }
自定義范圍分片算法:
packagecom.jkr.singledbshardingtables.shardingalgorithm;
?
?
importlombok.extern.slf4j.Slf4j;
importorg.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
importorg.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
importorg.springframework.stereotype.Component;
?
importjava.util.Collection;
importjava.util.LinkedHashSet;
importjava.util.Set;
?
/**
* 自定義范圍分片算法實(shí)現(xiàn)哈踱,支持分片鍵使用between and方式的sql路由解析
*
* @author sunyunsheng
* @version 1.0
* @date 2020/11/9
*/
@Slf4j
@Component
publicclassShardingTableRangeAlgorithmForUserIdimplementsRangeShardingAlgorithm<Integer>{
?
@Override
publicCollection<String>doSharding(Collection<String>availableTagetNames,RangeShardingValue<Integer>rangeShardingValue) {
?
Set<String>resList=newLinkedHashSet<>();
intlower=rangeShardingValue.getValueRange().lowerEndpoint();
intupper=rangeShardingValue.getValueRange().upperEndpoint();
log.info("范圍分片的最小值:{}荒适,最大值:{}",lower,upper);
for(inti=lower;i<=upper;i++)
? ? ?? {
for(StringtagetName:availableTagetNames)
? ? ? ? ?? {
if(tagetName.endsWith(Math.floorMod(i,availableTagetNames.size())+""))
? ? ? ? ? ? ?? {
resList.add(tagetName);
? ? ? ? ? ? ?? }
? ? ? ? ?? }
? ? ?? }
?
returnresList;
?? }
}
2、單庫(kù)水平分表+綁定表
參數(shù)配置:
spring:
? shardingsphere:
?? datasource:
? ?? name: ds0 ? #單個(gè)數(shù)據(jù)源可使用name
? ?? #names:ds0,ds1? 多個(gè)數(shù)據(jù)源使用names开镣,逗號(hào)分隔
? ?? ds0:? #配置每個(gè)數(shù)據(jù)源的參數(shù)
? ? ?? type: com.alibaba.druid.pool.DruidDataSource? #使用druid數(shù)據(jù)源
? ? ?? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ?? url: jdbc:mysql://127.0.0.1:3306/db_order?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ?? username: root
? ? ?? password: Root@123456
? ? ?? initial-size: 5 # 初始化大小刀诬,最小,最大
? ? ?? min-idle: 5
? ? ?? maxActive: 20
? ? ?? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ?? timeBetweenEvictionRunsMillis: 60000
? ? ?? minEvictableIdleTimeMillis: 300000
? ? ?? validationQuery: SELECT x
? ? ?? testWhileIdle: true
? ? ?? testOnBorrow: false
? ? ?? testOnReturn: false
? ? ?? poolPreparedStatements: true
? ? ?? maxPoolPreparedStatementPerConnectionSize: 20
? ? ?? filters: stat,wall,log4j
? ? ?? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
?? sharding:? #定義分表策略
? ?? tables: #可對(duì)多個(gè)表進(jìn)行分表策略配置邪财,固定參數(shù)
? ? ?? t_order: #要分表的邏輯表名
? ? ? ?? actual-data-nodes: ds0.t_order_$->{0..2} #實(shí)際數(shù)據(jù)節(jié)點(diǎn)陕壹,數(shù)據(jù)源名.實(shí)際表名。? 可采用行內(nèi)表達(dá)式簡(jiǎn)化配置树埠,此處會(huì)解析為笛卡爾積的組合結(jié)果
? ? ? ?? table-strategy: #分表策略
? ? ? ? ?? #1糠馆、采用單分片鍵的行表達(dá)式分片策略
? ? ? ? ?? #inline:
? ? ? ? ? ?? #sharding-column: user_id #分片鍵
? ? ? ? ? ?? #algorithm-expression: t_order_$->{user_id % 3} #分片算法,采用分片鍵取模怎憋,根據(jù)數(shù)據(jù)表分片個(gè)數(shù)取模
? ? ? ? ?? #2又碌、采用單分片鍵的標(biāo)準(zhǔn)分片策略
? ? ? ? ?? standard:
? ? ? ? ? ?? sharding-column: user_id #分片鍵
? ? ? ? ? ?? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類 ,支持=和in兩種模式的精確分片
? ? ? ? ? ?? precise-algorithm-class-name: com.jkr.singledbshardingtables.shardingalgorithm.ShardingTablePreciseAlgorithmForUserId
? ? ? ? ? ?? #可選的范圍分片算法盛霎,也是自定義實(shí)現(xiàn)范圍分片算法赠橙,可搭配精準(zhǔn)分片使用,當(dāng)使用between and時(shí)愤炸,采用范圍分片算法
? ? ? ? ? ?? #使用場(chǎng)景:當(dāng)分片鍵能夠支持查詢時(shí)使用范圍方式查詢的話期揪,在CUD時(shí)精準(zhǔn)分片,在R時(shí) 可以使用分片鍵的范圍查詢规个,此時(shí)如果配置了范圍分片的自定義算法實(shí)現(xiàn)
? ? ? ? ? ?? #則可以使用范圍分片算法進(jìn)行路由凤薛,以便于減少路由數(shù)量,在不配置范圍分片算法時(shí)诞仓,使用了between查詢缤苫,實(shí)測(cè)為會(huì)發(fā)生找不到分片規(guī)則的異常
? ? ? ? ? ?? range-algorithm-class-name: com.jkr.singledbshardingtables.shardingalgorithm.ShardingTableRangeAlgorithmForUserId
? ? ? ?? key-generator: #主鍵值生成器
? ? ? ? ?? column: id #主鍵列名
? ? ? ? ?? type: SNOWFLAKE #主鍵生成器類型,此處為使用雪花算法
? ? ? ? ?? props: #雪花算法的屬性參數(shù)墅拭,先了解雪花算法
? ? ? ? ? ?? worker.id: 123 #工作節(jié)點(diǎn)ID
? ? ? ? ? ?? max.tolerate.time.difference.milliseconds: 300? #最大容忍的時(shí)鐘回?fù)芎撩霐?shù)
? ? ?? t_order_item:
? ? ? ?? actual-data-nodes: ds0.t_order_item_$->{0..2}
? ? ? ?? table-strategy:
? ? ? ? ?? #inline:
? ? ? ? ?? #sharding-column: user_id
? ? ? ? ?? #algorithm-expression: t_order_$->{user_id % 3}
? ? ? ? ?? #2活玲、采用單分片鍵的標(biāo)準(zhǔn)分片策略
? ? ? ? ?? standard:
? ? ? ? ? ?? sharding-column: user_id
? ? ? ? ? ?? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類
? ? ? ? ? ?? precise-algorithm-class-name: com.jkr.singledbshardingtablesbinding.module.shardingalogrithm.ShardingTablePreciseAlgorithmForUserId
? ? ? ? ? ?? #range-algorithm-class-name: com.jkr.singledbshardingtablesbinding.module.shardingalogrithm.ShardingTableRangeAlgorithmForUserId
? ? ? ?? key-generator:
? ? ? ? ?? column: item_id
? ? ? ? ?? type: SNOWFLAKE
? ? ? ? ?? props:
? ? ? ? ? ?? worker.id: 521
? ? ? ? ? ?? max.tolerate.time.difference.milliseconds: 300
? ?? #配置t_order,t_order_item 為綁定表關(guān)系,減少sql路由,可以配置多組綁定表,使用數(shù)組形式下標(biāo)追加
? ?? binding-tables: t_order,t_order_item
多一個(gè)? ? binding-tables: t_order,t_order_item 配置即可舒憾,但分片鍵和分片規(guī)則要一致镀钓。
先測(cè)無(wú)綁定表關(guān)系配置的路由結(jié)果,再測(cè)配置綁定表關(guān)系的路由結(jié)果镀迂。
3丁溅、單庫(kù)水平分表+一主一從讀寫分離
參數(shù)配置:
spring:
? shardingsphere:
?? datasource:
? ?? #分片+讀寫分離
? ?? names: master,slave
? ?? master:
? ? ?? type: com.alibaba.druid.pool.DruidDataSource
? ? ?? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ?? url: jdbc:mysql://127.0.0.1:3306/db_order?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ?? username: root
? ? ?? password: Root@123456
? ? ?? initial-size: 5 # 初始化大小,最小探遵,最大
? ? ?? min-idle: 5
? ? ?? maxActive: 20
? ? ?? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ?? timeBetweenEvictionRunsMillis: 60000
? ? ?? minEvictableIdleTimeMillis: 300000
? ? ?? validationQuery: SELECT x
? ? ?? testWhileIdle: true
? ? ?? testOnBorrow: false
? ? ?? testOnReturn: false
? ? ?? poolPreparedStatements: true
? ? ?? maxPoolPreparedStatementPerConnectionSize: 20
? ? ?? filters: stat,wall,log4j
? ? ?? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
? ?? slave:
? ? ?? type: com.alibaba.druid.pool.DruidDataSource
? ? ?? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ?? url: jdbc:mysql://127.0.0.1:3306/db_order_slave0?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ?? username: root
? ? ?? password: Root@123456
? ? ?? initial-size: 5 # 初始化大小窟赏,最小,最大
? ? ?? min-idle: 5
? ? ?? maxActive: 20
? ? ?? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ?? timeBetweenEvictionRunsMillis: 60000
? ? ?? minEvictableIdleTimeMillis: 300000
? ? ?? validationQuery: SELECT x
? ? ?? testWhileIdle: true
? ? ?? testOnBorrow: false
? ? ?? testOnReturn: false
? ? ?? poolPreparedStatements: true
? ? ?? maxPoolPreparedStatementPerConnectionSize: 20
? ? ?? filters: stat,wall,log4j
? ? ?? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
?? sharding:
? ?? tables:
? ? ?? t_order:
? ? ? ?? actual-data-nodes: ds0.t_order_$->{0..2}
? ? ? ?? table-strategy:
? ? ? ? ?? #inline:
? ? ? ? ?? #sharding-column: user_id
? ? ? ? ?? #algorithm-expression: t_order_$->{user_id % 3}
? ? ? ? ?? #2箱季、采用單分片鍵的標(biāo)準(zhǔn)分片策略
? ? ? ? ?? standard:
? ? ? ? ? ?? sharding-column: user_id
? ? ? ? ? ?? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類
? ? ? ? ? ?? precise-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTablePreciseAlgorithmForUserId
? ? ? ? ? ?? #自定義實(shí)現(xiàn)的范圍分片算法類
? ? ? ? ? ?? #range-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTableRangeAlgorithmForUserId
? ? ? ?? key-generator:
? ? ? ? ?? column: id
? ? ? ? ?? type: SNOWFLAKE
? ? ? ? ?? props:
? ? ? ? ? ?? worker.id: 123
? ? ? ? ? ?? max.tolerate.time.difference.milliseconds: 300
? ? ?? t_order_item:
? ? ? ?? actual-data-nodes: ds0.t_order_item_$->{0..2}
? ? ? ?? table-strategy:
? ? ? ? ?? #inline:
? ? ? ? ?? #sharding-column: user_id
? ? ? ? ?? #algorithm-expression: t_order_$->{user_id % 3}
? ? ? ? ?? #2涯穷、采用單分片鍵的標(biāo)準(zhǔn)分片策略
? ? ? ? ?? standard:
? ? ? ? ? ?? sharding-column: user_id
? ? ? ? ? ?? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類
? ? ? ? ? ?? precise-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTablePreciseAlgorithmForUserId
? ? ? ? ? ?? #range-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTableRangeAlgorithmForUserId
? ? ? ?? key-generator:
? ? ? ? ?? column: item_id
? ? ? ? ?? type: SNOWFLAKE
? ? ? ? ?? props:
? ? ? ? ? ?? worker.id: 521
? ? ? ? ? ?? max.tolerate.time.difference.milliseconds: 300
? ?? #配置t_order,t_order_item 為綁定表關(guān)系,減少sql路由
? ?? binding-tables: t_order,t_order_item
? ?? #配置主從規(guī)則藏雏,每個(gè)主數(shù)據(jù)源一套配置求豫,包含主數(shù)據(jù)源名稱和從數(shù)據(jù)源名稱,從數(shù)據(jù)源可以配置多個(gè)诉稍,使用逗號(hào)分隔;多個(gè)主從配置最疆,依次配置
? ?? master-slave-rules:
? ? ?? ds0:
? ? ? ?? master-data-source-name: master
? ? ? ?? slave-data-source-names: slave
shardingjdbc 同一線程且同一數(shù)據(jù)庫(kù)連接內(nèi)杯巨,如有寫入操作,以后的讀操作均從主庫(kù)讀取努酸,用于保證數(shù)據(jù)一致性服爷。
先讀后寫路由結(jié)果:讀操作路由至從庫(kù)(讀庫(kù)),寫操作路由至主庫(kù)(寫庫(kù))获诈;
先寫后讀路由結(jié)果:寫操作路由至主庫(kù)(寫庫(kù))仍源,后續(xù)的讀全部路由至主庫(kù)(寫庫(kù));
4舔涎、單庫(kù)水平分表+一主多從讀寫分離笼踩,自定義從庫(kù)負(fù)載均衡算法實(shí)現(xiàn)
水平分表+一主多從讀寫分離參數(shù)配置:
spring:
? shardingsphere:
?? datasource:
? ?? #分片+讀寫分離
? ?? names: master,slave0,slave1
? ?? master:
? ? ?? type: com.alibaba.druid.pool.DruidDataSource
? ? ?? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ?? url: jdbc:mysql://127.0.0.1:3306/db_order?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ?? username: root
? ? ?? password: Root@123456
? ? ?? initial-size: 5 # 初始化大小,最小亡嫌,最大
? ? ?? min-idle: 5
? ? ?? maxActive: 20
? ? ?? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ?? timeBetweenEvictionRunsMillis: 60000
? ? ?? minEvictableIdleTimeMillis: 300000
? ? ?? validationQuery: SELECT x
? ? ?? testWhileIdle: true
? ? ?? testOnBorrow: false
? ? ?? testOnReturn: false
? ? ?? poolPreparedStatements: true
? ? ?? maxPoolPreparedStatementPerConnectionSize: 20
? ? ?? filters: stat,wall,log4j
? ? ?? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
? ?? slave0:
? ? ?? type: com.alibaba.druid.pool.DruidDataSource
? ? ?? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ?? url: jdbc:mysql://127.0.0.1:3306/db_order_slave0?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ?? username: root
? ? ?? password: Root@123456
? ? ?? initial-size: 5 # 初始化大小嚎于,最小,最大
? ? ?? min-idle: 5
? ? ?? maxActive: 20
? ? ?? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ?? timeBetweenEvictionRunsMillis: 60000
? ? ?? minEvictableIdleTimeMillis: 300000
? ? ?? validationQuery: SELECT x
? ? ?? testWhileIdle: true
? ? ?? testOnBorrow: false
? ? ?? testOnReturn: false
? ? ?? poolPreparedStatements: true
? ? ?? maxPoolPreparedStatementPerConnectionSize: 20
? ? ?? filters: stat,wall,log4j
? ? ?? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
? ?? slave1:
? ? ?? type: com.alibaba.druid.pool.DruidDataSource
? ? ?? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ?? url: jdbc:mysql://127.0.0.1:3306/db_order_slave1?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ?? username: root
? ? ?? password: Root@123456
? ? ?? initial-size: 5 # 初始化大小挟冠,最小于购,最大
? ? ?? min-idle: 5
? ? ?? maxActive: 20
? ? ?? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ?? timeBetweenEvictionRunsMillis: 60000
? ? ?? minEvictableIdleTimeMillis: 300000
? ? ?? validationQuery: SELECT x
? ? ?? testWhileIdle: true
? ? ?? testOnBorrow: false
? ? ?? testOnReturn: false
? ? ?? poolPreparedStatements: true
? ? ?? maxPoolPreparedStatementPerConnectionSize: 20
? ? ?? filters: stat,wall,log4j
? ? ?? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
?
?? sharding:
? ?? tables:
? ? ?? t_order:
? ? ? ?? actual-data-nodes: ds0.t_order_$->{0..2}
? ? ? ?? table-strategy:
? ? ? ? ?? #inline:
? ? ? ? ?? #sharding-column: user_id
? ? ? ? ?? #algorithm-expression: t_order_$->{user_id % 3}
? ? ? ? ?? #2、采用單分片鍵的標(biāo)準(zhǔn)分片策略
? ? ? ? ?? standard:
? ? ? ? ? ?? sharding-column: user_id
? ? ? ? ? ?? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類
? ? ? ? ? ?? precise-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTablePreciseAlgorithmForUserId
? ? ? ? ? ?? #range-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTableRangeAlgorithmForUserId
? ? ? ?? key-generator:
? ? ? ? ?? column: id
? ? ? ? ?? type: SNOWFLAKE
? ? ? ? ?? props:
? ? ? ? ? ?? worker.id: 123
? ? ? ? ? ?? max.tolerate.time.difference.milliseconds: 300
? ? ?? t_order_item:
? ? ? ?? actual-data-nodes: ds0.t_order_item_$->{0..2}
? ? ? ?? table-strategy:
? ? ? ? ?? #inline:
? ? ? ? ?? #sharding-column: user_id
? ? ? ? ?? #algorithm-expression: t_order_$->{user_id % 3}
? ? ? ? ?? #2知染、采用單分片鍵的標(biāo)準(zhǔn)分片策略
? ? ? ? ?? standard:
? ? ? ? ? ?? sharding-column: user_id
? ? ? ? ? ?? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類
? ? ? ? ? ?? precise-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTablePreciseAlgorithmForUserId
? ? ? ? ? ?? #range-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTableRangeAlgorithmForUserId
? ? ? ?? key-generator:
? ? ? ? ?? column: item_id
? ? ? ? ?? type: SNOWFLAKE
? ? ? ? ?? props:
? ? ? ? ? ?? worker.id: 521
? ? ? ? ? ?? max.tolerate.time.difference.milliseconds: 300
? ?? #配置t_order,t_order_item 為綁定表關(guān)系肋僧,減少sql路由
? ?? binding-tables: t_order,t_order_item
? ?? #配置主從規(guī)則,每個(gè)主數(shù)據(jù)源一套配置,包含主數(shù)據(jù)源名稱和從數(shù)據(jù)源名稱嫌吠,從數(shù)據(jù)源可以配置多個(gè)止潘,使用逗號(hào)分隔;多個(gè)主從配置居兆,依次配置
? ?? master-slave-rules:
? ? ?? ds0:
? ? ? ?? master-data-source-name: master
? ? ? ?? slave-data-source-names: slave0,slave1
? ? ? ?? #如果從數(shù)據(jù)源有多個(gè)覆山,可以使用內(nèi)置負(fù)載均衡算法,指定內(nèi)置負(fù)載均衡算法的類型 ROUND_ROBIN輪循泥栖,RANDOM隨機(jī)
? ? ? ?? load-balance-algorithm-type: VEHICLE_SPECIFIED
? ? ? ?? #也可以自定義實(shí)現(xiàn)從數(shù)據(jù)源的負(fù)載均衡算法簇宽,實(shí)現(xiàn)MasterSlaveLoadBalanceAlgorithm接口;與內(nèi)置負(fù)載均衡算法 兩者選其一,實(shí)測(cè)沒(méi)起作用
? ? ? ?? #load-balance-algorithm-class-name:
增加從庫(kù)的數(shù)據(jù)源配置吧享,并在主從規(guī)則中添加到從庫(kù)數(shù)據(jù)源列表中即可魏割,開啟負(fù)載均衡,可以使用內(nèi)置算法钢颂,分為 ROUND_ROBIN輪循钞它,RANDOM隨機(jī) 兩種。
如想使用自定義負(fù)載均衡算法殊鞭,通過(guò)下面的步驟來(lái)實(shí)現(xiàn):
A遭垛、首先需要定義一個(gè)負(fù)載均衡算法實(shí)現(xiàn)類,實(shí)現(xiàn)MasterSlaveLoadBalanceAlgorithm接口操灿,并實(shí)現(xiàn)getType和getDataSource方法锯仪;
/**
* TODO
* 自定義從庫(kù)負(fù)載均衡算法實(shí)現(xiàn)
* @author sunyunsheng
* @version 1.0
* @date 2020/11/12
*/
@Getter
@Setter
@Slf4j
publicclassVehicleMasterSlaveLoadBalanceAlgorithmimplementsMasterSlaveLoadBalanceAlgorithm{
?
privatefinalstaticStringALGORITHM_TYPE="VEHICLE_SPECIFIED";
?
privatePropertiesproperties=newProperties();
?
@Override
publicStringgetDataSource(Stringname,StringmasterDataSourceName,List<String>slaveDataSourceNames) {
?
log.debug("使用自定義從庫(kù)負(fù)載均衡算法,始終返回第一個(gè)從庫(kù)數(shù)據(jù)源名稱");
returnslaveDataSourceNames.get(0);
?? }
/**
* 返回自定義負(fù)載均衡算法類型名稱
* @return
*/
@Override
publicStringgetType() {
returnALGORITHM_TYPE;
?? }
}
B趾盐、工程中需增加SPI的配置庶喜,將自定義算法實(shí)現(xiàn)類加入到SPI配置文件中,由ShardingSphere啟動(dòng)時(shí)加載到負(fù)載均衡算法服務(wù)集合中救鲤,再通過(guò)配置的算法類型名稱久窟,找到對(duì)應(yīng)的實(shí)現(xiàn)類。
應(yīng)用配置文件中本缠,配置?
load-balance-algorithm-type: VEHICLE_SPECIFIED
C斥扛、官網(wǎng)中提到 如果不使用load-balance-algorithm-type參數(shù)指定算法實(shí)現(xiàn)類,也可以使用load-balance-algorithm-class-name 來(lái)指定具體的實(shí)現(xiàn)類全限定名稱搓茬,實(shí)測(cè)時(shí)沒(méi)起作用犹赖。所以可以使用上述形式進(jìn)行自定義負(fù)載算法實(shí)現(xiàn)及配置。
5卷仑、水平分庫(kù)水平分表+一主多從讀寫分離
參數(shù)配置:
#MyBatis-plus
mybatis-plus:
? mapper-locations: classpath:/mapper/**/*Mapper.xml
? #實(shí)體掃描峻村,多個(gè)package用逗號(hào)或者分號(hào)分隔
? type-aliases-package: com.jkr.shardingdbshardingtablesmasterslave.module.model
? global-config:
? ? db-config:
? ? ? id-type: 2
? configuration:
? ? #不加這個(gè)查詢數(shù)據(jù)為空時(shí),字段將被隱藏
? ? call-setters-on-nulls: false
? ? log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
? ? jdbc-type-for-null: null
spring:
? shardingsphere:
? ? datasource:
? ? ? #分庫(kù)分表+一主多從讀寫分離
? ? ? names: ordermaster0,ordermaster0slave0,ordermaster0slave1,ordermaster1,ordermaster1slave0,ordermaster1slave1
? ? ? ordermaster0:
? ? ? ? type: com.alibaba.druid.pool.DruidDataSource
? ? ? ? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ? ? url: jdbc:mysql://127.0.0.1:3306/db_master_order_0?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ? ? username: root
? ? ? ? password: Root@123456
? ? ? ? initial-size: 5 # 初始化大小锡凝,最小粘昨,最大
? ? ? ? min-idle: 5
? ? ? ? maxActive: 20
? ? ? ? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ? ? timeBetweenEvictionRunsMillis: 60000
? ? ? ? minEvictableIdleTimeMillis: 300000
? ? ? ? validationQuery: SELECT x
? ? ? ? testWhileIdle: true
? ? ? ? testOnBorrow: false
? ? ? ? testOnReturn: false
? ? ? ? poolPreparedStatements: true
? ? ? ? maxPoolPreparedStatementPerConnectionSize: 20
? ? ? ? filters: stat,wall,log4j
? ? ? ? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
? ? ? ordermaster0slave0:
? ? ? ? type: com.alibaba.druid.pool.DruidDataSource
? ? ? ? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ? ? url: jdbc:mysql://127.0.0.1:3306/db_master_order_0_slave0?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ? ? username: root
? ? ? ? password: Root@123456
? ? ? ? initial-size: 5 # 初始化大小,最小,最大
? ? ? ? min-idle: 5
? ? ? ? maxActive: 20
? ? ? ? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ? ? timeBetweenEvictionRunsMillis: 60000
? ? ? ? minEvictableIdleTimeMillis: 300000
? ? ? ? validationQuery: SELECT x
? ? ? ? testWhileIdle: true
? ? ? ? testOnBorrow: false
? ? ? ? testOnReturn: false
? ? ? ? poolPreparedStatements: true
? ? ? ? maxPoolPreparedStatementPerConnectionSize: 20
? ? ? ? filters: stat,wall,log4j
? ? ? ? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
? ? ? ordermaster0slave1:
? ? ? ? type: com.alibaba.druid.pool.DruidDataSource
? ? ? ? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ? ? url: jdbc:mysql://127.0.0.1:3306/db_master_order_0_slave1?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ? ? username: root
? ? ? ? password: Root@123456
? ? ? ? initial-size: 5 # 初始化大小张肾,最小芭析,最大
? ? ? ? min-idle: 5
? ? ? ? maxActive: 20
? ? ? ? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ? ? timeBetweenEvictionRunsMillis: 60000
? ? ? ? minEvictableIdleTimeMillis: 300000
? ? ? ? validationQuery: SELECT x
? ? ? ? testWhileIdle: true
? ? ? ? testOnBorrow: false
? ? ? ? testOnReturn: false
? ? ? ? poolPreparedStatements: true
? ? ? ? maxPoolPreparedStatementPerConnectionSize: 20
? ? ? ? filters: stat,wall,log4j
? ? ? ? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
? ? ? ordermaster1:
? ? ? ? type: com.alibaba.druid.pool.DruidDataSource
? ? ? ? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ? ? url: jdbc:mysql://127.0.0.1:3306/db_master_order_1?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ? ? username: root
? ? ? ? password: Root@123456
? ? ? ? initial-size: 5 # 初始化大小,最小吞瞪,最大
? ? ? ? min-idle: 5
? ? ? ? maxActive: 20
? ? ? ? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ? ? timeBetweenEvictionRunsMillis: 60000
? ? ? ? minEvictableIdleTimeMillis: 300000
? ? ? ? validationQuery: SELECT x
? ? ? ? testWhileIdle: true
? ? ? ? testOnBorrow: false
? ? ? ? testOnReturn: false
? ? ? ? poolPreparedStatements: true
? ? ? ? maxPoolPreparedStatementPerConnectionSize: 20
? ? ? ? filters: stat,wall,log4j
? ? ? ? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
? ? ? ordermaster1slave0:
? ? ? ? type: com.alibaba.druid.pool.DruidDataSource
? ? ? ? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ? ? url: jdbc:mysql://127.0.0.1:3306/db_master_order_1_slave0?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ? ? username: root
? ? ? ? password: Root@123456
? ? ? ? initial-size: 5 # 初始化大小馁启,最小,最大
? ? ? ? min-idle: 5
? ? ? ? maxActive: 20
? ? ? ? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ? ? timeBetweenEvictionRunsMillis: 60000
? ? ? ? minEvictableIdleTimeMillis: 300000
? ? ? ? validationQuery: SELECT x
? ? ? ? testWhileIdle: true
? ? ? ? testOnBorrow: false
? ? ? ? testOnReturn: false
? ? ? ? poolPreparedStatements: true
? ? ? ? maxPoolPreparedStatementPerConnectionSize: 20
? ? ? ? filters: stat,wall,log4j
? ? ? ? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
? ? ? ordermaster1slave1:
? ? ? ? type: com.alibaba.druid.pool.DruidDataSource
? ? ? ? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ? ? url: jdbc:mysql://127.0.0.1:3306/db_master_order_1_slave1?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ? ? username: root
? ? ? ? password: Root@123456
? ? ? ? initial-size: 5 # 初始化大小芍秆,最小惯疙,最大
? ? ? ? min-idle: 5
? ? ? ? maxActive: 20
? ? ? ? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ? ? timeBetweenEvictionRunsMillis: 60000
? ? ? ? minEvictableIdleTimeMillis: 300000
? ? ? ? validationQuery: SELECT x
? ? ? ? testWhileIdle: true
? ? ? ? testOnBorrow: false
? ? ? ? testOnReturn: false
? ? ? ? poolPreparedStatements: true
? ? ? ? maxPoolPreparedStatementPerConnectionSize: 20
? ? ? ? filters: stat,wall,log4j
? ? ? ? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
? ? sharding:
? ? ? #配置分表規(guī)則
? ? ? tables:
? ? ? ? t_order:
? ? ? ? ? actual-data-nodes: ds$->{0..1}.t_order_$->{0..2}
? ? ? ? ? #分庫(kù)策略
? ? ? ? ? database-strategy:
? ? ? ? ? ? standard:
? ? ? ? ? ? ? sharding-column: user_id
? ? ? ? ? ? ? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類
? ? ? ? ? ? ? precise-algorithm-class-name: com.jkr.shardingdbshardingtablesmasterslave.module.shardingalogrithm.ShardingDbPreciseAlgorithmForUserId
? ? ? ? ? #分表策略
? ? ? ? ? table-strategy:
? ? ? ? ? ? #inline:
? ? ? ? ? ? #sharding-column: user_id
? ? ? ? ? ? #algorithm-expression: t_order_$->{user_id % 3}
? ? ? ? ? ? #2、采用單分片鍵的標(biāo)準(zhǔn)分片策略
? ? ? ? ? ? standard:
? ? ? ? ? ? ? sharding-column: user_id
? ? ? ? ? ? ? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類
? ? ? ? ? ? ? precise-algorithm-class-name: com.jkr.shardingdbshardingtablesmasterslave.module.shardingalogrithm.ShardingTablePreciseAlgorithmForUserId
? ? ? ? ? ? ? #range-algorithm-class-name: com.jkr.shardingdbshardingtablesmasterslave.module.shardingalogrithm.ShardingTableRangeAlgorithmForUserId
? ? ? ? ? key-generator:
? ? ? ? ? ? column: id
? ? ? ? ? ? type: SNOWFLAKE
? ? ? ? ? ? props:
? ? ? ? ? ? ? worker.id: 123
? ? ? ? ? ? ? max.tolerate.time.difference.milliseconds: 300
? ? ? ? t_order_item:
? ? ? ? ? actual-data-nodes: ds$->{0..1}.t_order_item_$->{0..2}
? ? ? ? ? #分庫(kù)策略
? ? ? ? ? database-strategy:
? ? ? ? ? ? standard:
? ? ? ? ? ? ? sharding-column: user_id
? ? ? ? ? ? ? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類
? ? ? ? ? ? ? precise-algorithm-class-name: com.jkr.shardingdbshardingtablesmasterslave.module.shardingalogrithm.ShardingDbPreciseAlgorithmForUserId
? ? ? ? ? #分表策略
? ? ? ? ? table-strategy:
? ? ? ? ? ? #inline:
? ? ? ? ? ? #sharding-column: user_id
? ? ? ? ? ? #algorithm-expression: t_order_$->{user_id % 3}
? ? ? ? ? ? #2妖啥、采用單分片鍵的標(biāo)準(zhǔn)分片策略
? ? ? ? ? ? standard:
? ? ? ? ? ? ? sharding-column: user_id
? ? ? ? ? ? ? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類
? ? ? ? ? ? ? precise-algorithm-class-name: com.jkr.shardingdbshardingtablesmasterslave.module.shardingalogrithm.ShardingTablePreciseAlgorithmForUserId
? ? ? ? ? ? ? #range-algorithm-class-name: com.jkr.shardingdbshardingtablesmasterslave.module.shardingalogrithm.ShardingTableRangeAlgorithmForUserId
? ? ? ? ? key-generator:
? ? ? ? ? ? column: item_id
? ? ? ? ? ? type: SNOWFLAKE
? ? ? ? ? ? props:
? ? ? ? ? ? ? worker.id: 521
? ? ? ? ? ? ? max.tolerate.time.difference.milliseconds: 300
? ? ? #配置t_order,t_order_item 為綁定表關(guān)系霉颠,減少sql路由
? ? ? binding-tables: t_order,t_order_item
? ? ? #配置主從規(guī)則,每個(gè)主數(shù)據(jù)源一套配置荆虱,包含主數(shù)據(jù)源名稱和從數(shù)據(jù)源名稱捆姜,從數(shù)據(jù)源可以配置多個(gè)性雄,使用逗號(hào)分隔奶镶;多個(gè)主從配置胁孙,依次配置
? ? ? master-slave-rules:
? ? ? ? ds0:
? ? ? ? ? master-data-source-name: ordermaster0
? ? ? ? ? slave-data-source-names: ordermaster0slave0,ordermaster0slave1
? ? ? ? ? #如果從數(shù)據(jù)源有多個(gè),可以使用內(nèi)置負(fù)載均衡算法菜枷,指定內(nèi)置負(fù)載均衡算法的類型 ROUND_ROBIN輪循不从,RANDOM隨機(jī)
? ? ? ? ? #使用自定義負(fù)載均衡算法
? ? ? ? ? load-balance-algorithm-type: VEHICLE_SPECIFIED
? ? ? ? ds1:
? ? ? ? ? master-data-source-name: ordermaster1
? ? ? ? ? slave-data-source-names: ordermaster1slave0,ordermaster1slave1
? ? ? ? ? #如果從數(shù)據(jù)源有多個(gè),可以使用內(nèi)置負(fù)載均衡算法犁跪,指定內(nèi)置負(fù)載均衡算法的類型 ROUND_ROBIN輪循,RANDOM隨機(jī)
? ? ? ? ? load-balance-algorithm-type: ROUND_ROBIN
? ? props:
? ? ? sql.show: true
6歹袁、水平分庫(kù)水平分表+一主多從讀寫分離+廣播表+非分片表配置
當(dāng)進(jìn)行水平分庫(kù)分表后坷衍,由于并不是所有的表都需要進(jìn)行分片,對(duì)于非分片表又存在兩種使用情況条舔,一種是分片的表需要跟非分片表進(jìn)行關(guān)聯(lián)查詢避免跨庫(kù)關(guān)聯(lián)枫耳,一種是非分片表只存儲(chǔ)在其中一個(gè)主庫(kù)即可,與分片表無(wú)直接關(guān)聯(lián)查詢孟抗。 這兩種表的處理方式分別為 在各分庫(kù)中維護(hù)相同的非分片表迁杨,即廣播表,配置為廣播表的表在CUD時(shí)將會(huì)路由所有庫(kù)進(jìn)行同樣的操作凄硼,以保證數(shù)據(jù)的一致性铅协。對(duì)于分片表關(guān)聯(lián)廣播表查詢時(shí),將根據(jù)分片表的策略路由至指定的庫(kù)后使用指定庫(kù)的表進(jìn)行關(guān)聯(lián)查詢摊沉。
基于第5小節(jié)的水平分庫(kù)分表+讀寫分離基礎(chǔ)上配置廣播表狐史,在master-slave-rules相同層級(jí)增加一行配置即可:
#分庫(kù)時(shí),需在多個(gè)庫(kù)內(nèi)同時(shí)存在的表,為廣播表骏全,多個(gè)表以逗號(hào)分隔
broadcast-tables: t_product
對(duì)于第二種情況苍柏,數(shù)據(jù)量小的表,且增長(zhǎng)速度緩慢姜贡,無(wú)需分庫(kù)分表的話试吁,可以采用配置一個(gè)默認(rèn)數(shù)據(jù)源名稱,對(duì)配置中未指明分片規(guī)則的表全部路由至默認(rèn)數(shù)據(jù)源楼咳,對(duì)這些非分片表的CRUD將會(huì)始終路由至該默認(rèn)數(shù)據(jù)源下熄捍。 配置默認(rèn)數(shù)據(jù)源的表,同樣基于第5小節(jié)的水平分庫(kù)分表+讀寫分離基礎(chǔ)上配置在 master-slave-rules相同層級(jí)增加一行配置即可:
#未配置分片規(guī)則的表將通過(guò)默認(rèn)數(shù)據(jù)源定位
default-data-source-name: ds0
ds0為讀寫分離規(guī)則中的邏輯數(shù)據(jù)源名稱爬橡,代表非分片表將路由至ds0代表的主庫(kù)和從庫(kù)治唤。
7、讀寫分離糙申、數(shù)據(jù)脫敏在獨(dú)立使用和結(jié)合分片使用時(shí)的配置參數(shù)差異性說(shuō)明
A宾添、僅讀寫分離 與 數(shù)據(jù)分片+讀寫分離
僅讀寫分離的配置參數(shù),前綴為 spring.shardingsphere.masterslave
spring.shardingsphere.masterslave.name=ms
spring.shardingsphere.masterslave.master-data-source-name=master
spring.shardingsphere.masterslave.slave-data-source-names=slave0,slave1
spring.shardingsphere.masterslave.load-balance-algorithm-type=內(nèi)置從庫(kù)負(fù)載均衡算法類型柜裸,可選值:ROUND_ROBIN缕陕,RANDOM。
數(shù)據(jù)分片+讀寫分離時(shí)的配置參數(shù)疙挺,前綴為spring.shardingsphere.sharding.master-slave-rules
spring.shardingsphere.sharding.master-slave-rules.ds0.master-data-source-name=master0
spring.shardingsphere.sharding.master-slave-rules.ds0.slave-data-source-names=master0slave0, master0slave1
spring.shardingsphere.sharding.master-slave-rules.ds0.load-balance-algorithm-class-name= #從庫(kù)負(fù)載均衡自定義算法實(shí)現(xiàn)類的全限定名稱扛邑。
spring.shardingsphere.sharding.master-slave-rules.ds0.load-balance-algorithm-type= #內(nèi)置從庫(kù)負(fù)載均衡算法類型,可選值:ROUND_ROBIN铐然,RANDOM蔬崩。與自定義負(fù)載均衡算法實(shí)現(xiàn)類,兩者選其一搀暑,如果配置了自定義實(shí)現(xiàn)算法沥阳,則忽略內(nèi)置算法
額外注意:同時(shí)使用時(shí)需由讀寫分離配置規(guī)則中定義的邏輯數(shù)據(jù)源名稱作為 分片規(guī)則中的實(shí)際數(shù)據(jù)節(jié)點(diǎn)中的數(shù)據(jù)源名稱,比如下面完整水平分表+讀寫分離的配置:
spring:
? shardingsphere:
? ? datasource:
? ? ? #分片+讀寫分離
? ? ? names: master,slave
? ? ? master:
? ? ? ? type: com.alibaba.druid.pool.DruidDataSource
? ? ? ? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ? ? url: jdbc:mysql://127.0.0.1:3306/db_order?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ? ? username: root
? ? ? ? password: Root@123456
? ? ? ? initial-size: 5 # 初始化大小自点,最小桐罕,最大
? ? ? ? min-idle: 5
? ? ? ? maxActive: 20
? ? ? ? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ? ? timeBetweenEvictionRunsMillis: 60000
? ? ? ? minEvictableIdleTimeMillis: 300000
? ? ? ? validationQuery: SELECT x
? ? ? ? testWhileIdle: true
? ? ? ? testOnBorrow: false
? ? ? ? testOnReturn: false
? ? ? ? poolPreparedStatements: true
? ? ? ? maxPoolPreparedStatementPerConnectionSize: 20
? ? ? ? filters: stat,wall,log4j
? ? ? ? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
? ? ? slave:
? ? ? ? type: com.alibaba.druid.pool.DruidDataSource
? ? ? ? driver-class-name: com.mysql.cj.jdbc.Driver
? ? ? ? url: jdbc:mysql://127.0.0.1:3306/db_order_slave0?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
? ? ? ? username: root
? ? ? ? password: Root@123456
? ? ? ? initial-size: 5 # 初始化大小,最小桂敛,最大
? ? ? ? min-idle: 5
? ? ? ? maxActive: 20
? ? ? ? maxWait: 60000 # 配置獲取連接等待超時(shí)的時(shí)間
? ? ? ? timeBetweenEvictionRunsMillis: 60000
? ? ? ? minEvictableIdleTimeMillis: 300000
? ? ? ? validationQuery: SELECT x
? ? ? ? testWhileIdle: true
? ? ? ? testOnBorrow: false
? ? ? ? testOnReturn: false
? ? ? ? poolPreparedStatements: true
? ? ? ? maxPoolPreparedStatementPerConnectionSize: 20
? ? ? ? filters: stat,wall,log4j
? ? ? ? connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
? ? sharding:
? ? ? tables:
? ? ? ? t_order:
? ? ? ? ? actual-data-nodes: ds0.t_order_$->{0..2}
? ? ? ? ? table-strategy:
? ? ? ? ? ? #inline:
? ? ? ? ? ? #sharding-column: user_id
? ? ? ? ? ? #algorithm-expression: t_order_$->{user_id % 3}
? ? ? ? ? ? #2功炮、采用單分片鍵的標(biāo)準(zhǔn)分片策略
? ? ? ? ? ? standard:
? ? ? ? ? ? ? sharding-column: user_id
? ? ? ? ? ? ? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類
? ? ? ? ? ? ? precise-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTablePreciseAlgorithmForUserId
? ? ? ? ? ? ? #自定義實(shí)現(xiàn)的范圍分片算法類
? ? ? ? ? ? ? #range-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTableRangeAlgorithmForUserId
? ? ? ? ? key-generator:
? ? ? ? ? ? column: id
? ? ? ? ? ? type: SNOWFLAKE
? ? ? ? ? ? props:
? ? ? ? ? ? ? worker.id: 123
? ? ? ? ? ? ? max.tolerate.time.difference.milliseconds: 300
? ? ? ? t_order_item:
? ? ? ? ? actual-data-nodes: ds0.t_order_item_$->{0..2}
? ? ? ? ? table-strategy:
? ? ? ? ? ? #inline:
? ? ? ? ? ? #sharding-column: user_id
? ? ? ? ? ? #algorithm-expression: t_order_$->{user_id % 3}
? ? ? ? ? ? #2、采用單分片鍵的標(biāo)準(zhǔn)分片策略
? ? ? ? ? ? standard:
? ? ? ? ? ? ? sharding-column: user_id
? ? ? ? ? ? ? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類
? ? ? ? ? ? ? precise-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTablePreciseAlgorithmForUserId
? ? ? ? ? ? ? #自定義實(shí)現(xiàn)的范圍分片算法類
? ? ? ? ? ? ? #range-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTableRangeAlgorithmForUserId
? ? ? ? ? key-generator:
? ? ? ? ? ? column: item_id
? ? ? ? ? ? type: SNOWFLAKE
? ? ? ? ? ? props:
? ? ? ? ? ? ? worker.id: 521
? ? ? ? ? ? ? max.tolerate.time.difference.milliseconds: 300
? ? ? #配置t_order,t_order_item 為綁定表關(guān)系术唬,減少sql路由
? ? ? binding-tables: t_order,t_order_item
? ? ? #配置主從規(guī)則薪伏,每個(gè)主數(shù)據(jù)源一套配置,包含主數(shù)據(jù)源名稱和從數(shù)據(jù)源名稱粗仓,從數(shù)據(jù)源可以配置多個(gè)毅该,使用逗號(hào)分隔博秫;多個(gè)主從配置,依次配置
? ? ? master-slave-rules:
? ? ? ? ds0:
? ? ? ? ? master-data-source-name: master
? ? ? ? ? slave-data-source-names: slave
? ? ? ? ? #如果從數(shù)據(jù)源有多個(gè)眶掌,可以使用內(nèi)置負(fù)載均衡算法挡育,指定內(nèi)置負(fù)載均衡算法的類型 ROUND_ROBIN輪循,RANDOM隨機(jī)
? ? ? ? ? #load-balance-algorithm-type:
? ? ? ? ? #也可以自定義實(shí)現(xiàn)多個(gè)從數(shù)據(jù)源的負(fù)載均衡算法朴爬,實(shí)現(xiàn)MasterSlaveLoadBalanceAlgorithm接口;與內(nèi)置負(fù)載均衡算法 兩者選其一
? ? ? ? ? #load-balance-algorithm-class-name:
首先定義數(shù)據(jù)源時(shí)即寒,spring.shardingsphere.datasource.names中包含主從數(shù)據(jù)源名稱,master召噩、slave
spring:
? shardingsphere:
? ? datasource:
? ? ? #分片+讀寫分離
? ? ? names: master,slave
配置讀寫分離的主從規(guī)則時(shí)母赵,自定義邏輯數(shù)據(jù)源名稱 ds0,并配置主從數(shù)據(jù)源的名稱
#配置主從規(guī)則具滴,每個(gè)主數(shù)據(jù)源一套配置凹嘲,包含主數(shù)據(jù)源名稱和從數(shù)據(jù)源名稱,從數(shù)據(jù)源可以配置多個(gè)构韵,使用逗號(hào)分隔周蹭;多個(gè)主從配置,依次配置
master-slave-rules:
? ds0:
? ? master-data-source-name: master
? ? slave-data-source-names: slave
? ? #如果從數(shù)據(jù)源有多個(gè)疲恢,可以使用內(nèi)置負(fù)載均衡算法凶朗,指定內(nèi)置負(fù)載均衡算法的類型 ROUND_ROBIN輪循,RANDOM隨機(jī)
? ? #load-balance-algorithm-type:
? ? #也可以自定義實(shí)現(xiàn)多個(gè)從數(shù)據(jù)源的負(fù)載均衡算法显拳,實(shí)現(xiàn)MasterSlaveLoadBalanceAlgorithm接口;與內(nèi)置負(fù)載均衡算法 兩者選其一
? ? #load-balance-algorithm-class-name:
在配置分庫(kù)分表規(guī)則時(shí)棚愤,配置actual-data-nodes 實(shí)際數(shù)據(jù)節(jié)點(diǎn)參數(shù)時(shí),數(shù)據(jù)源名稱需使用自定義主從邏輯數(shù)據(jù)源名稱 ds0杂数,比如分表規(guī)則配置中的數(shù)據(jù)節(jié)點(diǎn)的數(shù)據(jù)源名為讀寫分離規(guī)則中的邏輯數(shù)據(jù)源ds0
tables:
? t_order:
?? actual-data-nodes: ds0.t_order_$->{0..2}
?? table-strategy:
? ?? #inline:
? ?? #sharding-column: user_id
? ?? #algorithm-expression: t_order_$->{user_id % 3}
? ?? #2宛畦、采用單分片鍵的標(biāo)準(zhǔn)分片策略
? ?? standard:
? ? ?? sharding-column: user_id
? ? ?? #自定義實(shí)現(xiàn)的精準(zhǔn)分片算法類
? ? ?? precise-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTablePreciseAlgorithmForUserId
? ? ?? #range-algorithm-class-name: com.jkr.onemastermoreslaveshardingtables.module.shardingalogrithm.ShardingTableRangeAlgorithmForUserId
?? key-generator:
? ?? column: id
? ?? type: SNOWFLAKE
? ?? props:
? ? ?? worker.id: 123
? ? ?? max.tolerate.time.difference.milliseconds: 300
B、僅數(shù)據(jù)脫敏和 數(shù)據(jù)分片+數(shù)據(jù)脫敏
僅數(shù)據(jù)脫敏配置參數(shù)揍移,前綴為spring.shardingsphere.encrypt
spring.shardingsphere.encrypt.encryptors.<encryptor-name>.type= #加解密器類型刃永,可自定義或選擇內(nèi)置類型:MD5/AES
spring.shardingsphere.encrypt.encryptors.<encryptor-name>.props.<property-name>= #屬性配置, 注意:使用AES加密器,需要配置AES加密器的KEY屬性:aes.key.value
spring.shardingsphere.encrypt.tables.<table-name>.columns.<logic-column-name>.plainColumn= #存儲(chǔ)明文的字段
spring.shardingsphere.encrypt.tables.<table-name>.columns.<logic-column-name>.cipherColumn= #存儲(chǔ)密文的字段
spring.shardingsphere.encrypt.tables.<table-name>.columns.<logic-column-name>.assistedQueryColumn= #輔助查詢字段羊精,針對(duì)ShardingQueryAssistedEncryptor類型的加解密器進(jìn)行輔助查詢
spring.shardingsphere.encrypt.tables.<table-name>.columns.<logic-column-name>.encryptor= #加密器名字
數(shù)據(jù)分片+數(shù)據(jù)脫敏配置參數(shù),前綴為spring.shardingsphere.sharding.encrypt-rule
spring.shardingsphere.sharding.encrypt-rule.encryptors.encryptor_aes.type=aes
spring.shardingsphere.sharding.encrypt-rule.encryptors.encryptor_aes.props.aes.key.value=123456
spring.shardingsphere.sharding.encrypt-rule.tables.t_order.columns.user_id.plainColumn=user_decrypt
spring.shardingsphere.sharding.encrypt-rule.tables.t_order.columns.user_id.cipherColumn=user_encrypt
spring.shardingsphere.sharding.encrypt-rule.tables.t_order.columns.user_id.assistedQueryColumn=user_assisted
spring.shardingsphere.sharding.encrypt-rule.tables.t_order.columns.user_id.encryptor=encryptor_aes