Sharding-JDBC二:MySQL读写分离

先搭建主从复制 主从复制

创建SpringBoot程序

添加依赖

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <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>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

创建实体类

@TableName("t_user")
@Data
public class TUser {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String uname;
}

创建Mapper

@Mapper
public interface TUserMapper extends BaseMapper<TUser> {

}

配置读写分离

模式配置

官方配置项说明 模式配置官方

mode (?): # 不配置则默认内存模式
  type: # 运行模式类型。可选配置:Memory、Standalone、Cluster
  repository (?): # 久化仓库配置。Memory 类型无需持久化
  overwrite: # 是否使用本地配置覆盖持久化配置
  • 注释(?): 表示这是一个可选项,可以选择性地配置。

数据源配置

dataSources: # 数据源配置,可配置多个 <data-source-name>
  <data-source-name>: # 数据源名称
    dataSourceClassName: # 数据源完整类名
    driverClassName: # 数据库驱动类名,以数据库连接池自身配置为准
    jdbcUrl: # 数据库 URL 连接,以数据库连接池自身配置为准
    username: # 数据库用户名,以数据库连接池自身配置为准
    password: # 数据库密码,以数据库连接池自身配置为准
    # ... 数据库连接池的其它属性

读写分离

rules:
- !READWRITE_SPLITTING
  dataSources:
    <data-source-name> (+): # 读写分离逻辑数据源名称
        type: # 读写分离类型,比如:Static,Dynamic
        props:
          auto-aware-data-source-name: # 自动发现数据源名称(与数据库发现配合使用)
          write-data-source-name: # 写库数据源名称
          read-data-source-names: # 读库数据源名称,多个从数据源用逗号分隔
      loadBalancerName: # 负载均衡算法名称
  
  # 负载均衡算法配置
  loadBalancers:
    <load-balancer-name> (+): # 负载均衡算法名称
      type: # 负载均衡算法类型
      props: # 负载均衡算法属性配置
        # ...

(+): # 读写分离逻辑数据源名称 详解

下面的实际使用中我们使用myds作为读写分离 逻辑 数据源名称
在这里插入图片描述
myds逻辑数据源名称实际有三个数据源master、slave1、slave2。 由他们三个组成了一个大的逻辑数据源就是myds 。
当程序的架构变得更大时。 myds也可能会变成庞大数据源的其中一个节点。
在这里插入图片描述

auto-aware-data-source-name:# 自动发现数据源名称(与数据库发现配合使用) 当 type: # 读写分离类型,为Dynamic 才配置
(+) 表示可以配置多个

实际配置

# 应用名称
spring:
  application:
    name: sharding-jdbc-demo
  profiles:
    active: dev
  shardingsphere:
    mode:
      type: Memory
    props:
      sql-show: true

    # 配置真实数据源
    datasource:
      names: master,slave1,slave2

      # 配置第 1 个数据源
      master:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3506/db_user?allowPublicKeyRetrieval=true&useSSL=false
        username: root
        password: 123456

      # 配置第 2 个数据源
      slave1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3507/db_user?allowPublicKeyRetrieval=true&useSSL=false
        username: root
        password: 123456

      # 配置第 3 个数据源
      slave2:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3508/db_user?allowPublicKeyRetrieval=true&useSSL=false
        username: root
        password: 123456

    # 读写分离配置
    rules:
      readwrite-splitting:
        data-sources:
          myds:
            type: Static
            props:
              write-data-source-name: master
              read-data-source-names: slave1,slave2
              sql-show: true
            load-balancer-name: alg_round

        # 负载均衡算法配置
        load-balancers:
          alg_round:
          # 轮询算法
            type: ROUND_ROBIN
 

负载均衡算法配置可根据官网进行实际配置 负载均衡算法

读写分离测试

  @Test
    public void contextLoads(){
        TUser user = new TUser();
        user.setUname("2df");
        userMapper.insert(user);
    }

在这里插入图片描述
Logic SQL: INSERT INTO t_user ( uname ) VALUES ( ? )

Logic SQL 就是指逻辑SQL
向逻辑数据源的t_user 逻辑表中插入数据,

具体t_user 表是哪个数据源 是master还是slave1,slave2呢?应用程序并不关心,因为把他交给了shardingjdbc 由shardingjdbc根据配置文件自动的判断,哪一台是写服务器,哪一台是从服务器.shardingjdbc会自动找到写数据源,从而向写数据源写入数据

在这里插入图片描述

Actual SQL: master ::: INSERT INTO t_user ( uname ) VALUES ( ? ) ::: [2df]
Actual SQL实际SQL指出了master数据源

事务测试

