數據庫讀寫分離、分庫分表——mycat與shardingjdbc

文章目錄

一、數據切分

  數據切分,簡單的說,就是通過某種條件,將我們之前存儲在一臺數據庫上的數據,分散到多臺數據庫中,從而達到降低單臺數據庫負載的效果。數據切分,根據其切分的規則,大致分爲兩種類型:

  • 垂直切分
  • 水平切分

1、垂直切分

  垂直切分就是按照不同的表或者Schema切分到不同的數據庫中,比如:在我們的課程中,訂單表(order)和商品表(product)在同一個數據庫中,而我們現在要對其切分,使得訂單表(order)和商品表(product)分別落到不同的物理機中的不同的數據庫中,使其完全隔離,從而達到降低數據庫負載的效果。
一句話概括:將不同的業務數據放到不同的庫中

  垂直切分的特點就是規則簡單,易於實施,可以根據業務模塊進行劃分,各個業務之間耦合性低,相互影響也較小。
  一個架構設計較好的應用系統,其總體功能肯定是有多個不同的功能模塊組成的。每一個功能模塊對應着數據庫裏的一系列表。
  意味着垂直拆分往往伴隨着,系統程序分佈式化、微服務化,當然單機的項目一般情況下也是用不到分庫分表的。

  在架構設計中,各個功能模塊之間的交互越統一、越少越好。這樣,系統模塊之間的耦合度會很低,各個系統模塊的可擴展性、可維護性也會大大提高。這樣的系統,實現數據的垂直切分就會很容易。
  但是,在實際的系統架構設計中,有一些表很難做到完全的獨立,往往存在跨庫join的現象。比如我們接到了一個需求,要求查詢某一個類目產生了多少訂單,如果在單體數據庫中,我們直接連表查詢就可以了。但是現在垂直切分成了兩個數據庫,跨庫連表查詢是十分影響性能的,也不推薦這樣用,只能通過接口去調取服務,這樣系統的複雜度又升高了。

優點:

  • 拆分後業務清晰,拆分規則明確;
  • 系統之間容易擴展和整合;
  • 數據維護簡單

缺點:

  • 部分業務表無法join,只能通過接口調用,提升了系統的複雜度;
  • 跨庫事務難以處理;
  • 垂直切分後,某些業務數據過於龐大,仍然存在單體性能瓶頸;

2、水平切分

  水平切分相比垂直切分,更爲複雜。它需要將一個表中的數據,根據某種規則拆分到不同的數據庫中,例如:訂單尾號爲奇數的訂單放在了訂單數據庫1中,而訂單尾號爲偶數的訂單放在了訂單數據庫2中。這樣,原本存在一個數據庫中的訂單數據,被水平的切分成了兩個數據庫。在查詢訂單數據時,我們還要根據訂單的尾號,判斷這個訂單在數據庫1中,還是在數據庫2中,然後將這條SQL語句發送到正確的數據庫中,查出訂單。

優點:

  • 解決了單庫大數據、高併發的性能瓶頸;
  • 拆分規則封裝好,對應用端幾乎透明,開發人員無需關心拆分細節;
  • 提高了系統的穩定性和負載能力;

缺點:

  • 拆分規則很難抽象;
  • 分片事務一致性難以解決;
  • 二次擴展時,數據遷移、維護難度大。比如:開始我們按照用戶id對2求模,但是隨着業務的增長,2臺數據庫難以支撐,還是繼續拆分成4個數據庫,那麼這時就需要做數據遷移了。

3、分庫分表的兩種模式

  • 客戶端模式,在每個應用模塊內,配置自己需要的數據源,直接訪問數據庫,在各模塊內完成數據的整合;例如:sharding-jdbc
  • 中間代理模式,中間代理統一管理所有的數據源,數據庫層對開發人員完全透明,開發人員無需關注拆分的細節。例如:MyCat

二、使用MyCat分庫分表

1、系統環境

  • 使用VMware做虛擬機,創建3臺機器
  • 操作系統使用Linux CentOS7
  • 採用yum方式,在兩臺機器上安裝mysql
  • 在第三臺機器上安裝MyCat,並修改配置文件

2、mysql安裝

