Java之读写分离实现

需求说明

  • 读写分离

    数据库做读写分离,一主多从

解决方案

  • 应用层解决

  • 中间件解决

    Sharding-JDBC

Sharding-JDBC

  • 官网地址

    https://shardingsphere.apache.org/document/current/en/overview/

  • 简介

    Sharding-JDBC定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架

  • 特性

    1. 适用于任何基于Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC

    2. 基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。

    3. 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer和PostgreSQL。

  • 调用流程
    ShardingJDBC调用原理图

  • 其他

    ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成。 他们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如Java同构、异构语言、容器、云原生等各种多样化的应用场景。

实现步骤

MySQL主从复制环境搭建

  • 参考链接

    https://blog.csdn.net/weixin_42586723/article/details/107752844

数据库创建

  • SQL语句

    分别在主从环境创建数据库mbank ,并在主节点mbank库中创建一个user表(此时会在从节点mbank库中自动创建user表),用于数据操作演示

    	CREATE DATABASE IF NOT EXISTS mbank DEFAULT CHARSET utf8 COLLATE utf8_general_ci;
    	USE mbank;
    	DROP TABLE IF EXISTS `user`;
        CREATE TABLE `user`(
            id bigint(64) not null,
            city varchar(20) not null,
            name varchar(20) not null,
            PRIMARY KEY (`id`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    
    
    
    

Maven项目搭建

  • 模块名称
    sjdbc-read-write-springboot

  • pom依赖

    
      <!-- Sharding-JDBC -->
      <dependency>
          <groupId>org.apache.shardingsphere</groupId>
          <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
          <version>4.0.0-RC1</version>
      </dependency>
    
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
    
      <dependency>
          <groupId>org.mybatis.spring.boot</groupId>
          <artifactId>mybatis-spring-boot-starter</artifactId>
          <version>2.0.1</version>
      </dependency>
    
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
      </dependency>
    
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid-spring-boot-starter</artifactId>
          <version>1.1.16</version>
      </dependency>
    
    

数据源配置

  • application配置

    
      server.port=8084
    
      mybatis.config-location=classpath:META-INF/mybatis-config.xml
    
      # 数据源名称集合,对应下面数据源配置的名称
      spring.shardingsphere.datasource.names=master,slave
    
    	# 主数据源
    	spring.shardingsphere.datasource.master.type=com.alibaba.druid.pool.DruidDataSource
    	spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
    	spring.shardingsphere.datasource.master.url=jdbc:mysql://192.168.159.134:3306/mbank?characterEncoding=utf-8
    	spring.shardingsphere.datasource.master.username=root
    	spring.shardingsphere.datasource.master.password=1q2w3e4r
    
    	# 从数据源
    	spring.shardingsphere.datasource.slave.type=com.alibaba.druid.pool.DruidDataSource
    	spring.shardingsphere.datasource.slave.driver-class-name=com.mysql.jdbc.Driver
    	spring.shardingsphere.datasource.slave.url=jdbc:mysql://192.168.159.133:3306/mbank?characterEncoding=utf-8
    	spring.shardingsphere.datasource.slave.username=root
    	spring.shardingsphere.datasource.slave.password=123456
    
    
      # 读写分离配置 load-balance-algorithm-type用于配置从库负载均衡算法类型,可选值:ROUND_ROBIN(轮询),RANDOM(随机)
      spring.shardingsphere.masterslave.load-balance-algorithm-type=round_robin
      # 最终的数据源名称
      spring.shardingsphere.masterslave.name=dataSource
      # 主库数据源名称
      spring.shardingsphere.masterslave.master-data-source-name=master
      # 从库数据源名称列表,多个逗号分割
      spring.shardingsphere.masterslave.slave-data-source-names=slave
    
      # 显示SQL
      spring.shardingsphere.props.sql.show=true
    
    
    
    

测试样例

  • 测试请求

    1. 发送请求
    
      # 请求新增
      http://localhost:8084/add
    
      # 查询列表
      http://localhost:8084/users
    
    
    1. 查看数据库
    
      -- 从库中执行发现已自动新增数据
      select * from user;
    
      -- 在从库中执行新增脚本,并测试查询列表请求,发现存在刚通过脚本新增的数据
    
    

总结

存在问题

  • 读延迟问题

    问题阐述

    系统刚插入一条数据,无法立即读取。因为主节点写入完之后数据是要复制给从节点的,读不到的原因是复制的时间比较长,也就是说数据还没复制到从节点,这时无法读取

    解决方案

    mysql5.7 的主从复制是多线程了,意味着速度会变快,但是不一定能保证百分百马上读取到

    1. 强制走主库查询
    若业务层要求必须实时读取,那么可以通过Sharding-JDBC配置强制走主库进行读取
    
    ```java
    
      public List<User> list() { // 强制路由主库 
    
        HintManager.getInstance().setMasterRouteOnly(); 
        return userRepository.list(); 
    
      }
    
    ```
    
  • 数据同步

    测试代码样例中并不涉及Mysql数据库之间复制,需要另外搭建主从复制的数据库。

参考地址

  • 项目源码地址

    https://github.com/yinjihuan/sharding-jdbc

  • 在IDEA里导入从Github上下载的Maven项目

    https://blog.csdn.net/sikefeng/article/details/80044693

  • Sharding-JDBC:查询量大如何优化

    https://www.cnblogs.com/yinjihuan/p/10965595.html

  • java读写分离的实现

    https://www.cnblogs.com/ngy0217/p/8987508.html

    https://www.cnblogs.com/ningwuyu/p/12091855.html

  • MySQL主从复制

    https://www.jianshu.com/p/19cb0f16dea4

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值