謝謝 https://www.cnblogs.com/huanshilang/p/12055296.html
技術選型:SpringBoot + Sharding-JDBC + MyBatis
使用Sharding-JDBC配置讀寫分離,優點在於數據源完全有Sharding託管,寫操作自動執行master庫,讀操作自動執行slave庫。不需要程序員在程序中關注這個實現了。
1. 核心jar包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dalaoyang</groupId>
<artifactId>springboot2_shardingjdbc_dxfl</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot2_shardingjdbc_dxfl</name>
<description>springboot2_shardingjdbc_dxfl</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.RELEASE</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- MySQL 連接驅動依賴 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- <dependency> <groupId> com.alibaba </groupId> <artifactId> druid-spring-boot-starter
</artifactId> <version> 1.1.10 </version> </dependency> -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<!-- jasper -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.44</version>
<scope>compile</scope>
</dependency>
<!-- springboot整合 redis -->
<!-- Dom4j 依賴包 -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<!-- sharding -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.0-RC1</version>
</dependency>
</dependencies>
<build>
<finalName>springboot2_shardingjdbc_dxfl</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2. yml文件配置
server:
port: 8084
spring:
main:
allow-bean-definition-overriding: true
shardingsphere:
datasource:
names:
master,slave
# 主數據源
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://106.44.600:3306/test_2?characterEncoding=utf-8
username: root
password: "123123
slave: # 從數據源
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://106.44.600:3307/test_2?characterEncoding=utf-8
username: root
password: "123123
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
mybatis:
mapper-locations: "classpath:mapper/*.xml" # mapper映射文件
type-aliases-package: "com.dalaoyang.mapper/*" # 別名類所在包
configuration:
call-setters-on-nulls: 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();
}