ShardingSphere之Sharding-JDBC分庫(kù)分表、讀寫分離


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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末囚玫,一起剝皮案震驚了整個(gè)濱河市喧锦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌抓督,老刑警劉巖燃少,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異铃在,居然都是意外死亡阵具,警方通過(guò)查閱死者的電腦和手機(jī)碍遍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)阳液,“玉大人怕敬,你說(shuō)我怎么就攤上這事×泵螅” “怎么了东跪?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鹰溜。 經(jīng)常有香客問(wèn)我虽填,道長(zhǎng),這世上最難降的妖魔是什么曹动? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任斋日,我火速辦了婚禮,結(jié)果婚禮上墓陈,老公的妹妹穿的比我還像新娘恶守。我一直安慰自己,他們只是感情好跛蛋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布熬的。 她就那樣靜靜地躺著,像睡著了一般赊级。 火紅的嫁衣襯著肌膚如雪押框。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天理逊,我揣著相機(jī)與錄音橡伞,去河邊找鬼。 笑死晋被,一個(gè)胖子當(dāng)著我的面吹牛兑徘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播羡洛,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼挂脑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了欲侮?” 一聲冷哼從身側(cè)響起崭闲,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎威蕉,沒(méi)想到半個(gè)月后刁俭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡韧涨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年牍戚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了侮繁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡如孝,死狀恐怖宪哩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情暑竟,我是刑警寧澤斋射,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站但荤,受9級(jí)特大地震影響罗岖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜腹躁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一桑包、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧纺非,春花似錦哑了、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至炕淮,卻和暖如春拆火,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背涂圆。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工们镜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人润歉。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓模狭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親踩衩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嚼鹉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容