參考資料:猿天地 https://mp.weixin.qq.com/s/kp2lJHpTMz4bDWkJYjVbOQ 作者:尹吉歡
技術選型:SpringBoot + Sharding-JDBC + MyBatis
使用Sharding-JDBC配置讀寫分離,優點在於數據源完全有Sharding托管,寫操作自動執行master庫,讀操作自動執行slave庫。不需要程序員在程序中關注這個實現了。
1. 核心jar包
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- sharding --> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.0.0-RC1</version> </dependency> <!-- mybatis-plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.2.0</version> </dependency> <!--阿里數據庫連接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.14</version> </dependency> <!-- mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.18</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.60</version> </dependency> </dependencies>
2. yml文件配置
spring:
main:
allow-bean-definition-overriding: true
shardingsphere:
datasource:
names:
master,slave
# 主數據源
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db_master?characterEncoding=utf-8
username: ****
password: ****
# 從數據源
slave:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db_slave?characterEncoding=utf-8
username: ****
password: ****
masterslave:
# 讀寫分離配置
load-balance-algorithm-type: round_robin
# 最終的數據源名稱
name: dataSource
# 主庫數據源名稱
master-data-source-name: master
# 從庫數據源名稱列表,多個逗號分隔
slave-data-source-names: slave
props:
# 開啟SQL顯示,默認false
sql:
show: true
參數解讀:
load-balance-algorithm-type 用於配置從庫負載均衡算法類型,可選值:ROUND_ROBIN(輪詢),RANDOM(隨機)
props.sql.show=true 在執行SQL時,會打印SQL,並顯示執行庫的名稱
3. 項目啟動測試
看到下面日志就說明配置成功了
2019-12-17 16:12:16.004 INFO 19164 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-1} inited
2019-12-17 16:12:17.458 INFO 19164 --- [ main] com.alibaba.druid.pool.DruidDataSource : {dataSource-2} inited
執行SQL時,會打印一下日志:
[ main] ShardingSphere-SQL : Rule Type: master-slave
[ main] ShardingSphere-SQL : SQL: SELECT id,address,gender,username FROM user_info ::: DataSources: slave
4. 相關問題
讀寫分離架構中經常出現,那就是讀延遲的問題如何解決?
剛插入一條數據,然后馬上就要去讀取,這個時候有可能會讀取不到?歸根到底是因為主節點寫入完之后數據是要復制給從節點的,讀不到的原因是復制的時間比較長,也就是說數據還沒復制到從節點,你就已經去從節點讀取了,肯定讀不到。mysql5.7 的主從復制是多線程了,意味着速度會變快,但是不一定能保證百分百馬上讀取到,這個問題我們可以有兩種方式解決:
(1)業務層面妥協,是否操作完之后馬上要進行讀取
(2)對於操作完馬上要讀出來的,且業務上不能妥協的,我們可以對於這類的讀取直接走主庫,當然Sharding-JDBC也是考慮到這個問題的存在,所以給我們提供了一個功能,可以讓用戶在使用的時候指定要不要走主庫進行讀取。在讀取前使用下面的方式進行設置就可以了:
public List<UserInfo> getList() { // 強制路由主庫 HintManager.getInstance().setMasterRouteOnly(); return this.list(); }