【数据库】使用ShardingSphere+Mybatis-Plus实现读写分离

书接上回:数据库调优方案中数据库主从复制,如何实现读写分离

ShardingSphere 实现读写分离的方式是通过配置数据源的方式,使得应用程序可以在执行读操作和写操作时分别访问不同的数据库实例。这样可以将读取操作分发到多个从库(从服务器),从而提高读取性能,同时将写操作发送到主库(主服务器)以确保数据的一致性。

引入依赖

		<dependency>
            <groupId>org.apache.shardingspheregroupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starterartifactId>
            <version>5.1.1version>
        dependency>
        <dependency>
            <groupId>com.baomidougroupId>
            <artifactId>mybatis-plus-boot-starterartifactId>
            <version>3.5.2version>
        dependency>
        <dependency>
             <groupId>com.mysqlgroupId>
             <artifactId>mysql-connector-jartifactId>
             <version>${mysql-version}version>
         dependency>

配置

# 读写分离配置
spring:
  shardingsphere:
    datasource:
      # 配置真实数据源
      names: master,slave1,slave2
      # 配置第 1 个数据源
      master:
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/sso
        password: 123456
        type: com.zaxxer.hikari.HikariDataSource
        username: root
      # 配置第 2 个数据源
      slave1:
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/sso_test
        password: 123456
        type: com.zaxxer.hikari.HikariDataSource
        username: root
      # 配置第 3 个数据源
      slave2:
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://127.0.0.1:3306/slave_test
        password: 123456
        type: com.zaxxer.hikari.HikariDataSource
        username: root
    mode:
      # 内存模式
      type: Memory
    # 打印sql
    props:
      sql-show: true
    rules:
      readwrite-splitting:
        data-sources:
          myds:
            # 读数据源负载均衡算法名称
            load-balancer-name: alg_round
            props:
              # 读数据源名称,多个从数据源用逗号分隔
              read-data-source-names: slave1,slave2
              # 写数据源名称
              write-data-source-name: master
            # 读写分离类型,如: Static,Dynamic
            type: Static
        load-balancers:
          # 定义负载均衡算法:随机,轮询,权重
          alg_random:
            type: RANDOM
          alg_round:
            type: ROUND_ROBIN
          alg_weight:
            props:
              slave1: 1
              slave2: 2
            type: WEIGHT

创建数据库表

由于主、从数据库里的数据是一样的,所以sso和sso_test都用下面代码创建sys_business表

CREATE TABLE `sys_business` (
	`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
	`avaliable` TINYINT ( 1 ) DEFAULT '1' COMMENT '是否可用#0:禁用#1:启用',
	`name` VARCHAR ( 30 ) CHARACTER 
	SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '系统名称',
	`permission` VARCHAR ( 30 ) CHARACTER 
	SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '权限字符',
	`path` VARCHAR ( 100 ) CHARACTER 
	SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '路由地址',
	`icon` VARCHAR ( 30 ) CHARACTER 
	SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '图表',
	`create_time` datetime DEFAULT NULL COMMENT '创建时间',
	`update_time` datetime DEFAULT NULL COMMENT '更新时间',
	`delete_flag` TINYINT ( 1 ) DEFAULT '1' COMMENT '是否删除#1:未删除#0:已删除',
PRIMARY KEY ( `id` ) 
) ENGINE = INNODB AUTO_INCREMENT = 3 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci;

编写实体类

@Data
@TableName("sys_business")
public class Sso {
    private Long id;

    private String name;
}

业务代码

mapper

public interface SsoMapper extends BaseMapper<Sso> {
}

service

public interface ISsoService extends IService<Sso> {
}

service实现类

@Service
public class ISsoServiceImpl extends ServiceImpl<SsoMapper, Sso> implements ISsoService {
}

测试

1、先在sso_test(从)读,后向sso(主)插(测试配置文件是否生效)

	@Resource
    private ISsoService iSsoService;
    
    @RequestMapping("/slace_master")
    public boolean masterTest(){
        Sso sso = iSsoService.getById(1L);
        System.out.println(sso.toString());
        return iSsoService.save(sso);
    }

当前从库中的数据:
在这里插入图片描述
主库此时还没有数据:
【数据库】使用ShardingSphere+Mybatis-Plus实现读写分离_第1张图片
运行后:
【数据库】使用ShardingSphere+Mybatis-Plus实现读写分离_第2张图片
先在从库中查出,然后向主库中写入,实现了数据的同步,说明集成生效了。

2、先插主库,后读从库(没有加事务)

因为sso_test没有对sso这个库的binlog日志进行监听,现在这两个库是没有同步关系的,写入sso后,不会同步到sso_test。


    @RequestMapping("insert_and_read")
    public boolean inAndRed(){
        Sso sso =new Sso();
        sso.setId(2L);
        sso.setName("TestName1");
        boolean save = iSsoService.save(sso);
        Sso byId = iSsoService.getById(2L);
        System.out.println(byId);
        return save;
    }

执行后主库中的数据:
【数据库】使用ShardingSphere+Mybatis-Plus实现读写分离_第3张图片
执行后从库中的数据:
【数据库】使用ShardingSphere+Mybatis-Plus实现读写分离_第4张图片
打印结果:
在这里插入图片描述

在2中的方法上加事务@Transactional注解(会强制读取刚执行完写入的库也就是主库)


    @RequestMapping("insert_and_read")
    @Transactional
    public boolean inAndRed(){
        Sso sso =new Sso();
        sso.setId(2L);
        sso.setName("TestName1");
        boolean save = iSsoService.save(sso);
        Sso byId = iSsoService.getById(2L);
        System.out.println(byId);
        return save;
    }

在这里插入图片描述

你可能感兴趣的:(数据库,mybatis)