前文
《Sharding-JDBC简单使用》
《Sharding-JDBC主子表(绑定表)关联》
规划
由于这里我只有 2 台数据库,就搞个一主一从,规划如下;
ds0: master_order # 写库
表: m_order_0
m_order_1
ds1: slave_order # 读库
表: m_order_0
m_order_1
- 数据库分片策略:不分片,永远在一个库
- 表数据分片策略:偶数分到 m_order_0,奇数分到 m_order_1
环境准备
创建两个数据库:master_order 和 slave_order
创建表:m_order_0 和 m_order_1
CREATE TABLE `m_order_0` (
`id` int(11) NOT NULL,
`order_amount` decimal(10,2) NOT NULL COMMENT '订单金额',
`order_status` int(1) NOT NULL COMMENT '订单状态',
`user_id` int(11) NOT NULL COMMENT '用户 iD',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
配置读写分离 + 分片表
这里就要配置上面我们规划的那种了
server:
port: 8080
tomcat:
uri-encoding: utf-8
servlet:
encoding:
charset: UTF-8
logging:
level:
com.jcl.sharing: info
spring:
application:
name: sharing-jdbc-sample
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
# ?????????
default-property-inclusion: non_null
# sharding ??
shardingsphere:
# 打印 sharding 的 sql 信息
props:
sql:
show: true
datasource:
names: ds0master,ds0slave
ds0master:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://localhost:3306/master_order?serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=utf8
username: root
password: 123456
ds0slave:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://192.168.1.6:3306/slave_order?serverTimezone=Asia/Shanghai&useSSL=true&characterEncoding=utf8
username: root
password: 123456
# 分片表的读写分离配置
sharding:
master-slave-rules:
# 自定义一个读写分离的数据源名称
ms:
name: ms
# 写数据源
masterDataSourceName: ds0master
# 读数据源列表
slaveDataSourceNames:
- ds0slave
# 读写分离负载均衡
loadBalanceAlgorithmType: round_robin
tables:
m_order:
# 实际节点, 前面的数据节点需要指定读写分离规则里面的数据源名称
# 由于这里只有一个读写分离规则,所以写死这个数据贵
actual-data-nodes: ms.m_order_$->{0..1}
# 数据库分片策略
# database-strategy:
# inline:
# sharding-column: id
# algorithm-expression: ds$->{user_id % 2}
# 表分片策略
table-strategy:
inline:
sharding-column: id
# 偶数分到 m_order_0,奇数分到 m_order_1
algorithm-expression: m_order_$->{id % 2}
mybatis:
configuration:
map-underscore-to-camel-case: true
# ??sql
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: /mapper/*.xml
注意的是数据源的自定义名称:ds0master 这个是有效的,写成 ds0_master 启动会报错,注意这个天坑~ 这里笔者专门花了一个小时左右时间,去层层进断点调试,下面会说!
功能测试
@Test
void testOrderAdd2() {
Order order = new Order();
// 分到 m_order_0 中
order.setUserId(2);
// 表:id 偶数分到 t_order_1, 奇数分到 t_order_2
order.setId(2);
order.setOrderAmount(BigDecimal.TEN);
order.setOrderStatus(1);
orderMapper.insertSelective(order);
}
@Test
public void testOrderRead() {
Order order = orderMapper.selectByPrimaryKey(2);
System.out.println(order);
}
读取结果
2022-09-24 20:53:52.725 INFO 2376 --- [ main] ShardingSphere-SQL : Actual SQL: ds0slave ::: select
id
, order_amount, order_status, user_id
from m_order_0
where id = ? ::: [2]
<== Total: 0
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5b74902c]
null
这个结果是正常的,因为这一章我至少配置了 sharding 的读写分离,单库分表,但是在数据库层面却没有设置主从同步,所以这个是正常的
在这里非常感谢茶佬提供的文章!