聊聊 Sharding-JDBC 實(shí)現(xiàn) 讀寫分離~
今天聊一下如何通過Sharding-JDBC簡單的實(shí)現(xiàn)讀寫分離~
為什么要讀寫分離?
讀寫分離則是將事務(wù)性的增、改、刪操作在主庫執(zhí)行,查詢操作在從庫執(zhí)行。
一般業(yè)務(wù)的寫操作都是比較耗時(shí),為了避免寫操作影響查詢的效率,可以使用讀寫分離。
當(dāng)然讀寫分離并不是萬能的,還有前面的分庫分表方案。
讀寫分離如何搭建?
MySQL搭建讀寫分離非常簡單,一般有一主一從、一主多從,對(duì)于MySQL的主從的相關(guān)概念這里就不再詳細(xì)介紹了。
下面陳某就以MySQL5.7為例,使用docker搭建一個(gè)一主一從的架構(gòu),步驟如下:
1. pull鏡像
使用如下命令從鏡像倉庫中下載鏡像:
docker pull mysql:5.7.26
2. 創(chuàng)建目錄
MySQL數(shù)據(jù)和配置文件掛載的目錄:
mkdir -p /usr/local/mysqlData/master/cnf
mkdir -p /usr/local/mysqlData/master/data
mkdir -p /usr/local/mysqlData/slave/cnf
mkdir -p /usr/local/mysqlData/slave/data
3. 編寫配置master節(jié)點(diǎn)配置
修改MySQL主節(jié)點(diǎn)的配置文件,內(nèi)容如下:
vim /usr/local/mysqlData/master/cnf/mysql.cnf
[mysqld]
## 設(shè)置server_id,注意要唯一
server-id=1
## 開啟binlog
log-bin=mysql-bin
## binlog緩存
binlog_cache_size=1M
## binlog格式(mixed、statement、row,默認(rèn)格式是statement)
binlog_format=mixed
4. 編寫配置slave節(jié)點(diǎn)配置
修改MySQL從節(jié)點(diǎn)的配置文件,內(nèi)容如下:
vim /usr/local/mysqlData/slave/cnf/mysql.cnf
[mysqld]
## 設(shè)置server_id,注意要唯一
server-id=2
## 開啟binlog,以備Slave作為其它Slave的Master時(shí)使用
log-bin=mysql-slave-bin
## relay_log配置中繼日志
relay_log=edu-mysql-relay-bin
## 如果需要同步函數(shù)或者存儲(chǔ)過程
log_bin_trust_function_creators=true
## binlog緩存
binlog_cache_size=1M
## binlog格式(mixed、statement、row,默認(rèn)格式是statement)
binlog_format=mixed
## 跳過主從復(fù)制中遇到的所有錯(cuò)誤或指定類型的錯(cuò)誤,避免slave端復(fù)制中斷
## 如:1062錯(cuò)誤是指一些主鍵重復(fù),1032錯(cuò)誤是因?yàn)橹鲝臄?shù)據(jù)庫數(shù)據(jù)不一致
slave_skip_errors=1062
5. 啟動(dòng)MySQL主節(jié)點(diǎn)
命令如下:
docker run -itd -p 3306:3306 --name master -v /usr/local/mysqlData/master/cnf:/etc/mysql/conf.d -v /usr/local/mysqlData/master/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.26
6. 添加復(fù)制master數(shù)據(jù)的用戶reader,供從服務(wù)器使用
命令如下:
[root@aliyun /]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6af1df686fff mysql:5.7 "docker-entrypoint..." 5 seconds ago Up 4 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp master
[root@aliyun /]# docker exec -it master /bin/bash
root@41d795785db1:/# mysql -u root -p123456
mysql> GRANT REPLICATION SLAVE ON *.* to 'reader'@'%' identified by 'reader';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)
7. 創(chuàng)建并運(yùn)行mysql從服務(wù)器
命令如下:
docker run -itd -p 3307:3306 --name slaver -v /usr/local/mysqlData/slave/cnf:/etc/mysql/conf.d -v /usr/local/mysqlData/slave/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7.26
8. 在從服務(wù)器上配置連接主服務(wù)器的信息
首先主服務(wù)器上查看master_log_file、master_log_pos兩個(gè)參數(shù),然后切換到從服務(wù)器上進(jìn)行主服務(wù)器的連接信息的設(shè)置。
主服務(wù)上執(zhí)行:
root@6af1df686fff:/# mysql -u root -p123456
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 591 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
docker查看主服務(wù)器容器的ip地址:
[root@aliyun /]# docker inspect --format='{{.NetworkSettings.IPAddress}}' master
172.17.0.2
從服務(wù)器上執(zhí)行:
[root@aliyun /]# docker exec -it slaver /bin/bash
root@fe8b6fc2f1ca:/# mysql -u root -p123456
mysql> change master to master_host='172.17.0.2',master_user='reader',master_password='reader',master_log_file='mysql-bin.000003',master_log_pos=591;
9. 從服務(wù)器啟動(dòng)I/O 線程和SQL線程
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.17.0.2
Master_User: reader
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 591
Relay_Log_File: edu-mysql-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Slave_IO_Running: Yes,Slave_SQL_Running: Yes即表示啟動(dòng)成功。
Sharding-JDBC 實(shí)現(xiàn)讀寫分離
上面使用Docker搭建了一個(gè)MySQL的一主一從的架構(gòu),如下:
| ip:port | 節(jié)點(diǎn) | 數(shù)據(jù)庫 |
|---|---|---|
| 192.168.47.149:3306 | 主節(jié)點(diǎn) | product_db_1 |
| 192.168.47.149:3307 | 從節(jié)點(diǎn) | product_db_1 |
Sharding-JDBC對(duì)于讀寫分離的配置非常簡單,分為如下幾個(gè)步驟:
“關(guān)于數(shù)據(jù)庫中的表的SQL就不再貼了,文末有案例源碼,自己下載!
”
1. 數(shù)據(jù)源配置
無論是分庫分表還是讀寫分離,數(shù)據(jù)源的聲明肯定是必須的,如下:
spring:
# Sharding-JDBC的配置
shardingsphere:
datasource:
# 數(shù)據(jù)源,這里配置兩個(gè),分別是ds1,ds2
names: ds1,ds2
# 主庫
ds1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.47.149:3306/product_db1?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
# 從庫
ds2:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.47.149:3307/product_db1?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
“源碼已經(jīng)上傳GitHub,關(guān)注公眾號(hào):碼猿技術(shù)專欄,回復(fù)關(guān)鍵詞:9537 獲取
”
2. 主從節(jié)點(diǎn)配置
第①步僅僅配置了數(shù)據(jù)源,并未指定哪個(gè)是主庫,哪個(gè)是從庫,Sharding-JDBC 默認(rèn)是不知道哪個(gè)主庫還是從庫的,因此需要自己配置。
配置規(guī)則如下:
#主庫數(shù)據(jù)源名稱,名稱隨意
spring.shardingsphere.masterslave.<master-slave-data-source-name>.master-data-source-name=
#從庫數(shù)據(jù)源名稱列表
spring.shardingsphere.masterslave.<master-slave-data-source-name>.slave-data-source-names[0]=
#從庫數(shù)據(jù)源名稱列表
spring.shardingsphere.masterslave.<master-slave-data-source-name>.slave-data-source-names[1]=
#從庫負(fù)載均衡算法類名稱。該類需實(shí)現(xiàn)MasterSlaveLoadBalanceAlgorithm接口且提供無參數(shù)構(gòu)造器
spring.shardingsphere.masterslave.<master-slave-data-source-name>.load-balance-algorithm-class-name=
#從庫負(fù)載均衡算法類型,可選值:ROUND_ROBIN,RANDOM。若`load-balance-algorithm-class-name`存在則忽略該配置
spring.shardingsphere.masterslave.<master-slave-data-source-name>.load-balance-algorithm-type=
這里的<master-slave-data-source-name>一定要注意,這個(gè)是主從配置的名稱(相當(dāng)于邏輯數(shù)據(jù)源),名稱可以隨意,但是一定要唯一。
陳某的配置如下:
spring:
# Sharding-JDBC的配置
shardingsphere:
# 主從節(jié)點(diǎn)配置
masterslave:
# 從庫負(fù)載均衡算法,內(nèi)置兩個(gè)值:RANDOM、ROUND_ROBIN
load-balance-algorithm-type: round_robin
# 主從的名稱,隨意,但是要保證唯一
name: ms
# 指定主數(shù)據(jù)源
master-data-source-name: ds1
# 指定從數(shù)據(jù)源
slave-data-source-names:
- ds2
指定的邏輯數(shù)據(jù)源為ms,主庫為ds1,從庫為ds2。
“”
load-balance-algorithm-type:指定從庫的負(fù)載均衡算法,后面文章介紹
3. 測試
經(jīng)過上面兩步的配置,Sharding-JDBC的讀寫分離已經(jīng)配置成功,下面來測試一下。
理想效果:
-
寫操作:任何的寫操作都應(yīng)該在主庫數(shù)據(jù)源ds1中執(zhí)行 -
讀操作:任何的讀操作都應(yīng)該在從庫數(shù)據(jù)源ds2中執(zhí)行
1、寫操作
直接insert插入一條數(shù)據(jù),查看Sharding-JDBC的日志,如下:
“可以看到都在ds1中執(zhí)行了
”
2、讀操作
根據(jù)商品ID查詢一條數(shù)據(jù),效果如下:
“可以看到都在ds2中執(zhí)行了
”
總結(jié)
本篇文章介紹了MySQL的讀寫分離架構(gòu)搭建以及使用Sharding-JDBC去實(shí)現(xiàn)程序中無感知使用讀寫分離。
關(guān)于讀寫分離還有一些內(nèi)容未介紹,將會(huì)放在后面文章詳細(xì)介紹。