(1)下載mysql的yum引導

下載地址:
https://dev.mysql.com/downloads/repo/yum/
注意選擇對應的linux版本,這裏採用linux7的,mysql 版本是8.0

(2)將文件上傳到linux系統上
(3)安裝mysql
yum localinstall mysql80-community-release-el7-3.noarch.rpm
yum install mysql-community-server
(4)啓動mysql
service mysqld start
(5)查詢登錄的默認密碼

查詢結果最後一個冒號之後的就是密碼

grep 'temporary password' /var/log/mysqld.log
(6)登錄mysql
mysql -uroot -p

然後輸入密碼

(7)修改默認密碼
ALTER USER 'root'@'localhost' IDENTIFIED BY '這裏想要的密碼';

修改的密碼需要複雜一點,一個大寫字母、一個小寫字母、一個數字和一個特殊字符,並且密碼的總長度至少爲8個字符,否則不符合密碼策略無法修改成功

(8)創建用戶並授權

創建用戶
由於我們使用的是mysql8,密碼的默認加密方式改變Navicat無法連接,需要指定爲老的加密方式:identified with mysql_native_password
當我們指定了老的加密方式後,控制檯的客戶端連接時需要指定連接的加密方式:mysql -uroot -p --default-auth=mysql_native_password

create user '用戶名'@'%' identified with mysql_natice_password by '密碼';

授權所有權限

grant all on *.* to '用戶名'@'%';

然刷新一下配置

flush privileges;

如果還是無法連接,嘗試關閉linux的防火牆

3、mycat安裝

(1)下載地址

dl.mycat.io/1.6.7.3

(2)將文件上傳到linux系統上
(3)解壓壓縮包
tar -zxvf Mycat-server-1.6.7.3-release-20190828135747-linux.tar.gz
(4)修改server.xml

進入mycat根目錄下的

vim config/server.xml

將root的schemas屬性改成user

<user name="root" defaultAccount="true">
    <property name="password">123456</property>
    <property name="schemas">user</property>
</user>

下面還有個user的配置可以直接刪掉,或者把schemas屬性也改成user

(5)修改schema.xml
vim config/schema.xml

配置分鍵表

<!-- 這個name要和server.xml配置中的schemas屬性一致 />
<!-- sqlMaxLimit會默認在查詢語句之後添加limit,防止一下查詢多個庫,數據量過大,想要額外查詢需要自己添加limit />
<schema name="user" checkSQLschema="true" sqlMaxLimit="100">
    <table name="表名" dataNode="dn200,dn201" rule="auto-sharding-long">
</schema>

配置數據節點

<!-- dataHost需要和下面的配置的dataHost的name屬性一致  />
<dataNode name="dn200" dataHost="db200" database="庫名">
<dataNode name="dn201" dataHost="db201" database="庫名">

修改dataHost

<!-- 配置第一個數據  />
<!-- balance:負載均衡類型:0不開啓讀寫分離,1和2讀寫均勻分配,3讀落在readHast上  />
<dataHost name="db200" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
    <heartbeat>select user()</heartbeat>
    <!-- 添加一個寫庫 />
    <writeHost host="M1" url="192.168.85.200:3306" user="用戶名" password="密碼">
        <!-- 添加一個讀庫 ,讀寫分離的時候使用,佔時不需要 />
        <!-- <readHost host="S1" url="192.168.85.203" user="用戶名" password="密碼"> />
    </writeHost>
</dataHost>

<!-- 配置第二個數據 />
<dataHost name="db201" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
    <heartbeat>select user()</heartbeat>
    <!-- 添加一個寫庫 />
    <writeHost host="M2" url="192.168.85.201:3306" user="用戶名" password="密碼">
    </writeHost>
</dataHost>
(6)修改分鍵規則

在schema.xml中配置的分鍵規則爲"auto-sharding-long"查看rule.xml,找到對應的規則

<tableRule name="auto-sharding-long">
    <rule>
        #分鍵的字段爲id,就是表中必須有一個名爲id的字段
        <columns>id</columns>
        <algorithm>rang-long</algorithm>
    </rule>
</tableRule>

