ShardingJDBC分庫分表+讀寫分離
準備工作
共四臺Mysql,每臺Mysql有一個user數據庫,每個user庫有3張表(user_tb_0,user_tb_1,user_tb_2),共4*3=12張表,表結構都是一樣的。
兩臺master,兩臺slave。如下圖。slave和master實時同步備份,master是主數據庫(寫操作),slave是從數據庫(讀操作)。
表結構如下:
CREATE TABLE `user_tb_0` (
`id` bigint(20) NOT NULL,
`username` varchar(40) NOT NULL COMMENT '用戶名',
`password` varchar(200) NOT NULL COMMENT '密碼',
`nickname` varchar(100) DEFAULT NULL COMMENT '暱稱',
`money` decimal(16,4) NOT NULL DEFAULT '0.0000' COMMENT '金額',
`is_deleted` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否刪除',
`create_date` datetime NOT NULL COMMENT '創建時間',
`modify_date` datetime NOT NULL COMMENT '更新時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
pom.xml 添加以下依賴
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-namespace</artifactId>
<version>4.0.1</version>
</dependency>
<!--阿里數據庫連接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
<!--分頁-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.10</version>
</dependency>
application.yml配置如下
server:
port: 8001
spring:
# main:
# allow-bean-definition-overriding: true
application:
name: sharding-jdbc-example
shardingsphere:
props:
sql:
show: true
# 數據源配置,可配置多個
datasource:
names: master0,master1,slave0,slave1
master0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3310/user?useUnicode=true&useSSL=false
username: root
password: '123456'
slave0:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3311/user?useUnicode=true&useSSL=false
username: root
password: '123456'
master1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3312/user?useUnicode=true&useSSL=false
username: root
password: '123456'
slave1:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3313/user?useUnicode=true&useSSL=false
username: root
password: '123456'
sharding:
master-slave-rules:
ms0:
master-data-source-name: master0
slave-data-source-names: slave0
ms1:
master-data-source-name: master1
slave-data-source-names: slave1
tables:
user:
key-generator:
column: id
type: SNOWFLAKE
actual-data-nodes: ms$->{0..1}.user_tb_$->{0..2}
database-strategy:
inline:
sharding-column: id
algorithm-expression: ms$->{(id / 10).toBigInteger() % 2}
# algorithm-expression: ms$->{id % 2}
table-strategy:
inline:
sharding-column: id
algorithm-expression: user_tb_$->{id % 3}
mybatis:
type-aliases-package: com.cunzaizhe.entity
mapper-locations: classpath:mapper/*Mapper.xml
pagehelper:
helper-dialect: mysql
support-methods-arguments: true
params: count=countSql
reasonable: false
- 分庫分表原理:先根據id的十位上的數%2被平均分到master0和master1數據庫上,然後再根據id個位上的數%3被平均分到user_tb_0,user_tb_1,user_tb_2上。
- master0,master1,slave0,slave1四個數據源
- 根據用戶id來分庫分表
- 分庫規則 ms$->{(id / 10).toBigInteger() % 2} 十位上的數模2
- 分表規則 user_tb_$->{id % 3} 個位上的數模3
測試一下效果
共插入了300萬條數據 平均每張表50萬條左右
根據id查詢一條記錄 是770毫秒
用戶名模糊查詢 並按照時間排序,分頁取前十條 是1894毫秒
ps:是在一臺電腦,docker部署的4臺mysql
實際情況根據業務發展趨勢和預估在前期設計好數據庫,分庫分表怎麼分,如果是財大氣粗可以直接上TiDB,但對服務器配置要求比較高。TiDB是分佈式數據庫,兼容MySQL,讓數據庫就做它自己的事情。