【读写分离?聊聊Mysql多数据源实现读写分离的几种方案】

一.什么是MySQL 读写分离

我记得实习的第一家公司做个一个项目就用过mysql多数据源的读写分离方案(4年前了…依稀记得也是在mapper层面来分离的),但那时候是我同事弄的,完全不懂怎么实现的,觉得他好厉害。从此成了心里的一道坎,很久之前就了解了,一直想着要写篇博客记录下,ok,那赶紧开始吧~
先了解下概念什么是读写分离、优势、实现方式、注意事项、和使用场景。如果项目里面有用到数据库集群,开始有性能方面问题,结合业务场景及综合衡量下去考虑是否适用数据库读写分离方案。
以下解释来自chatgpt,我觉得说的挺好的。

MySQL 读写分离是一种数据库优化策略,通过将数据库的读操作和写操作分开,分别交由不同的数据库实例处理,以提高系统的性能和扩展性。具体来说,读写分离通常涉及一个主数据库(Master)和一个或多个从数据库(Slave),它们通过复制机制保持数据的一致性。
以下是读写分离的核心概念:

  1. 主从复制(Master-Slave Replication)
  • 主库(Master):负责处理所有的写操作(INSERT、UPDATE、DELETE 等),也可以处理读操作。
  • 从库(Slave):主要用于处理读操作(SELECT),不会直接接收写操作。从库通过复制机制从主库同步数据,确保数据一致性。
  1. 读写分离的优势
  • 提高读性能:由于从库处理读操作,可以通过增加从库实例来扩展系统的读性能,减轻主库的负担。
    减少主库压力:写操作集中在主库,从库处理大部分的读操作,主库的压力减少,有助于提高写操作的响应速度。
    容错性:在某些情况下,从库可以用作备份,如果主库出现故障,可以临时将从库提升为主库以保持服务的可用性。
  1. 实现方式
    读写分离可以通过多种方式实现,包括:
  • 手动分离:应用程序通过逻辑代码,手动决定读请求发送到从库,写请求发送到主库。
  • 代理层(中间件):使用数据库中间件(如 MySQL Proxy、MaxScale、MyCat等),在应用和数据库之间自动实现读写分离和负载均衡。
  • 连接池支持:某些数据库连接池(如 Druid、HikariCP)可以自动支持主从库的读写分离。
  1. 注意事项
  • 数据一致性问题:由于复制存在延迟,从库上的数据可能会比主库滞后。如果应用程序对实时数据一致性要求较高,需谨慎处理。
  • 负载均衡:要合理分配读请求到不同的从库,避免单个从库成为瓶颈。
  • 主库故障恢复:需要设计可靠的故障转移机制,确保主库出现问题时,从库能够及时接管。
  1. 使用场景
    读写分离适用于读操作远多于写操作的场景,例如电商平台、社交媒体网站等。在这些场景中,读请求往往占大多数,通过读写分离可以有效提升系统的扩展性和性能。

二.读写分离的几种实现方式(手动控制)

这里只介绍手动分离读写库:应用程序通过逻辑代码,手动决定读请求发送到从库,写请求发送到主库的几种实现方式。

1.基于Spring下的AbstractRoutingDataSource

根据大家平常开发习惯,我还是从controller层开始吧。

1.yml

我的yml配置如下:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    datasource1:
      url: jdbc:mysql://127.0.0.1:3306/tl_mall_master?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
      username: root
      password: 123456
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      driver-class-name: com.mysql.cj.jdbc.Driver
    datasource2:
      url: jdbc:mysql://127.0.0.1:3306/tl_mall_slave?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
      username: root
      password: 123456
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      driver-class-name: com.mysql.cj.jdbc.Driver
2.Controller
@RestController
@RequestMapping("friend")
@Slf4j
public class FriendController {
   

    @Autowired
    private FriendService friendService;

    @GetMapping(value = "select")
    public List<Friend> select(){
   
        return friendService.list();
    }


    @GetMapping(value = "insert")
    public String in(){
   
        Friend friend = new Friend();
        friend.setName("jinbiao666");
        friendService.save(friend);
        return "主库插入成功";
    }
}
3.Service实现
@Service
public class FriendImplService implements FriendService {
   

    @Autowired
    FriendMapper friendMapper;

    @Override
    @WR("R")        // 库2
    public List<Friend> list() {
   
        return friendMapper.list();
    }

    @Override
    @WR("W")        // 库1
    public void save(Friend friend) {
   
        friendMapper.save(friend);
    }
}
4.Mapper层
public interface FriendMapper {
   
    @Select("SELECT * FROM friend")
    List<Friend> list();

    @Insert("INSERT INTO  friend(`name`) VALUES (#{name})")
    void save(Friend friend);
}
5.定义多数据源
@Configuration
public class DataSourceConfig {
   

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource1")
    public DataSource dataSource1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值