看配置可以知道分鍵規則的計算方式爲"algorithm",在文件的下面找到對應的計算方式

<function name="rang-long" class="io.mycat.route.function.AutoPartitionByLong">
    <property name="mapFile">autopartition-long.txt</property>
</function>

具體的執行的類叫AutoPartitionByLong,配置文件叫autopartition-long.txt,在config目錄下可以找到autopartition-long.txt,打開文件,並刪除掉最後一行

#rang start-end,data node index
# K=1000,M=10000
0-500M=0
500M-1000M=1

這裏的意思是,id在0-500*10000的時候放到第一個庫,500*10000-1000*10000的時候放在第二個庫,並且這裏的規則要和schema.xml中配置的dataNode的數量一致

(7)在mysql中創建庫和表
  • 創建庫的時候,庫名需要和 schema.xml配置文件中dataNode的database屬性一致
  • 創建表的時候,表名需要和 schema.xml配置文件中schema下的table裏的name屬性一致
(8)啓動mycat
#所有信息打到控制檯
./bin/mycat console
#後臺啓動
./bin/mycat start
(9)使用Navicat進行連接

直接創建一個mysql的連接
連接地址:填寫mycat的地址,我這裏爲192.168.85.202
端口:8066(mycat默認端口)
用戶名:root(用戶名密碼都配置在server.xml中)
密碼:123456

插入數據測試一下,可以根據id的規則分別插入不同的數據,再去對應的mysql裏面查看數據是否分庫成功

(10)使用Navicat連接mycat管理

直接創建一個mysql的連接
連接地址:填寫mycat的地址,我這裏爲192.168.85.202
端口:9066(mycat管理端口)
用戶名:root(用戶名密碼都配置在server.xml中)
密碼:123456

這裏面有個user庫,雙擊是打不開的右鍵連接-》命令列介面,不要右鍵庫,

#幫助
show @@help;

#刷新配置  這樣就不用重啓mycat,就能更變配置了
reload @@config_all;

4、mysql主從配置

(1)修改主配置文件

主機地址:192.168.85.200
打開mysql的配置文件

vim /etc/my.cnf

在mysqld添加兩個配置

log-bin=test_mysql
server-id=1

重啓mysql

service mysqld restart
(2)修改從配置文件

從機地址:192.168.85.204
打開mysql的配置文件

vim /etc/my.cnf

在mysqld添加兩個配置

server-id=2

重啓mysql

service mysqld restart
(3)主創建備份賬號並授權REPLICATION SLAVE

主機上登錄mysql客戶端

mysql -uroot -p

創建replication的賬號

create user 'repl'@'%' identified by '密碼';

進行授權

grant replication slave on *.* to 'repl'@'%';

刷新權限

flush privileges;
(4)主進行鎖表,用於向從庫同步數據,鎖表之後就無法進行寫操作

主數客戶端控制檯中進行鎖表

flush tables with read lock;

查詢bin-log的日誌定位,查詢出來的東西需要記住,後面配置需要使用

show master status;
(5)主庫原本就有的數據需要手動的複製到從庫中

備份主庫數據
複製一個新的會話界面,在linux下執行下面語句,之前的mysql客戶端不能關閉,關閉後會釋放表鎖
在當前文件夾下會生成dbdump.db文件,根據數據量大小,執行時間會有所不同,可能會很長時間

mysqldump --all-databases --master-data > dbdump.db -uroot -p

將dbdump.db複製到從機上,什麼方法都行復制過去就可以了,我這裏使用scp命令

scp [email protected]:~/dbdump.db .

將數據還原到從數據庫中,從數據原本的數據會被覆蓋掉

mysql < dbdump.db -uroot -p
(6)解鎖主庫的表鎖

在主機mysql的客戶端裏輸入

unlock tables;
(7)在從上設置主的配置

在從機mysql的客戶端裏輸入

CHANGE MASTER TO 
MASTER_HOST='主機ip地址', 
MASTER_USER='主從同步的用戶(這裏是repl)',
MASTER_PASSWORD='密碼',
MASTER_LOG_FILE='第四部要記住的file名稱',
MASTER_LOG_POS=第四部要記住的Positon(這裏沒有單引號的);

完整的如下

