【MySQL】Spring Boot项目基于Sharding-JDBC和MySQL主从复制实现读写分离(8千字详细教程)
目錄
- 前言
- 一、 介紹
- 二、 主從復制
- 1. 原理
- 2. 克隆從機
- 3. 克隆從機大坑
- 4. 遠程登陸
- 5. 主機配置
- 6. 從機配置
- 7. 主機:建立賬戶并授權
- 8. 從機:配置需要復制的主機
- 9. 測試
- 10. 停止主從同步
- 三、 讀寫分離
- 1. Sharding-JDBC介紹
- 2. 一主一從
- 3. 一主一從讀寫分離
- 3.1 實現步驟
- 3.2 配置讀寫分離規則
- 3.3 允許bean定義覆蓋配置項
- 3.4 啟動項目測試
前言
- 本篇文章將手把手教你如何在 Linux 虛擬機上搭建 MySQL 一主一從的數據庫架構,教你如何實現 MySQL 主從復制,再到手把手教你如何在 Spring Boot 項目上使用 Sharding-JDBC 框架實現讀寫分離。
- 筆者開發環境介紹:
- Linux 系統:Centos 7
- 虛擬機:VMware 16
- MySQL :8.0.31
- 如果還沒安裝 VMware 虛擬機軟件和 CentOS 7 的小伙伴可以移步到我的這篇博文進行學習——《Linux系統CentOS7虛擬機VMware安裝保姆級教程》。
- 如果不知道在 CentOS 7 如何安裝 MySQL 的小伙伴可以移步到我的這篇博文進行學習——《Linux下如何安裝MySQL以及遠程登錄保姆級教程》。
一、 介紹
-
面對日益增加的系統訪問量,數據庫的吞吐量面臨著巨大瓶頸。對于同一時刻有大量并發讀操作和較少寫操作類型的應用系統來說,將數據庫拆分為主庫和從庫,主庫負責處理事務性的增刪改操作,從庫負責處理查詢操作,能夠有效的避免由數據更新導致的行級鎖,使得整個系統的查詢性能得到極大的改善。這就稱為讀寫分離。
二、 主從復制
1. 原理
- MySQL 主從復制是一個異步的復制過程,底層是基于 MySQL 數據庫自帶的二進制日志 (Binlog) 功能。就是一臺或多臺 MySQL 數據庫 (slave,即從庫) 從另一臺 MySQL 數據庫 (master,即主庫) 進行日志的復制然后再解析日志并應用到自身,最終實現從庫的數據和主庫的數據保持一致。MySQL 主從復制是 MySQL 數據庫自帶功能,無需借助第三方工具。
- MySQL 復制過程分成三步:
- master 將改變記錄到二進制日志 (binary log) ;
- slave 將 master 的 binary log 拷貝到它的中繼日志 (relay log) ;
- slave 重做中繼日志中的事件,將改變應用到自己的數據庫中。
2. 克隆從機
-
首先要準備兩臺 Linux 虛擬機,筆者已經安裝過一臺虛擬機作為主機,IP 地址為 192.168.148.100 (server100) ,現在我們通過 VMware 軟件的 “克隆” 功能來克隆出第二臺 Linux 虛擬機作為從機,IP 地址設置為 192.168.148.101 。
-
首先關閉 server100 :
-
然后左側右擊 server100 –> 管理 –> 克隆:
-
點擊 “下一頁” :
-
保持默認,下一頁:
-
選擇 “創建完整克隆” ,點擊下一頁:
-
改名、改存放路徑:
-
開始克隆:
-
克隆完成:
-
克隆完成后,要修改四個位置。第一個是網絡,雙擊 server101 的網絡適配器:
-
點擊 “高級” :
-
點擊 “生成” 來修改 MAC 地址,確保兩臺虛擬機的 MAC 地址不同:
-
然后,開機 server101 ,登錄 root 用戶:
-
修改主機名稱。命令如下:
vim /etc/hostname記得 :wq 保存退出。
-
重命名后需要重啟:
reboot -
重啟完再以 root 用戶登錄,下一步是更改 IP 地址:
vim /etc/sysconfig/network-scripts/ifcfg-ens33 -
改兩個地方,一個是 UUID ,確保和 server100 不同即可;另一個是 IPADDR ,我修改為 192.168.148.101 。
修改好后按 :wq 保存退出。
-
然后重啟網絡:
systemctl restart network -
這樣,一臺虛擬機就克隆完成了。重要的是,里面曾經安裝的 JDK、MySQL、Redis 等軟件和數據都是跟 server100 保持一致的。這就省去了我們重復安裝和配置的麻煩了。
3. 克隆從機大坑
-
克隆的方式生成的虛擬機 (包含 MySQL Server),則克隆的虛擬機 MySQL Server 的 UUID 相同 (此 UUID 是 MySQL 服務的 UUID,和前面修改的 Linux 網絡配置的 UUID 不是同一個東西) ,必須修改,否則在有些場景會報錯。比如: show slave status\G ,報如下的錯誤:
Last_IO_Error: Fatal error: The slave I/0 thread stops because master and slave have equal MySQL server UUIDs; these UUIDS must be different for replication to work. -
解決方法:
修改 MySQL Server 的 UUID 方式:
vim /var/lib/mysql/auto.cnf自己隨便改,與 server 100 不同即可。
-
然后,重啟 MySQL 服務即可:
systemctl restart mysqld
4. 遠程登陸
-
筆者采用 MobaXTerm 遠程登陸:
-
新建連接:
-
成功遠程連接:
-
此時,server100 也可以開機了:
-
server100 作為主機、server101 作為從機,一主一從實現讀寫分離。
-
SQLyog 遠程登錄 - 教程詳見我的這篇博文的第 4 章《4. SQLyog遠程連接》。
5. 主機配置
-
建議 MySQL 版本一致且后臺以服務運行,主從所有配置項都配置在[mysqld] 節點下,且都是小寫字母。具體參數配置如下:
-
必選:
# [必須]主服務器唯一ID server-id=100# [必須]啟用二進制日志,指名路徑。比如:自己本地的路徑/log/mysqlbin log-bin=ouc-bin -
可選:
# [可選] 0(默認)表示可讀可寫(主機),1表示只讀(從機) read-only=0# 設置日志文件保留的時長,單位是秒 binlog_expire_logs_seconds=6000# 控制單個二進制日志大小。此參數的最大和默認值是1GB max_binlog_size=200M# [可選]設置不要復制的數據庫 binlog-ignore-db=test# [可選]設置需要復制的數據庫,默認全部記錄。比如: binlog-do-db=atguigu_master_slave binlog-do-db=需要復制的主數據庫名字# [可選]設置binlog格式 binlog_format=STATEMENT -
重啟后臺 MySQL 服務,使配置生效。
【注意】
- 先搭建完主從復制,再創建數據庫。MySQL 主從復制起始時,從機不繼承主機數據。
-
進入主機 server100 ,輸入以下命令進入 biglog 配置文件:
vim /etc/my.cnf -
在第 3 行左右,修改成如下的樣子:
按 :wq 保存并退出。
-
然后重啟 MySQL 服務:
systemctl restart mysqld
6. 從機配置
-
從機 server101 也如法炮制。
-
要求主從所有配置項都配置在 /etc/my.cnf 的 [mysqld] 欄位下,且都是小寫字母。
-
必選:
[mysqld] # [必須]從服務器唯一ID,要與主服務器不同 server-id=101 -
可選:
# [可選]啟用中繼日志 relay-log=mysql-relay -
重啟后臺 mysql 服務,使配置生效。
systemctl restart mysqld
【注意】
- 主、從機都要開放 MySQL 端口號 3306 的防火墻。
7. 主機:建立賬戶并授權
-
如果你使用的是 MySQL 5.7 ,只需執行下面一條指令即可:
-- MySQL 5.7專用 GRANT REPLICATION SLAVE ON *.* TO 'slave101'@'從機器數據庫IP' IDENTIFIED BY 'xsh981104';其中,‘slave101’ 是你自己起的從機名稱。
-
注意,筆者使用的是 MySQL 8.0 ,在主機端進入 MySQL root 用戶,輸入以下命令創建名為 slave101 的賬戶,用于主機和從機之間的通信:
mysql> CREATE USER 'slave101'@'%' IDENTIFIED BY 'xsh981104'; -
我創建的時候報了一個錯誤:
ERROR 1396 (HY000): Operation CREATE USER failed for 'slave101'@'%' -
原因是這個用戶之前創建過,但刪除了,沒有刷新權限。解決方法是先刪除這個用戶,然后再刷新權限,再次創建即可。
-- 刪除用戶 DROP USER 'slave101';-- 刷新權限 FLUSH PRIVILEGES;-- 再次創建用戶 CREATE USER 'slave101'@'%' IDENTIFIED BY 'xsh981104'; -
成功創建用戶 slave101 :
-
然后,賦予用戶 slave101 權限:
GRANT REPLICATION SLAVE ON *.* TO 'slave101'@'%';其中,REPLICATION 指的是主從復制的權限、*.* 表示任何數據庫下的任何表、'slave101'@'%' 表示授予權限的用戶。
-
授權后,可以用下面的命令來查看用戶 slave101 擁有的所有權限:
SHOW GRANTS FOR 'slave101'@'%'; -
然后,如果你是 MySQL 8.0 ,下面的語句必須執行。否則出問題:
ALTER USER 'slave101'@'%' IDENTIFIED WITH mysql_native_password BY 'xsh981104';
【注意】
- 上面這句不執行,從機執行 show slave status\G 時會報下面的錯誤:
Last_IO_Error: error connecting to master ‘slave1@192.168.1.150:3306’ - retry-time: 60 retries: 1 message: Authentication plugin ‘caching_sha2_password’ reported error: Authentication requires secure connection.
-
刷新權限:
FLUSH PRIVILEGES; -
接下來是比較重要的步驟:查詢 Master 的狀態,并記錄下 File 和 Position 的值:
SHOW MASTER STATUS;記錄下 File 和 Position 的值。注意執行完此步驟后不要再操作主服務器,防止主服務器狀態值變化。
-
到這里,主庫的配置就完成了。
8. 從機:配置需要復制的主機
-
步驟1-從機上,進入 MySQL ,開始復制主機:
CHANGE MASTER TO MASTER_HOST='主機的IP地址', MASTER_USER='主機用戶名', MASTER_PASSWORD='主機用戶名的密碼', MASTER_LOG_FILE='ouc-bin.00000X', MASTER_LOG_POS=主機的Position值; -
舉例:
CHANGE MASTER TO MASTER_HOST='192.168.148.100',MASTER_USER='slave101',MASTER_PASSWORD='xsh981104',MASTER_LOG_FILE='ouc-bin.000002',MASTER_LOG_POS=1805; -
步驟2-啟動 slave 同步:
START SLAVE;
-
疑難雜癥 1 - 有的小伙伴在步驟一時遇到類似下面的報錯:
ERROR 3021 (HY000): This operation cannot be performed with a runing slave io thread; run STOP SLAVE IO_THREAD FOR CHANNEL '' first.這是因為從庫之前已經配置過主從復制,必須先停掉原來的:
STOP SLAVE;再重新執行步驟 1 和 2 即可。
-
疑難雜癥 2 - 有的小伙伴還遇到下面的報錯:
ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository這是因為之前你開啟過中繼日志,又關掉了。解決方法是重置一下即可:
RESET SLAVE; -
接著,查看從庫的同步狀態:
SHOW SLAVE STATUS\G; -
這樣,主從復制就搭建完畢了。
9. 測試
-
用 SQLyog 遠程連接至主庫和從庫。
-
在主庫 192.168.148.100 中創建一個新的數據庫 test1 :
CREATE DATABASE IF NOT EXISTS test1 CHARACTER SET 'utf8'; -
使用該數據庫,在該數據庫下創建數據表 students :
CREATE TABLE IF NOT EXISTS students( id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, last_name VARCHAR(15) NOT NULL ); -
在該表下插入數據:
INSERT INTO students(last_name) VALUES('Tom'), ('Amy'); -
查看主庫:
SELECT * FROM students; -
打開從庫 192.168.148.101 ,再沒有任何操作的情況下,發現已經把主庫的數據庫 test1 以及數據表 students 復制過來了:
-
且數據表 students 中的數據也是完全相同的:
SELECT * FROM students; -
說明主從復制搭建成功。
10. 停止主從同步
-
如果你想停止主從同步,只需在從庫輸入下面指令即可:
STOP SLAVE;
三、 讀寫分離
1. Sharding-JDBC介紹
-
Sharding-JDBC 定位為輕量級 Java 框架,在Java的 JDBC 層提供的額外服務。它使用客戶端直連數據庫,以 jar 包形式提供服務,無需額外部署和依賴,可理解為增強版的 JDBC 驅動,完全兼容 JDBC 和各種 ORM 框架。使用 Sharding-JDBC 可以在程序中輕松的實現數據庫讀寫分離。
- 適用于任何基于 JDBC 的 ORM 框架,如: JPA、Hibernate、 Mybatis、Spring JDBC Template 或直接使用 JDBC。
- 支持任何第三方的數據庫連接池,如: DBCP、 C3PO、 BoneCP、Druid、 HikariCP 等。
- 支持任意實現 JDBC 規范的數據庫。目前支持 MySQL、 Oracle、 SQLServer、 PostgreSQL 以及任何遵循 SQL92 標準的數據庫。
-
與 Spring Boot 結合使用時,只需要添加 Maven 依賴坐標即可:
<!-- Sharding-JDBC --> <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.0.1</version> </dependency>
2. 一主一從
-
在實現讀寫分離之前,要把 MySQL 的主從復制的結構搭建好。
-
筆者的主庫 IP 地址為 192.168.148.100 ,從庫 IP 地址為 192.168.148.101 。版本都是 MySQL 8.0.31 。
-
如果你的 MySQL 數據庫安裝在 Windows 電腦上,把 Windows 電腦上的數據庫備份成 .sql 文件,恢復到主庫上即可。不知道的小伙伴可以轉到我的這篇博文中學習——《如何把Windows上的MySQL數據庫遷移到Linux服務器上》。
3. 一主一從讀寫分離
3.1 實現步驟
- 使用 Sharding-JDBC 實現讀寫分離只需要三步:
3.2 配置讀寫分離規則
-
打開 Spring Boot 的配置文件 application.yml 。在 spring: 節點下添加下面的配置:
spring:# 配置Sharding-JDBC讀寫分離規則shardingsphere:# 指定數據源datasource:names:master,slave # 一主一從# 配置主庫數據源master: # 必須跟上面names對應type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.148.100:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: xsh981104# 配置從庫數據源slave: # 必須跟上面names對應type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.148.101:3306/reggie?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: rootpassword: xsh981104# 讀寫分離配置masterslave:load-balance-algorithm-type: round_robin # 多個從庫的負載均衡策略:輪詢name: dataSource # 最終的數據源名稱master-data-source-name: master # 主庫數據源名稱slave-data-source-names: slave # 從庫數據源名稱列表,多個逗號分隔props:sql:show: true # 開啟SQL顯示,默認false -
大家根據自己的主、從庫的 IP 地址和密碼作相應的修改即可。
-
如果有爆紅的情況,那就把 pom.xml 中的 Duird 的 Maven 坐標改成下面即可:
<!-- Druid數據庫連接池 --> <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version> </dependency> -
然后,清除 IDEA 緩存并重啟 IDEA 即可正常啟動 Spring Boot 項目:
3.3 允許bean定義覆蓋配置項
-
為什么要配置這一項呢?是因為 Sharding-JDBC 和 Druid 都會創建一個 DataSource 的 bean ,這樣兩個重名的 bean 就會發生沖突。因此必須在 Spring Boot 配置文件 application.yml 中配置允許 bean 定義覆蓋為 true ,這樣,后定義的 bean 就會覆蓋前面定義的 bean ,從而解決了 bean 沖突的問題。
spring:main:# 允許bean定義覆蓋allow-bean-definition-overriding: true -
這樣,基于 MySQL 主從復制實現讀寫分離就成功實現了。
3.4 啟動項目測試
-
啟動 Spring Boot 項目,可以看到啟動日志里生成了兩個數據源:
-
打開瀏覽器來測試一下,在瀏覽器地址欄輸入你項目的地址,筆者這里是黑馬的《瑞吉外賣》的后臺管理系統。
-
從日志中可以看到,讀取員工表是從 slave 從庫中讀取的:
-
我們來測試一下寫操作,編輯一下員工信息:
-
可以看到,寫操作是主庫 master 操作的:
-
至此,基于 MySQL 主從復制實現讀寫分離就成功開發完畢了!
-
如果你還有任何疑問,歡迎隨時在下方評論或者私信我,我會盡快給大家解答。
總結
以上是生活随笔為你收集整理的【MySQL】Spring Boot项目基于Sharding-JDBC和MySQL主从复制实现读写分离(8千字详细教程)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 服务IP(VIP)的作用
- 下一篇: linux cmake编译源码,linu