先把mysql安装一主两从
参考这个
docker安装mysql5.7主从复制_我是一只代码狗的博客-CSDN博客
接下来我们测试下读写分离
在springboot项目中pom.xml引入
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
配置文件
#内存模式,生产环境如果有集群请改成集群模式
spring.shardingsphere.mode.type=Memory
# 配置真实数据源
spring.shardingsphere.datasource.names=master,slave1,slave2
# 配置第 1 个数据源
spring.shardingsphere.datasource.master.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master.jdbc-url=jdbc:mysql://192.168.23.136:13306/db1
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=123456
# 配置第 2 个数据源
spring.shardingsphere.datasource.slave1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave1.jdbc-url=jdbc:mysql://192.168.23.136:13307/db1
spring.shardingsphere.datasource.slave1.username=root
spring.shardingsphere.datasource.slave1.password=123456
# 配置第 3 个数据源
spring.shardingsphere.datasource.slave2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave2.jdbc-url=jdbc:mysql://192.168.23.136:13308/db1
spring.shardingsphere.datasource.slave2.username=root
spring.shardingsphere.datasource.slave2.password=123456
# 读写分离类型,如: Static,Dynamic
spring.shardingsphere.rules.readwrite-splitting.data-sources.myds.type=Static
# 写数据源名称
spring.shardingsphere.rules.readwrite-splitting.data-sources.myds.props.write-data-source-name=master
# 读数据源名称,多个从数据源用逗号分隔
spring.shardingsphere.rules.readwrite-splitting.data-sources.myds.props.read-data-source-names=slave1,slave2
# 负载均衡算法名称
spring.shardingsphere.rules.readwrite-splitting.data-sources.myds.load-balancer-name=alg_round
# 负载均衡算法配置
# 负载均衡算法类型
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_round.type=ROUND_ROBIN
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_random.type=RANDOM
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_weight.type=WEIGHT
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_weight.props.slave1=1
spring.shardingsphere.rules.readwrite-splitting.load-balancers.alg_weight.props.slave2=2
# 打印SQl
spring.shardingsphere.props.sql-show=true
package com.example.demo2.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("biao")
public class Biao {
@TableId(type = IdType.AUTO)
private Integer id;
private String pwd;
}
package com.example.demo2.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo2.entity.Biao;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BiaoMapper extends BaseMapper<Biao> {
}
package com.example.demo2.controller;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class TestController {
@Autowired
private TestService testService;
@GetMapping("/test")
public void test(){
testService.test();
}
}
package com.example.demo2.service;
import com.example.demo2.entity.Biao;
import com.example.demo2.mapper.BiaoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
public interface TestService {
public void test();
}
package com.example.demo2.service.impl;
import com.example.demo2.entity.Biao;
import com.example.demo2.mapper.BiaoMapper;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private BiaoMapper biaoMapper;
@Override
public void test(){
Biao biao=new Biao();
biao.setPwd("aaa");
biaoMapper.insert(biao);
}
}
http://localhost:8080/test
Logic sql:逻辑sql 不知道你要插入那个数据源
Actual SQL:真实的sql ,插入的master的数据源
接下来我们看下数据库,可以看到3个数据库都有数据了
接下来我们看下不加事物会是什么样子
package com.example.demo2.service.impl;
import com.example.demo2.entity.Biao;
import com.example.demo2.mapper.BiaoMapper;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private BiaoMapper biaoMapper;
@Override
public void test(){
Biao biao=new Biao();
biao.setPwd("bbb");
biaoMapper.insert(biao);
List<Biao> biaos = biaoMapper.selectList(null);
for (Biao x : biaos) {
System.out.println(x.getId()+"---"+x.getPwd());
}
}
}
http://localhost:8080/test
我们可以看到在不加事物的情况下,插入master,读取slave1
我们在看下加了事物
package com.example.demo2.service.impl;
import com.example.demo2.entity.Biao;
import com.example.demo2.mapper.BiaoMapper;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private BiaoMapper biaoMapper;
@Transactional(rollbackFor = Exception.class)
@Override
public void test(){
Biao biao=new Biao();
biao.setPwd("bbb");
biaoMapper.insert(biao);
List<Biao> biaos = biaoMapper.selectList(null);
for (Biao x : biaos) {
System.out.println(x.getId()+"---"+x.getPwd());
}
}
}
http://localhost:8080/test
在加了事物之后,读写都是走的master,这就是为了保证一致性
接下来我们看下负载均衡算法
package com.example.demo2.controller;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class TestController {
@Autowired
private TestService testService;
@GetMapping("/test")
public void test(){
testService.test();
}
@GetMapping("/lb")
public void lb(){
testService.lb();
}
}
package com.example.demo2.service;
import com.example.demo2.entity.Biao;
import com.example.demo2.mapper.BiaoMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
public interface TestService {
public void test();
public void lb();
}
package com.example.demo2.service.impl;
import com.example.demo2.entity.Biao;
import com.example.demo2.mapper.BiaoMapper;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private BiaoMapper biaoMapper;
@Transactional(rollbackFor = Exception.class)
@Override
public void test(){
Biao biao=new Biao();
biao.setPwd("bbb");
biaoMapper.insert(biao);
List<Biao> biaos = biaoMapper.selectList(null);
for (Biao x : biaos) {
System.out.println(x.getId()+"---"+x.getPwd());
}
}
@Override
public void lb(){
List<Biao> biaos = biaoMapper.selectList(null);
}
}
http://localhost:8080/lb
我们多刷几次,可以看到一次slave2,一次slave1
我们也可以设置随机访问 ,只需要改这里
我们还可以设置权重
我们可以看到,权重越大的,查询的越多
接下来我们看下垂直分片
垂直分片就是数据库不同,表结构也不相同
先把之前的mysql都停掉
docker stop mysql-master
docker stop mysql-slave
docker stop mysql-slave2
然后安装2个mysql,不用做主从
docker run -d -p 13309:3306 --privileged=true -v /mydata/mysql-user/log:/var/log/mysql -v /mydata/mysql-user/data:/var/lib/mysql -v /mydata/mysql-user/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql-user mysql:5.7
docker run -d -p 13310:3306 --privileged=true -v /mydata/mysql-order/log:/var/log/mysql -v /mydata/mysql-order/data:/var/lib/mysql -v /mydata/mysql-order/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 --name mysql-order mysql:5.7
在user的mysql创建user表
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
在order的mysql创建order表
CREATE TABLE `t_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_name` varchar(255) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
在我们的代码中加入下面的信息
配置文件
#内存模式,生产环境如果有集群请改成集群模式
spring.shardingsphere.mode.type=Memory
# 配置真实数据源
spring.shardingsphere.datasource.names=server-user,server-order
# 配置第 1 个数据源
spring.shardingsphere.datasource.server-user.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-user.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-user.jdbc-url=jdbc:mysql://192.168.23.136:13309/db1
spring.shardingsphere.datasource.server-user.username=root
spring.shardingsphere.datasource.server-user.password=123456
# 配置第 2 个数据源
spring.shardingsphere.datasource.server-order.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order.jdbc-url=jdbc:mysql://192.168.23.136:13310/db1
spring.shardingsphere.datasource.server-order.username=root
spring.shardingsphere.datasource.server-order.password=123456
# 标准分片表配置(数据节点)
# spring.shardingsphere.rules.sharding.tables.<table-name>.actual-data-nodes=值
# 值由数据源名 + 表名组成,以小数点分隔。
# <table-name>:逻辑表名
spring.shardingsphere.rules.sharding.tables.user.actual-data-nodes=server-user.user
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=server-order.t_order
# 打印SQL
spring.shardingsphere.props.sql-show=true
package com.example.demo2.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
@TableName("t_order")
@Data
public class Order {
@TableId(type = IdType.AUTO)
private Integer id;
private String orderName;
private Integer userId;
}
package com.example.demo2.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
}
package com.example.demo2.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo2.entity.Order;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface OrderMapper extends BaseMapper<Order> {
}
package com.example.demo2.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo2.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
package com.example.demo2.service.impl;
import com.example.demo2.entity.Order;
import com.example.demo2.entity.User;
import com.example.demo2.mapper.OrderMapper;
import com.example.demo2.mapper.UserMapper;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private UserMapper userMapper;
@Autowired
private OrderMapper orderMapper;
@Override
public void test(){
User user=new User();
user.setName("bbb");
userMapper.insert(user);
Order order=new Order();
order.setOrderName("订单");
order.setUserId(user.getId());
orderMapper.insert(order);
List<User> aa = userMapper.selectList(null);
List<Order>bb=orderMapper.selectList(null);
}
@Override
public void lb(){
}
}
http://localhost:8080/test
我们可以看到,插入和查询都走了不同的数据库的表
接下来我们在看下水平分片
水平分片就是表结构相同,数据不同
先把之前的表都删除了,然后再不同的数据库创建
t_order0,t_order1表
注意:我们的主键是没有设置自增的,要不然会冲突
CREATE TABLE t_order0 (
id BIGINT,
order_no VARCHAR(30),
user_id BIGINT,
amount DECIMAL(10,2),
PRIMARY KEY(id)
);
CREATE TABLE t_order1 (
id BIGINT,
order_no VARCHAR(30),
user_id BIGINT,
amount DECIMAL(10,2),
PRIMARY KEY(id)
);
配置文件
#内存模式,生产环境如果有集群请改成集群模式
spring.shardingsphere.mode.type=Memory
# 打印SQL
spring.shardingsphere.props.sql-show=true
#========================数据源配置
# 配置真实数据源
spring.shardingsphere.datasource.names=server-order0,server-order1
# 配置第 1 个数据源
spring.shardingsphere.datasource.server-order0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order0.jdbc-url=jdbc:mysql://192.168.23.136:13309/db1
spring.shardingsphere.datasource.server-order0.username=root
spring.shardingsphere.datasource.server-order0.password=123456
# 配置第 2 个数据源
spring.shardingsphere.datasource.server-order1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order1.jdbc-url=jdbc:mysql://192.168.23.136:13310/db1
spring.shardingsphere.datasource.server-order1.username=root
spring.shardingsphere.datasource.server-order1.password=123456
#========================标准分片表配置(数据节点配置)
# spring.shardingsphere.rules.sharding.tables.<table-name>.actual-data-nodes=值
# 值由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。
# <table-name>:逻辑表名
# 因为是多个表,所以我们要使用表达式 这样多个数据源.多个表都能配置上,不用写那么长
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=server-order$->{0..1}.t_order$->{0..1}
#------------------------分库策略
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=user_id
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_inline_userid
#------------------------分片算法配置
# 行表达式分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userid.type=INLINE
# 分片算法属性配置 我们对user_id取模,如果为偶数 放入第一个数据源,如果为奇数 放入第二个数据源
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userid.props.algorithm-expression=server-order$->{user_id % 2}
# 分片算法名称 取模分片算法 如果使用这个,就把上面的分配算法名称注释掉,和行表达式分片算法是一样的效果
#spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_mod
# 取模分片算法
# 分片算法类型
#spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.type=MOD
# 分片算法属性配置
#spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.props.sharding-count=2
#------------------------分表策略
# 分片列名称 按照订单编号去分表 哈希取模 一条在t_order0,一条在t_order1表
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=order_no
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=alg_hash_mod
#------------------------分片算法配置
# 哈希取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.type=HASH_MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.props.sharding-count=2
package com.example.demo2.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
@TableName("t_order")
@Data
public class Order {
//分布式id
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String orderNo;
private Long userId;
private Double amount;
}
package com.example.demo2.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.demo2.entity.Order;
import com.example.demo2.mapper.OrderMapper;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private OrderMapper orderMapper;
@Override
public void test(){
for (int i = 0; i < 4; i++) {
Order order=new Order();
order.setUserId(1L);
order.setOrderNo("order"+i);
order.setAmount(1.0);
orderMapper.insert(order);
}
for (int i = 5; i < 9; i++) {
Order order=new Order();
order.setUserId(2L);
order.setOrderNo("order"+i);
order.setAmount(1.0);
orderMapper.insert(order);
}
}
@Override
public void lb(){
}
}
http://localhost:8080/test
我们可以看到user_id=1的都放到了第一个数据源中,表的4条数数据,也分别按照订单编号放到
t_order0,t_order1表中
user_id=2的都放到了第二个数据源中,表数据也按照订单编号也分别放到了不同的表中
接下来我们测试一下查询
http://localhost:8080/test
可以看到8条数据都查询出来了
我们在来测试下单查user_id=1的
package com.example.demo2.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.demo2.entity.Order;
import com.example.demo2.mapper.OrderMapper;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private OrderMapper orderMapper;
@Override
public void test(){
QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
orderQueryWrapper.eq("user_id", 1L);
List<Order> orders = orderMapper.selectList(orderQueryWrapper);
orders.forEach(System.out::println);
}
@Override
public void lb(){
}
}
可以看到sql只访问了一个数据源,性能提升
接下来我们在看下雪花算法
package com.example.demo2.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
@TableName("t_order")
@Data
public class Order {
//当配置了shardingsphere-jdbc的分布式序列时,走的是雪花算法
//当没有配置时,走的默认表自增
@TableId(type = IdType.AUTO)
private Long id;
private String orderNo;
private Long userId;
private Double amount;
}
#内存模式,生产环境如果有集群请改成集群模式
spring.shardingsphere.mode.type=Memory
# 打印SQL
spring.shardingsphere.props.sql-show=true
#========================数据源配置
# 配置真实数据源
spring.shardingsphere.datasource.names=server-order0,server-order1
# 配置第 1 个数据源
spring.shardingsphere.datasource.server-order0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order0.jdbc-url=jdbc:mysql://192.168.23.136:13309/db1
spring.shardingsphere.datasource.server-order0.username=root
spring.shardingsphere.datasource.server-order0.password=123456
# 配置第 2 个数据源
spring.shardingsphere.datasource.server-order1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order1.jdbc-url=jdbc:mysql://192.168.23.136:13310/db1
spring.shardingsphere.datasource.server-order1.username=root
spring.shardingsphere.datasource.server-order1.password=123456
#========================标准分片表配置(数据节点配置)
# spring.shardingsphere.rules.sharding.tables.<table-name>.actual-data-nodes=值
# 值由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。
# <table-name>:逻辑表名
# 因为是多个表,所以我们要使用表达式 这样多个数据源.多个表都能配置上,不用写那么长
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=server-order$->{0..1}.t_order$->{0..1}
#------------------------分库策略
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=user_id
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_inline_userid
#------------------------分片算法配置
# 行表达式分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userid.type=INLINE
# 分片算法属性配置 我们对user_id取模,如果为偶数 放入第一个数据源,如果为奇数 放入第二个数据源
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userid.props.algorithm-expression=server-order$->{user_id % 2}
# 分片算法名称 取模分片算法 如果使用这个,就把上面的分配算法名称注释掉,和行表达式分片算法是一样的效果
#spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_mod
# 取模分片算法
# 分片算法类型
#spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.type=MOD
# 分片算法属性配置
#spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.props.sharding-count=2
#------------------------分表策略
# 分片列名称 按照订单编号去分表 哈希取模 一条在t_order0,一条在t_order1表
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=order_no
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=alg_hash_mod
#------------------------分片算法配置
# 哈希取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.type=HASH_MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.props.sharding-count=2
#------------------------分布式序列策略配置
# 分布式序列列名称 按照id生成雪花算法
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=id
# 分布式序列算法名称
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=alg_snowflake
# 分布式序列算法配置
# 分布式序列算法类型
spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.type=SNOWFLAKE
http://localhost:8080/test
我们插入一些数据,看下数据库,生成18位的雪花算法id
接下来我们看下多表关联
在所有的数据库中创建订单详情表,注意:主键没有写自增
CREATE TABLE t_order_item0(
id BIGINT,
order_no VARCHAR(30),
user_id BIGINT,
price DECIMAL(10,2),
`count` INT,
PRIMARY KEY(id)
);
CREATE TABLE t_order_item1(
id BIGINT,
order_no VARCHAR(30),
user_id BIGINT,
price DECIMAL(10,2),
`count` INT,
PRIMARY KEY(id)
);
配置文件
#内存模式,生产环境如果有集群请改成集群模式
spring.shardingsphere.mode.type=Memory
# 打印SQL
spring.shardingsphere.props.sql-show=true
#========================数据源配置
# 配置真实数据源
spring.shardingsphere.datasource.names=server-order0,server-order1
# 配置第 1 个数据源
spring.shardingsphere.datasource.server-order0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order0.jdbc-url=jdbc:mysql://192.168.23.136:13309/db1
spring.shardingsphere.datasource.server-order0.username=root
spring.shardingsphere.datasource.server-order0.password=123456
# 配置第 2 个数据源
spring.shardingsphere.datasource.server-order1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order1.jdbc-url=jdbc:mysql://192.168.23.136:13310/db1
spring.shardingsphere.datasource.server-order1.username=root
spring.shardingsphere.datasource.server-order1.password=123456
#========================标准分片表配置(数据节点配置)
# spring.shardingsphere.rules.sharding.tables.<table-name>.actual-data-nodes=值
# 值由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。
# <table-name>:逻辑表名
# 因为是多个表,所以我们要使用表达式 这样多个数据源.多个表都能配置上,不用写那么长
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=server-order$->{0..1}.t_order$->{0..1}
spring.shardingsphere.rules.sharding.tables.t_order_item.actual-data-nodes=server-order$->{0..1}.t_order_item$->{0..1}
#------------------------分库策略
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=user_id
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_inline_userid
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order_item.database-strategy.standard.sharding-column=user_id
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order_item.database-strategy.standard.sharding-algorithm-name=alg_inline_userid
#------------------------分片算法配置
# 行表达式分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userid.type=INLINE
# 分片算法属性配置 我们对user_id取模,如果为偶数 放入第一个数据源,如果为奇数 放入第二个数据源
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userid.props.algorithm-expression=server-order$->{user_id % 2}
# 分片算法名称 取模分片算法 如果使用这个,就把上面的分配算法名称注释掉,和行表达式分片算法是一样的效果
#spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_mod
# 取模分片算法
# 分片算法类型
#spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.type=MOD
# 分片算法属性配置
#spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.props.sharding-count=2
#------------------------分表策略
# 分片列名称 按照订单编号去分表 哈希取模 一条在t_order0,一条在t_order1表
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=order_no
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=alg_hash_mod
# 分片列名称 按照订单编号去分表 哈希取模 一条在t_order_item0,一条在t_order_item1表
spring.shardingsphere.rules.sharding.tables.t_order_item.table-strategy.standard.sharding-column=order_no
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order_item.table-strategy.standard.sharding-algorithm-name=alg_hash_mod
#------------------------分片算法配置
# 哈希取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.type=HASH_MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.props.sharding-count=2
#------------------------分布式序列策略配置
# 分布式序列列名称 按照id生成雪花算法
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=id
# 分布式序列算法名称
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=alg_snowflake
# 分布式序列列名称
spring.shardingsphere.rules.sharding.tables.t_order_item.key-generate-strategy.column=id
# 分布式序列算法名称
spring.shardingsphere.rules.sharding.tables.t_order_item.key-generate-strategy.key-generator-name=alg_snowflake
# 分布式序列算法配置
# 分布式序列算法类型
spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.type=SNOWFLAKE
package com.example.demo2.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
@TableName("t_order_item")
@Data
public class OrderItem {
//当配置了shardingsphere-jdbc的分布式序列时,自动使用shardingsphere-jdbc的分布式序列
@TableId(type = IdType.AUTO)
private Long id;
private String orderNo;
private Long userId;
private BigDecimal price;
private Integer count;
}
package com.example.demo2.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo2.entity.OrderItem;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface OrderItemMapper extends BaseMapper<OrderItem> {
}
package com.example.demo2.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.demo2.entity.Order;
import com.example.demo2.entity.OrderItem;
import com.example.demo2.mapper.OrderItemMapper;
import com.example.demo2.mapper.OrderMapper;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderItemMapper orderItemMapper;
@Override
public void test(){
for (long i = 0; i < 2; i++) {
Order order = new Order();
order.setOrderNo("order" + i);
order.setUserId(1L);
orderMapper.insert(order);
for (long j = 1; j < 3; j++) {
OrderItem orderItem = new OrderItem();
orderItem.setOrderNo("order" + i);
orderItem.setUserId(1L);
orderItem.setPrice(new BigDecimal(10));
orderItem.setCount(2);
orderItemMapper.insert(orderItem);
}
}
for (long i = 3; i < 5; i++) {
Order order = new Order();
order.setOrderNo("order" + i);
order.setUserId(2L);
orderMapper.insert(order);
for (long j = 1; j < 3; j++) {
OrderItem orderItem = new OrderItem();
orderItem.setOrderNo("order" + i);
orderItem.setUserId(2L);
orderItem.setPrice(new BigDecimal(1));
orderItem.setCount(3);
orderItemMapper.insert(orderItem);
}
}
}
@Override
public void lb(){
}
}
http://localhost:8080/test
插入数据后,会发现不同的userid,对应不同的订单编号
我们来测试下查询
package com.example.demo2.entity;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class OrderVo {
private String orderNo;
private BigDecimal amount;
}
package com.example.demo2.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo2.entity.Order;
import com.example.demo2.entity.OrderVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface OrderMapper extends BaseMapper<Order> {
@Select({"SELECT o.order_no, SUM(i.price * i.count) AS amount",
"FROM t_order o JOIN t_order_item i ON o.order_no = i.order_no",
"GROUP BY o.order_no"})
List<OrderVo> getOrderAmount();
}
package com.example.demo2.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.demo2.entity.Order;
import com.example.demo2.entity.OrderItem;
import com.example.demo2.entity.OrderVo;
import com.example.demo2.mapper.OrderItemMapper;
import com.example.demo2.mapper.OrderMapper;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderItemMapper orderItemMapper;
@Override
public void test(){
List<OrderVo> orderAmountList = orderMapper.getOrderAmount();
orderAmountList.forEach(System.out::println);
}
@Override
public void lb(){
}
}
http://localhost:8080/test
可以看到,虽然数据是查询出来了,但是会产生笛卡尔积,不是我们想要的效果
我们想要的是自己的用户id,对应自己订单编号
接下来我们配置绑定表
配置文件
#内存模式,生产环境如果有集群请改成集群模式
spring.shardingsphere.mode.type=Memory
# 打印SQL
spring.shardingsphere.props.sql-show=true
#========================数据源配置
# 配置真实数据源
spring.shardingsphere.datasource.names=server-order0,server-order1
# 配置第 1 个数据源
spring.shardingsphere.datasource.server-order0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order0.jdbc-url=jdbc:mysql://192.168.23.136:13309/db1
spring.shardingsphere.datasource.server-order0.username=root
spring.shardingsphere.datasource.server-order0.password=123456
# 配置第 2 个数据源
spring.shardingsphere.datasource.server-order1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order1.jdbc-url=jdbc:mysql://192.168.23.136:13310/db1
spring.shardingsphere.datasource.server-order1.username=root
spring.shardingsphere.datasource.server-order1.password=123456
#========================标准分片表配置(数据节点配置)
# spring.shardingsphere.rules.sharding.tables.<table-name>.actual-data-nodes=值
# 值由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。
# <table-name>:逻辑表名
# 因为是多个表,所以我们要使用表达式 这样多个数据源.多个表都能配置上,不用写那么长
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=server-order$->{0..1}.t_order$->{0..1}
spring.shardingsphere.rules.sharding.tables.t_order_item.actual-data-nodes=server-order$->{0..1}.t_order_item$->{0..1}
#------------------------分库策略
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=user_id
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_inline_userid
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order_item.database-strategy.standard.sharding-column=user_id
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order_item.database-strategy.standard.sharding-algorithm-name=alg_inline_userid
#------------------------分片算法配置
# 行表达式分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userid.type=INLINE
# 分片算法属性配置 我们对user_id取模,如果为偶数 放入第一个数据源,如果为奇数 放入第二个数据源
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userid.props.algorithm-expression=server-order$->{user_id % 2}
# 分片算法名称 取模分片算法 如果使用这个,就把上面的分配算法名称注释掉,和行表达式分片算法是一样的效果
#spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_mod
# 取模分片算法
# 分片算法类型
#spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.type=MOD
# 分片算法属性配置
#spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.props.sharding-count=2
#------------------------分表策略
# 分片列名称 按照订单编号去分表 哈希取模 一条在t_order0,一条在t_order1表
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=order_no
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=alg_hash_mod
# 分片列名称 按照订单编号去分表 哈希取模 一条在t_order_item0,一条在t_order_item1表
spring.shardingsphere.rules.sharding.tables.t_order_item.table-strategy.standard.sharding-column=order_no
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order_item.table-strategy.standard.sharding-algorithm-name=alg_hash_mod
#------------------------分片算法配置
# 哈希取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.type=HASH_MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.props.sharding-count=2
#------------------------分布式序列策略配置
# 分布式序列列名称 按照id生成雪花算法
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=id
# 分布式序列算法名称
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=alg_snowflake
# 分布式序列列名称
spring.shardingsphere.rules.sharding.tables.t_order_item.key-generate-strategy.column=id
# 分布式序列算法名称
spring.shardingsphere.rules.sharding.tables.t_order_item.key-generate-strategy.key-generator-name=alg_snowflake
# 分布式序列算法配置
# 分布式序列算法类型
spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.type=SNOWFLAKE
#------------------------绑定表
spring.shardingsphere.rules.sharding.binding-tables[0]=t_order,t_order_item
我们在来看下效果,可以看到,这次只查询了4条,不会产生笛卡尔积,大大的提升了效率
绑定表:
指分片规则一致的一组分片表。 使用绑定表进行多表关联查询时,必须使用分片键进行关联,否则会出现笛卡尔积关联或跨库关联,从而影响查询效率。
接下来我们在看下广播表
广播表就是在所有数据库都有这张表,并且数据都一样
在所有数据库都创建字典表
CREATE TABLE t_dict(
id BIGINT,
dict_type VARCHAR(200),
PRIMARY KEY(id)
);
package com.example.demo2.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@TableName("t_dict")
@Data
public class Dict {
//可以使用MyBatisPlus的雪花算法
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String dictType;
}
package com.example.demo2.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo2.entity.Dict;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface DictMapper extends BaseMapper<Dict> {
}
配置文件
#内存模式,生产环境如果有集群请改成集群模式
spring.shardingsphere.mode.type=Memory
# 打印SQL
spring.shardingsphere.props.sql-show=true
#========================数据源配置
# 配置真实数据源
spring.shardingsphere.datasource.names=server-order0,server-order1
# 配置第 1 个数据源
spring.shardingsphere.datasource.server-order0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order0.jdbc-url=jdbc:mysql://192.168.23.136:13309/db1
spring.shardingsphere.datasource.server-order0.username=root
spring.shardingsphere.datasource.server-order0.password=123456
# 配置第 2 个数据源
spring.shardingsphere.datasource.server-order1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.server-order1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.server-order1.jdbc-url=jdbc:mysql://192.168.23.136:13310/db1
spring.shardingsphere.datasource.server-order1.username=root
spring.shardingsphere.datasource.server-order1.password=123456
#========================标准分片表配置(数据节点配置)
# spring.shardingsphere.rules.sharding.tables.<table-name>.actual-data-nodes=值
# 值由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。
# <table-name>:逻辑表名
# 因为是多个表,所以我们要使用表达式 这样多个数据源.多个表都能配置上,不用写那么长
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=server-order$->{0..1}.t_order$->{0..1}
spring.shardingsphere.rules.sharding.tables.t_order_item.actual-data-nodes=server-order$->{0..1}.t_order_item$->{0..1}
#------------------------分库策略
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=user_id
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_inline_userid
# 分片列名称
spring.shardingsphere.rules.sharding.tables.t_order_item.database-strategy.standard.sharding-column=user_id
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order_item.database-strategy.standard.sharding-algorithm-name=alg_inline_userid
#------------------------分片算法配置
# 行表达式分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userid.type=INLINE
# 分片算法属性配置 我们对user_id取模,如果为偶数 放入第一个数据源,如果为奇数 放入第二个数据源
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_inline_userid.props.algorithm-expression=server-order$->{user_id % 2}
# 分片算法名称 取模分片算法 如果使用这个,就把上面的分配算法名称注释掉,和行表达式分片算法是一样的效果
#spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=alg_mod
# 取模分片算法
# 分片算法类型
#spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.type=MOD
# 分片算法属性配置
#spring.shardingsphere.rules.sharding.sharding-algorithms.alg_mod.props.sharding-count=2
#------------------------分表策略
# 分片列名称 按照订单编号去分表 哈希取模 一条在t_order0,一条在t_order1表
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=order_no
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=alg_hash_mod
# 分片列名称 按照订单编号去分表 哈希取模 一条在t_order_item0,一条在t_order_item1表
spring.shardingsphere.rules.sharding.tables.t_order_item.table-strategy.standard.sharding-column=order_no
# 分片算法名称
spring.shardingsphere.rules.sharding.tables.t_order_item.table-strategy.standard.sharding-algorithm-name=alg_hash_mod
#------------------------分片算法配置
# 哈希取模分片算法
# 分片算法类型
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.type=HASH_MOD
# 分片算法属性配置
spring.shardingsphere.rules.sharding.sharding-algorithms.alg_hash_mod.props.sharding-count=2
#------------------------分布式序列策略配置
# 分布式序列列名称 按照id生成雪花算法
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=id
# 分布式序列算法名称
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=alg_snowflake
# 分布式序列列名称
spring.shardingsphere.rules.sharding.tables.t_order_item.key-generate-strategy.column=id
# 分布式序列算法名称
spring.shardingsphere.rules.sharding.tables.t_order_item.key-generate-strategy.key-generator-name=alg_snowflake
# 分布式序列算法配置
# 分布式序列算法类型
spring.shardingsphere.rules.sharding.key-generators.alg_snowflake.type=SNOWFLAKE
#------------------------绑定表
spring.shardingsphere.rules.sharding.binding-tables[0]=t_order,t_order_item
#t_dict数据节点可不配置,默认情况下,向所有数据源广播
# 广播表
spring.shardingsphere.rules.sharding.broadcast-tables[0]=t_dict
package com.example.demo2.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.demo2.entity.Dict;
import com.example.demo2.entity.Order;
import com.example.demo2.entity.OrderItem;
import com.example.demo2.entity.OrderVo;
import com.example.demo2.mapper.DictMapper;
import com.example.demo2.mapper.OrderItemMapper;
import com.example.demo2.mapper.OrderMapper;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderItemMapper orderItemMapper;
@Autowired
private DictMapper dictMapper;
@Override
public void test(){
Dict dict = new Dict();
dict.setDictType("type");
dictMapper.insert(dict);
}
@Override
public void lb(){
}
}
接下来测试下插入
http://localhost:8080/test
可以看到,所有表都有数据了,并且数据都一样
我们来查询一下
package com.example.demo2.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.demo2.entity.Dict;
import com.example.demo2.entity.Order;
import com.example.demo2.entity.OrderItem;
import com.example.demo2.entity.OrderVo;
import com.example.demo2.mapper.DictMapper;
import com.example.demo2.mapper.OrderItemMapper;
import com.example.demo2.mapper.OrderMapper;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderItemMapper orderItemMapper;
@Autowired
private DictMapper dictMapper;
@Override
public void test(){
List<Dict> dicts = dictMapper.selectList(null);
dicts.forEach(System.out::println);
}
@Override
public void lb(){
}
}
我们多刷新几次,可以看到他每次查询的都是随机的数据源,不会2个数据源都去访问
这就就避免了跨库查询,大大的提升了效率
接下来我们在看下ShardingSphere-Proxy
安装
docker run -d \
-v /root/server/proxy-a/conf:/opt/shardingsphere-proxy/conf \
-v /root/server/proxy-a/ext-lib:/opt/shardingsphere-proxy/ext-lib \
-e ES_JAVA_OPTS="-Xmx256m -Xms256m -Xmn128m" \
-p 3321:3307 \
--name server-proxy-a \
apache/shardingsphere-proxy:5.1.1
上传mysql驱动
cd /root/server/proxy-a/ext-lib
进入这个目录,创建server.yaml
/root/server/proxy-a/conf
vi server.yaml
rules:
- !AUTHORITY
users:
- root@%:root
provider:
type: ALL_PRIVILEGES_PERMITTED
props:
sql-show: true
然后重启代理
docker restart server-proxy-a
然后连接
用户名root,密码root,端口3321
接下来创建读写分离的yaml
配置之前的数据库
vi config-readwrite-splitting.yaml
schemaName: db3
dataSources:
write_ds:
url: jdbc:mysql://192.168.23.136:13309/db1?serverTimezone=UTC&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
read_ds_0:
url: jdbc:mysql://192.168.23.136:13310/db1?serverTimezone=UTC&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
- !READWRITE_SPLITTING
dataSources:
readwrite_ds:
type: Static
props:
write-data-source-name: write_ds
read-data-source-names: read_ds_0
重启容器
docker restart server-proxy-a
可以看到代理这里就多个一个db3的数据库
可以看到其他数据库的数据表也同步过来了
接下来看下代码
配置文件
注意:这里连接的是代理的配置
#mysql数据库连接(proxy)
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.23.136:3321/db3?serverTimezone=GMT%2B8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
package com.example.demo2.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.demo2.entity.Dict;
import com.example.demo2.entity.Order;
import com.example.demo2.entity.OrderItem;
import com.example.demo2.entity.OrderVo;
import com.example.demo2.mapper.DictMapper;
import com.example.demo2.mapper.OrderItemMapper;
import com.example.demo2.mapper.OrderMapper;
import com.example.demo2.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
@Service
public class TestServiceImpl implements TestService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderItemMapper orderItemMapper;
@Autowired
private DictMapper dictMapper;
@Override
public void test(){
List<Dict> dicts = dictMapper.selectList(null);
dicts.forEach(System.out::println);
}
@Override
public void lb(){
}
}
pom.xml把这个注释掉
http://localhost:8080/test
我们进入容器 看下日志
docker exec -it server-proxy-a /bin/bash
tail -f /opt/shardingsphere-proxy/logs/stdout.log
访问了读的数据库
我们在测试下添加,可以看到走的写库
接下来我们在看下代理的垂直分片
vi config-sharding.yaml
schemaName: db4
dataSources:
ds_0:
url: jdbc:mysql://192.168.23.136:13309/db1?serverTimezone=UTC&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
ds_1:
url: jdbc:mysql://192.168.23.136:13310/db1?serverTimezone=UTC&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
- !SHARDING
tables:
t_order_item:
actualDataNodes: ds_0.t_order_item0
t_order:
actualDataNodes: ds_1.t_order0
重启容器
docker restart server-proxy-a
在代理的数据库执行
SELECT * from t_order0;
SELECT * from t_order_item0;
可以看到查询的就是不同的数据库
接下来在看下代理的水平分片
vi config-sharding.yaml
schemaName: db7
dataSources:
ds_order0:
url: jdbc:mysql://192.168.23.136:13309/db1?serverTimezone=UTC&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
ds_order1:
url: jdbc:mysql://192.168.23.136:13310/db1?serverTimezone=UTC&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
- !SHARDING
tables:
t_order:
actualDataNodes: ds_order${0..1}.t_order${0..1}
databaseStrategy:
standard:
shardingColumn: user_id
shardingAlgorithmName: alg_mod
tableStrategy:
standard:
shardingColumn: order_no
shardingAlgorithmName: alg_hash_mod
keyGenerateStrategy:
column: id
keyGeneratorName: snowflake
t_order_item:
actualDataNodes: ds_order${0..1}.t_order_item${0..1}
databaseStrategy:
standard:
shardingColumn: user_id
shardingAlgorithmName: alg_mod
tableStrategy:
standard:
shardingColumn: order_no
shardingAlgorithmName: alg_hash_mod
keyGenerateStrategy:
column: id
keyGeneratorName: snowflake
bindingTables:
- t_order,t_order_item
broadcastTables:
- t_dict
shardingAlgorithms:
alg_mod:
type: MOD
props:
sharding-count: 2
alg_hash_mod:
type: HASH_MOD
props:
sharding-count: 2
keyGenerators:
snowflake:
type: SNOWFLAKE
重启容器
docker restart server-proxy-a
注意:t_order和t_order_item都是逻辑表
真实的表是不同数据库的t_order0,t_order1,t_order_item0,t_order_item1
在代理数据库查询一下字典表
SELECT * from t_dict
过滤日志
tail -f /opt/shardingsphere-proxy/logs/stdout.log|grep 'Actual'
在代理数据库查询一下订单详情表
SELECT * from t_order_item