CHANGE MASTER TO 
MASTER_HOST='192.168.85.200', 
MASTER_USER='repl',
MASTER_PASSWORD='123456',
MASTER_LOG_FILE='test-mysql.000001',
MASTER_LOG_POS=1460;

然後激活從庫

start slave;

mysql的主從搭建完成!!

(8)mycat配置讀寫分離

修改schema.xml

vim config/schema.xml

修改dataHost

<!-- balance:負載均衡類型:0不開啓讀寫分離,1和2讀寫均勻分配,3讀落在readHast上  />
<!-- 這裏的balance改成 1,2,3都沒有問題>
<dataHost name="db200" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
    <heartbeat>select user()</heartbeat>
    <!-- 添加一個寫庫 />
    <writeHost host="M1" url="192.168.85.200:3306" user="用戶名" password="密碼">
        <!-- 添加一個讀庫/>
        <readHost host="S1" url="192.168.85.204" user="用戶名" password="密碼"> />
    </writeHost>
</dataHost>

連接的時候需要連接的mycat,這樣寫入操作mycat會分配給192.168.85.200來完成,然後192.168.85.200通過mysql的主從功能將數據同步給192.168.85.204,讀操作mycat全部分配給192.168.85.204

5、mycat全局表和父子表

(1)全局表

在分片的情況下,當業務表因爲規模而進行分片以後,業務表與這些附屬的字典表之間的關聯,就成了比較棘手的問題,考慮到字典表具有以下幾個特性:
• 變動不頻繁
• 數據量總體變化不大
• 數據規模不大,很少有超過數十萬條記錄。

鑑於此,MyCAT 定義了一種特殊的表,稱之爲“全局表”,全局表具有以下特性:
• 全局表的插入、更新操作會實時在所有節點上執行,保持各個分片的數據一致性
• 全局表的查詢操作,只從一個節點獲取
• 全局表可以跟任何一個表進行 JOIN 操作
打開schema.xml

vim schema.xml

再添加一個table標籤

<table name="表名" dataNode="dn200,dn201" type="global" />

type爲global的就是全局表

(2)父子表

在實際工作中經常會遇到父子級表或者叫詳情表,例如:訂單表和訂單詳情表,但是分庫分表後,很有可能父表信息錄入到了db1中,而子表信息錄入進了db2中,這樣就無法join查詢了,mycat考慮到了這個問題,提供了父子表關係建立,讓父子表的數據錄入到同一個庫中。
創建兩張表,所有的數據庫中都要創建
o_order表(order是關鍵字,這裏使用o_order):

字段 中文解釋
id id
total_amount 價格
order_status 訂單狀態

order_item表:

字段 中文解釋
id id
order_id order表的id
product_name 商品名稱
num 購買數量

修改mycat配置,打開schema.xml

vim schema.xml

再添加一個table標籤

<table name="o_order" dataNode="dn200,dn201" type="auto-sharding-long">
    <childTable name="order_item" joinKey="order_id" parentKey="id"/>
</table>

三、MyCat-Ha

1、mycat高可用架構圖

在這裏插入圖片描述

2、mycat高可用架構搭建

(1)在兩臺機器上安裝mycat

我這裏安裝的機器ip分別爲:192.168.85.205和192.168.85.206
配置保持一致

(2)在兩臺機器上安裝haproxy

我這裏安裝的機器ip分別爲:192.168.85.210和192.168.85.211

#查詢
yum search haproxy
#安裝
yum -y install haproxy x86_64

修改配置文件

vim /etc/haproxy/haproxy.cfg

修改以下的配置,其他的保持不變

defaults
    mode        tcp
    option      tcplog
    #option    http-server-close
    #option    forwardfor   except  127.0.0.0/8
    ....
    
#這個5000是連接端口號
frontend main *:5000
    #ac | url_static     path_beg        -i /static /images /javascript /stylesheets
    #ac | url_static     path_end        -i .jpg .gif .png .css .js
    
    #這個是使用http的時候的配置,對應下方的backend static
    #use_backend static      if url_static
    #這個是使用tcp的時候的配置,對應下方的backend app
    default_packend         app
    
    ...