@Test
public void testTrans(){

    TUser user = new TUser();
    user.setUname("韩跑跑");
    userMapper.insert(user);

    List<TUser> users = userMapper.selectList(null);
}

实际SQL日志
在这里插入图片描述

  • 先向逻辑数据源插入数据
    • 实际上是主机插入数据
  • 查询是逻辑数据源
    • 实际上是slave1查询数据

添加事务@Transactional//开启事务

    /**
     * 事务测试
     */
    @Transactional//开启事务
    @Test
    public void testTrans(){

        TUser user = new TUser();
        user.setUname("添加事务测试");
        userMapper.insert(user);

        List<TUser> users = userMapper.selectList(null);
    }

在这里插入图片描述
查询和插入均在master执行。这是问什么呢?

  • 不添加@Transactional:insert对主库操作,select对从库操作
  • 添加@Transactional:则insert和select均对主库操作
    其中第五项Rolled back transaction for test: ● 事务回滚 在JUnit测试环境下的**@Transactional**注解,默认情况下就会对事务进行回滚(即使在没加注解@Rollback,也会对事务回滚)
    ● 测试环境下查看数据库,并没有数据插入 。

负载均衡

/**
 * 读数据测试
 */
@Test
public void testSelectAll(){
    List<TUser> users1 = userMapper.selectList(null);
    List<TUser> users2 = userMapper.selectList(null);
    List<TUser> users3 = userMapper.selectList(null);
    List<TUser> users4 = userMapper.selectList(null);
    users1.forEach(System.out::println);
}

在这里插入图片描述
看出是slave1,slave2是轮询查询的。因为我们现在使用的就是轮询的算法。

切换随机算法

        # 负载均衡算法配置
        load-balancers:
          alg_round:
            # 轮询算法
            type: ROUND_ROBIN
          alg_random:
            # 随机访问算法
            type: RANDOM

更改引用的算法名称

load-balancer-name: alg_round
改为对相应的算法名称
load-balancer-name: alg_random

执行testSelectAll
在这里插入图片描述
可以看出执行了三个slave1 一个slave2

切换权重算法,需要配置 权重值


        # 负载均衡算法配置
        load-balancers:
          alg_round:
            # 轮询算法
            type: ROUND_ROBIN
          alg_random:
            # 随机访问算法
            type: RANDOM
          alg_weight:
            # 权重访问算法
            type: WEIGHT
            props:
              slave1 : 1
              slave2 : 2

引用的算法名称

load-balancer-name: alg_random
改为对相应的算法名称
load-balancer-name: alg_weight

执行testSelectAll,

  /**
     * 读数据测试
     */
    @Test
    public void testSelectAll(){
        List<TUser> users1 = userMapper.selectList(null);
        List<TUser> users2 = userMapper.selectList(null);
        List<TUser> users3 = userMapper.selectList(null);
        List<TUser> users4 = userMapper.selectList(null);
        List<TUser> users5 = userMapper.selectList(null);
        List<TUser> users6 = userMapper.selectList(null);
        users1.forEach(System.out::println);
    }

在这里插入图片描述
可以看出六次查询有五次使用了slave2

读写分离全部配置


# 应用名称
spring:
  application:
    name: sharding-jdbc-demo
  profiles:
    active: dev
  shardingsphere:
    mode:
      type: Memory
    props:
      sql-show: true

    # 配置真实数据源
    datasource:
      names: master,slave1,slave2

      # 配置第 1 个数据源
      master:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3506/db_user?allowPublicKeyRetrieval=true&useSSL=false
        username: root
        password: 123456

      # 配置第 2 个数据源
      slave1:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3507/db_user?allowPublicKeyRetrieval=true&useSSL=false
        username: root
        password: 123456

      # 配置第 3 个数据源
      slave2:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3508/db_user?allowPublicKeyRetrieval=true&useSSL=false
        username: root
        password: 123456

    # 读写分离配置
    rules:
      readwrite-splitting:
        data-sources:
          # 读写分离逻辑数据源名称
          myds:
            # 读写分离类型,比如:Static,Dynamic
            type: Static
            props:
              # 写库数据源名称
              write-data-source-name: master
              # 读库数据源名称,多个从数据源用逗号分隔
              read-data-source-names: slave1,slave2
              sql-show: true
            #负载均衡算法名称
            load-balancer-name: alg_random

        # 负载均衡算法配置
        load-balancers:
          alg_round:
            # 轮询算法
            type: ROUND_ROBIN
          alg_random:
            # 随机访问算法
            type: RANDOM
          alg_weight:
            # 权重访问算法
            type: WEIGHT
            props:
              slave1 : 1
              slave2 : 2


  • 14
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值