前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >springboot实战之mysql读写分离

springboot实战之mysql读写分离

作者头像
lyb-geek
发布2019-10-22 16:47:00
2.3K0
发布2019-10-22 16:47:00
举报
文章被收录于专栏:Linyb极客之路Linyb极客之路
什么是读写分离

读写分离,基本的原理是让主数据库处理事务性增、改、删操作,而从数据库处理SELECT查询操作,让两者分工明确达到提高数据库整体读写性能。当然,主数据库另外一个功能就是负责将事务性查询导致的数据变更同步到从库中,也就是写操作。即主从复制和读写分离是离不开的。

mysql主从复制原理

ps:mysql的主从复制配置,不在本文讨论范围之内。不过如果对mysql主从如何配置感兴趣的朋友,可以查看这篇文章

https://www.jianshu.com/p/1ac435a6510e

什么时候需要读写分离

  • 1、在高并发情况,当业务量非常大时,一台服务器的性能无法满足需求,就可以通过配置主从复制实现写分离来分摊负载,避免因负载太高而造成无法及时响应请求。
  • 2、读远比写多的场景

当有出现上述场景时,可以考虑用读写分离,但也并非一上来就采用读写分离,我们可以优先考虑优化我们的代码逻辑,根据慢查询日志来优化sql语句,引入缓存层如redis,甚至可以引入全文搜索引擎等

读写分离类型

基于程序代码内部实现

在代码中根据select,insert进行路由分类,这类方法也是目前生产环境应用最广泛的,优点是性能好,因为在程序代码中已经将读写的数据源拆分至两个,所以不需要额外的mysql proxy解析sql报文,在进行路由至不同数据库节点。缺点是通常该架构较复杂,运维成本相对较高。

基于中间代理层实现

代理层一般位于客户端和服务器之间,代理服务器接到客户端请求后通过解析sql文本再将sql路由至可用的数据库节点中。优点是程序不需要改造可以实现无缝迁移,可移植性较好。缺点是性能相对前者略微逊色一些,并且并不是所有的读操作都能够被路由至从节点中。

本文主要介绍基于程序代码的实现,下边进行代码层面整合介绍

读写分离实现

这边介绍三种代码层读写分离实现

  • 第一种方法基于spring提供原生的AbstractRoutingDataSource搭配AOP进行实现
  • 第二种方法使用mybatis-plus提供的dynamic-datasource-spring-boot-starter进行实现
  • 第三种方法使用Sharding-JDBC进行实现

1、采用AbstractRoutingDataSource搭配AOP

该方案在之前文章spring多数据源实现一文就有介绍,之前是以xml文件配置,本文是改成javaconfig配置,其实现原理一样。因此就不再论述,其实现具体可以查看链接

http://1t.click/azCR

2、mybatis-plus提供的dynamic-datasource-spring-boot-starter

a、pom.xml

代码语言:javascript
复制
<dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    </dependency>

b、application.yml配置

代码语言:javascript
复制
spring:
  datasource:
    dynamic:
      primary: leader
      datasource:
        leader:
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/boot-learning?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&serverTimezone=UTC
          druid: #以下均为默认值
            initial-size: 3
            max-active: 8
            min-idle: 2
            max-wait: -1
            min-evictable-idle-time-millis: 30000
            max-evictable-idle-time-millis: 30000
            time-between-eviction-runs-millis: 0
            validation-query: select 1
            validation-query-timeout: -1
            test-on-borrow: false
            test-on-return: false
            test-while-idle: true
            pool-prepared-statements: true
            max-open-prepared-statements: 100
            filters: stat,wall
            share-prepared-statements: true
        follow:
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/springboot-learning?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&serverTimezone=UTC
          druid: #以下均为默认值
            initial-size: 3
            max-active: 8
            min-idle: 2
            max-wait: -1
            min-evictable-idle-time-millis: 30000
            max-evictable-idle-time-millis: 30000
            time-between-eviction-runs-millis: 0
            validation-query: select 1
            validation-query-timeout: -1
            test-on-borrow: false
            test-on-return: false
            test-while-idle: true
            pool-prepared-statements: true
            max-open-prepared-statements: 100
            filters: stat,wall
            share-prepared-statements: true
            #DruidDataSourceAutoConfigure会注入一个DataSourceWrapper,其会在原生的spring.datasource下找url,username,password等。而我们动态数据源的配置路径是变化的。
  autoconfigure:
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure,io.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration

3、在service层加上 @DS注解,通过@DS制定要操作的数据库

代码语言:javascript
复制
@Override
  @Transactional
  @DS("follow")
  public BookDTO addBook(BookDTO bookDTO) {
    Book book = dozerMapper.map(bookDTO,Book.class);
    boolean isExitBookByName = ObjectUtils.isNotEmpty(getBookByName(bookDTO.getBookName()));
    if(isExitBookByName){
      throw new BizException("书名已经存在");
    }
    book.setCreateDate(new Date());
    book.setUpdateDate(new Date());
    baseMapper.insert(book);

    bookDTO = dozerMapper.map(book,BookDTO.class);

    return bookDTO;
  }

通过上面3步就可以实现读写分离,更多实现细节可以查看如下链接

https://mp.baomidou.com/guide/dynamic-datasource.html

3、通过Sharding-JDBC实现

架构图

a、pom.xml

代码语言:javascript
复制
<dependency>
      <groupId>io.shardingsphere</groupId>
      <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    </dependency>

b、application.yml配置

代码语言:javascript
复制
sharding:
  jdbc:
    datasource:
      #Canonical names should be kebab-case ('-' separated), lowercase alpha-numeric characters and must start with a letter
      names: master-ds,slave-ds
      master-ds:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/boot-learning?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&serverTimezone=UTC
        username: root
        password: 123456
      slave-ds:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/springboot-learning?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&serverTimezone=UTC
        username: root
        password: 123456
    config:
      sharding:
        props:
          sql.show: true
      masterslave:
        load-balance-algorithm-type: round_robin
        name: dataSource
        master-data-source-name: master-ds
        slave-data-source-names: slave-ds
spring:
  main:
    allow-bean-definition-overriding: true

仅需上面2步,就可以实现读写分离。更多详细配置可以查看如下链接

https://shardingsphere.apache.org/document/current/cn/manual/sharding-jdbc/configuration/config-spring-boot/

总结

以上就是代码层读写分离的几种方案,实现都挺简单的,那这几种方案,到底选哪一种呢,如果你业务是采用mybaits-plus来做dao层,很显然就可以使用上面所述的第二种。如果不是,推荐使用sharding-jdbc来实现。其实本文也就简单介绍下读写分离,推荐大家可以看下这篇博文浅谈高性能数据库集群 —— 读写分离

参考文档

【mysql 读写分离】10分钟了解读写分离的作用

https://blog.csdn.net/u013421629/article/details/78793966

MySQL读写分离最佳实践

https://www.jianshu.com/p/1ac435a6510e

demo链接

https://github.com/lyb-geek/springboot-learning/tree/master/springboot-dynamic-datasource

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linyb极客之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么时候需要读写分离
  • 读写分离类型
  • 读写分离实现
  • 总结
  • 参考文档
  • demo链接
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档