#配置連接的mycat
backend app
    balance     roundrobin
    server app1 192.168.85.205:8066 check
    server app2 192.168.85.206:8066 check

啓動haproxy,會爆一些警告無所謂

haproxy -f /etc/haproxy/haproxy.cfg
(3)在兩臺機器上安裝keepalived

安裝keepalived,這裏簡單的安裝一下
詳細的可以參考,裏面有詳細的keepalived安裝和說明:
https://blog.csdn.net/qq_34886352/article/details/103581973

#搜索
yum search keepalived
#安裝
yum -y install keepalived.x86_64

修改keepalived配置文件

vim /etc/keepalived/keepalived.conf

註釋掉vrrp_strict

#vrrp_strict

配置master節點

這裏添加一個監聽haproxy進程的腳本
vrrp_script chk_happroxy{
    #檢測使用的語句  不存在返回1  存在返回0
    script "killall -0 haproxy"
    #兩秒檢測一次
    interval 2
}

#多餘的vrrp_instance刪除掉
vrrp_instance VI_1{
    state MASTER
    #網卡 這個需要自己查一下自己的網卡,推薦的文章裏面有說明
    interface etc33
    ...(這些都不用改)
    virtual_ipaddress{
        192.168.85.20
    }
    #添加監聽
    track_script{
        chk_haproxy
    }
}

#多餘的virtual_server刪除掉
virtual_server 192.168.85.20 6000{
    ...(這些都不用改)
    #對應的真實的主機的地址
    real_server 192.168.85.210 5000{
        weight 1
        TCP_CHECK{
            connect_port 5000
            connect_timeout 10000
        }
    }
}

配置slave節點

這裏添加一個監聽haproxy進程的腳本
vrrp_script chk_happroxy{
    #檢測使用的語句  不存在返回1  存在返回0
    script "killall -0 haproxy"
    #兩秒檢測一次
    interval 2
}

#多餘的vrrp_instance刪除掉
vrrp_instance VI_1{
    state SLAVE
    #網卡 這個需要自己查一下自己的網卡,推薦的文章裏面有說明
    interface etc33
    ...(這些都不用改)
    virtual_ipaddress{
        192.168.85.20
    }
    #添加監聽
    track_script{
        chk_haproxy
    }
}

#多餘的virtual_server刪除掉
virtual_server 192.168.85.20 6000{
    ...(這些都不用改)
    #對應的真實的主機的地址
    real_server 192.168.85.211 5000{
        weight 1
        TCP_CHECK{
            connect_port 5000
            connect_timeout 10000
        }
    }
}

啓動keepalived

keepalived -f /ect/keepalived/keepalived.conf
#或者
service keepalived start
(4)使用Navicat連接keepalived的虛擬ip

直接創建一個mysql的連接
連接地址:192.168.85.20(keepalivd的虛擬ip)
端口:6000(keepalived的監聽端口)
用戶名:root(用戶名密碼都配置在mycat的server.xml中)
密碼:123456

四、基於Sharding-JDBC的讀寫分離和分庫分表

官方文檔:https://shardingsphere.apache.org/document/current/cn/quick-start/sharding-jdbc-quick-start/

Sharding-JDBC是ShardingSphere的第一個產品,也是ShardingSphere的前身。 它定位爲輕量級Java框架,在Java的JDBC層提供的額外服務。它使用客戶端直連數據庫,以jar包形式提供服務,無需額外部署和依賴,可理解爲增強版的JDBC驅動,完全兼容JDBC和各種ORM框架。

每個庫都創建2個t_order表,分別叫做t_order_1和t_order_2
t_order表:

字段 中文解釋
order_id 訂單id
total_amount 價格
order_status 訂單狀態
user_id 用戶id

1、Spring整合sharding-jdbc

(1)引入maven依賴
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-namespace</artifactId>
    <version>4.0.0-RC2</version>
</dependency>
(2)springxml的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:sharding="http://shardingsphere.apache.org/schema/shardingsphere/sharding"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://shardingsphere.apache.org/schema/shardingsphere/sharding
                        http://shardingsphere.apache.org/schema/shardingsphere/sharding/sharding.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    <!-- 添加數據源 -->
    <bean id="ds0" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
        <!-- 數據庫驅動 -->
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
        <property name="username" value="用戶名"/>
        <property name="password" value="密碼"/>
        <property name="jdbcUrl" value="jdbc:mysql://192.168.85.200:3306/sharding_order?serverTimezone=Asia/Shanghai&amp;useSSL=false"/>
    </bean>
    
    <!-- 第二個數據源 -->
    <bean id="ds1" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
        <!-- 數據庫驅動 -->
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
        <property name="username" value="用戶名"/>
        <property name="password" value="密碼"/>
        <property name="jdbcUrl" value="jdbc:mysql://192.168.85.201:3306/sharding_order?serverTimezone=Asia/Shanghai&amp;useSSL=false"/>
    </bean>
    
    <!-- 配置sharding-jdbc -->
    <sharding:data-source id="sharding-data-source">
        <!-- 配置數據源 -->
        <sharding:sharding-rule data-source-name="ds0,ds1">
            <sharding:table-rules>
                <!-- logic-table :分片表的邏輯表名 -->
                <!-- atcual-data-nodes :實際的數據節點   ds$->{0..1}:分爲兩個部分ds是數據源的前綴,$->{0..1}是佔位符,等同於${} -->
                <!--  database-strategy-ref :庫的分片策略 -->
                <!--  table-strategy-ref :表的分片策略 -->
                <sharding:table-rule logic-table="t_order" 
                atcual-data-nodes="ds$->{0..1}.t_order_$->{1..2}"
                database-strategy-ref="databaseStrategy"
                table-strategy-ref="tableStrategy"
                />
            </sharding:table-rules>
        </sharding:sharding-rule>
    </sharding:data-source>
    
    <!-- 數據庫的分片規則 -->
    <!-- sharding-column:分庫使用的字段 -->
    <!-- algorithm-expression:分片規則,對user_id取模 -->
    <sharding:inline-strategy id="databaseStrategy" sharding-column="user_id" algorithm-expression="ds$->{user_id%2}"/>
    </beans>
    
    <!-- 表的分片規則 -->
    <sharding:inline-strategy id="tableStrategy" sharding-column="id" algorithm-expression="t_order_$->{id%2+1}"/>
    
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="sharding-data-source"/>
        <property name="mapperLocations" value="classpath*:/mybatis/*.xml"/>
    </bean>
</beans>
(3)mybatis的注意事項
  • mybatis的xml文件裏的表需要使用邏輯表名
  • @MapperScan不要忘記加了,不知道的回頭看看mybatis的配置
  • 和正常使用mybatis一樣就行了,會自動的去識別分庫分表

2、SpringBoot整合sharding-jdbc

(1)引入maven依賴
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.0.0-RC2</version>
</dependency>
(2)application.properties配置
spring.shardingsphere.datasource.names=ds0,ds1

spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds0.jdbcUrl=jdbc:mysql://192.168.85.200:3306/sharding_order?serverTimezone=Asia/Shanghai&amp;useSSL=false
spring.shardingsphere.datasource.ds0.username=
spring.shardingsphere.datasource.ds0.password=

spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds1.jdbcUrl=jdbc:mysql://192.168.85.201:3306/sharding_order?serverTimezone=Asia/Shanghai&amp;useSSL=false
spring.shardingsphere.datasource.ds1.username=
spring.shardingsphere.datasource.ds1.password=

spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds$->{0..1}.t_order_$->{1..2}
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression=ds$->{user_id%2}

spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{id % 2+1}

mybatis.mapper-locations=/mybatis/*.xml
logging.pattern.dateformat=HH:mm:ss

3、廣播表(全局表)配置

(1)創建表

所有數據庫都創建一個地址表

字段 中文解釋
id id
name 地區名
(2)設置廣播表

spring修改xml文件

    <!-- 配置sharding-jdbc -->
    <sharding:data-source id="sharding-data-source">
        <!-- 配置數據源 -->
        <sharding:sharding-rule data-source-name="ds0,ds1">
            <sharding:table-rules>
                <!-- logic-table :分片表的邏輯表名 -->
                <!-- atcual-data-nodes :實際的數據節點   ds$->{0..1}:分爲兩個部分ds是數據源的前綴,$->{0..1}是佔位符,等同於${} -->
                <!--  database-strategy-ref :庫的分片策略 -->
                <!--  table-strategy-ref :表的分片策略 -->
                <sharding:table-rule logic-table="t_order" 
                atcual-data-nodes="ds$->{0..1}.t_order_$->{1..2}"
                database-strategy-ref="databaseStrategy"
                table-strategy-ref="tableStrategy"
                />
            </sharding:table-rules>
            
            <!-- 這裏就是廣播表的配置 -->
            <sharding:broadcast-table-rules>
                <sharding:broadcast-table-rule table="area"/>
            </sharding:broadcast-table-rules>
        </sharding:sharding-rule>
    </sharding:data-source>

springboot,修改application.properties配置

# 添加廣播表配置
spring.shardingsphere.sharding.broadcast-tables=area

這樣在插入和修改的時候,就會同時更新所有庫中的這張表,也可以進行join查詢了

4、綁定表(父子表)配置

(1)創建表

所有數據庫都創建2個t_order_item表,分別叫做t_order_item_1和t_order_item_2

字段 中文解釋
id id
order_id 訂單表id
pruduct_name 商品名
user_id 用戶id
(2)設置綁定表

spring修改xml文件

    <!-- 配置sharding-jdbc -->
    <sharding:data-source id="sharding-data-source">
        <!-- 配置數據源 -->
        <sharding:sharding-rule data-source-name="ds0,ds1">
            <sharding:table-rules>
                <!-- logic-table :分片表的邏輯表名 -->
                <!-- atcual-data-nodes :實際的數據節點   ds$->{0..1}:分爲兩個部分ds是數據源的前綴,$->{0..1}是佔位符,等同於${} -->
                <!--  database-strategy-ref :庫的分片策略 -->
                <!--  table-strategy-ref :表的分片策略 -->
                <sharding:table-rule logic-table="t_order" 
                atcual-data-nodes="ds$->{0..1}.t_order_$->{1..2}"
                database-strategy-ref="databaseStrategy"
                table-strategy-ref="tableStrategy"
                />
            </sharding:table-rules>
            
            <!-- 這裏就是廣播表的配置 -->
            <sharding:broadcast-table-rules>
                <sharding:broadcast-table-rule table="area"/>
            </sharding:broadcast-table-rules>
            
            <!-- 這裏就是綁定表的配置 ,與mycat不同,sharding-jdbc 不需要指定,關聯關係的字段,是通過兩種表之間相同的字段進行關聯的-->
            <sharding:binding-table-rules>
                <sharding:binding-table-rule logic-tables="t_order,t_order_item"/>
            </sharding:binding-table-rules>
        </sharding:sharding-rule>
    </sharding:data-source>

這裏可能會有個bug,會提示廣播表爲空,主要原因是因爲在初始化幫點表的時候,會檢測是否同時是廣播表,但是廣播表尚未初始化,就會拋出空指針
如果以後問題解決,這裏我再補上

5、讀寫分離

(1)springxml的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:sharding="http://shardingsphere.apache.org/schema/shardingsphere/sharding"
       xmlns:master-slave="http://shardingsphere.apache.org/schema/shardingsphere/masterslave"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://shardingsphere.apache.org/schema/shardingsphere/sharding
                        http://shardingsphere.apache.org/schema/shardingsphere/sharding/sharding.xsd
                        http://shardingsphere.apache.org/schema/shardingsphere/masterslave
                        http://shardingsphere.apache.org/schema/shardingsphere/masterslave/master-slave.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context.xsd
                        http://www.springframework.org/schema/tx
                        http://www.springframework.org/schema/tx/spring-tx.xsd">
    
    <!-- 添加數據源 -->
    <bean id="ds0" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
        <!-- 數據庫驅動 -->
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
        <property name="username" value="用戶名"/>
        <property name="password" value="密碼"/>
        <property name="jdbcUrl" value="jdbc:mysql://192.168.85.200:3306/sharding_order?serverTimezone=Asia/Shanghai&amp;useSSL=false"/>
    </bean>
    
    <!-- 添加一個從數據源 -->
    <bean id="slave0" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
        <!-- 數據庫驅動 -->
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
        <property name="username" value="用戶名"/>
        <property name="password" value="密碼"/>
        <property name="jdbcUrl" value="jdbc:mysql://192.168.85.203:3306/sharding_order?serverTimezone=Asia/Shanghai&amp;useSSL=false"/>
    </bean>
    
    <!-- 第二個數據源 -->
    <bean id="ms1" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
        <!-- 數據庫驅動 -->
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
        <property name="username" value="用戶名"/>
        <property name="password" value="密碼"/>
        <property name="jdbcUrl" value="jdbc:mysql://192.168.85.201:3306/sharding_order?serverTimezone=Asia/Shanghai&amp;useSSL=false"/>
    </bean>
    
    <!-- 主從的讀寫規則  random:在所有的從庫中隨機查詢-->
    <master-slave:load-balance-algorithm id="msStrategy" type="random">
    
    <!-- 配置sharding-jdbc -->
    <sharding:data-source id="sharding-data-source">
        <!-- 配置數據源 -->
        <sharding:sharding-rule data-source-name="ds0,slave0,ds1">
            <!-- 主從配置 -->
            <sharding:master-slave-rules>
                <sharding:master-slave-rule id="ms0" master-data-source-name="ds0" slave-data-source-names="slave0" strategy-ref="msStrategy"/>
            </sharding:master-slave-rules>
            <sharding:table-rules>
                <sharding:table-rule logic-table="t_order" 
                atcual-data-nodes="ms$->{0..1}.t_order_$->{1..2}"
                database-strategy-ref="databaseStrategy"
                table-strategy-ref="tableStrategy"
                />
            </sharding:table-rules>
        </sharding:sharding-rule>
    </sharding:data-source>
    
    <!-- 數據庫的分片規則 -->
    <!-- sharding-column:分庫使用的字段 -->
    <!-- algorithm-expression:分片規則,對user_id取模 -->
    <sharding:inline-strategy id="databaseStrategy" sharding-column="user_id" algorithm-expression="ms$->{user_id%2}"/>
    </beans>
    
    <!-- 表的分片規則 -->
    <sharding:inline-strategy id="tableStrategy" sharding-column="id" algorithm-expression="t_order_$->{id%2+1}"/>
    
    <bean class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="sharding-data-source"/>
        <property name="mapperLocations" value="classpath*:/mybatis/*.xml"/>
    </bean>
</beans>
(2)springboot,修改application.properties配置
spring.shardingsphere.datasource.names=ds0,ms1,slave0

spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds0.jdbcUrl=jdbc:mysql://192.168.85.200:3306/sharding_order?serverTimezone=Asia/Shanghai&amp;useSSL=false
spring.shardingsphere.datasource.ds0.username=
spring.shardingsphere.datasource.ds0.password=

spring.shardingsphere.datasource.slave0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave0.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.slave0.jdbcUrl=jdbc:mysql://192.168.85.203:3306/sharding_order?serverTimezone=Asia/Shanghai&amp;useSSL=false
spring.shardingsphere.datasource.slave0.username=
spring.shardingsphere.datasource.slave0.password=

spring.shardingsphere.datasource.ms1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ms1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ms1.jdbcUrl=jdbc:mysql://192.168.85.201:3306/sharding_order?serverTimezone=Asia/Shanghai&amp;useSSL=false
spring.shardingsphere.datasource.ms1.username=
spring.shardingsphere.datasource.ms1.password=

spring.shardingsphere.sharding.master-slave-rules.ms0.master-data-source-name=ds0
spring.shardingsphere.sharding.master-slave-rules.ms0.slave-data-source-name=slave0
spring.shardingsphere.sharding.master-slave-rules.ms0.load-balance.algorithm-type=RANDOM

spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ms$->{0..1}.t_order_$->{1..2}
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression=ms$->{user_id%2}

spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{id % 2+1}

mybatis.mapper-locations=/mybatis/*.xml
logging.pattern.dateformat=HH:mm:ss
(3)配置完成之後,其他東西都是自動的,正常使用mybatis就可以了
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章