手把手教你实现MySQL读写分离+故障转移,不信你学不会!(上)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 手把手教你实现MySQL读写分离+故障转移,不信你学不会!(上)

前言


上一篇发了手动搭建Redis集群和MySQL主从同步(非Docker)之后,很多同学对文中主从结构提到的读写分离感兴趣,本打算在双十一期间直接把读写分离分享给大家,奈何工作一直没停下,所以这周抽空把这些分享出来。


关于MySQL的读写分离的实现,有两种方式,第一种方式即我们手动在代码层实现逻辑,来解析读请求或者写请求,分别分发到不同的数据库中,实现读写分离;第二种方式就是基于MyCat中间件来实现读写分离的效果;这两种方式我都会在这篇博客中进行详细地介绍、搭建,并且分析其中的优劣。


原理初探


从MySQL的主从同步开始谈起,最开始我们的数据库架构是这样的。


image.png


主库负责了所有的读写操作,而从库只对主库进行了备份,就像我在上一篇文章中说的那样,我认为如果只实现了一个备份,不能读写分离和故障转移,不能降低Master节点的IO压力,这样的主从架构看起来性价比似乎不是很高。


我们所希望的主从架构是,当我们在写数据时,请求全部发到Master节点上,当我们需要读数据时,请求全部发到Slave节点上。并且多个Slave节点最好可以存在负载均衡,让集群的效率最大化。


那么这样的架构就不够我们使用了,我们需要找寻某种方式,来实现读写分离。那么实际上有两种方式。


方法1:代码层实现读写分离


这种方法的优势就是比较灵活,我们可以按照自己的逻辑来决定读写分离的规则。如果使用了这样的方法,我们整个数据库的架构就可以用下面这张图进行概括:


image.png


方法2:使用中间层(虚拟节点)进行请求的转发


这种方式最主要的特点就是我们在除了数据库以外地方,新构建了一个虚拟节点,而我们所有的请求都发到这个虚拟节点上,由这个虚拟节点来转发读写请求该相应的数据库。


这种方式的特点就是,其构建了一个独立的节点来接收所有的请求,而不用在我们的程序中配置多数据源,我们的项目只需要将url指向这个虚拟节点,然后由这个虚拟节点来处理读写请求。不是有这么一句话吗,专业的事交给专业的人来做,大概是这么个意思吧。而现在存在的MyCat等中间件,就是这样的一个”专业的人“。


image.png


那么下面我就会动手实现上述两个读写分离的解决方案,代码层实现读写分离和使用中间件实现读写分离


手动实现读写分离


实现读写分离的方法有很多,我这里会说到两种,第一种是使用MyBatis和Spring,手写MyBatis拦截器来判断SQL是读或者写,从而选择数据源,最后交给Spring注入数据源,来实现读写分离;第二种是使用MyCat中间件,配置化地实现读写分离,每种方式都有其可取之处,可以自己视情况选用。


环境说明


这里用到了我的上篇博客手动搭建Redis集群和MySQL主从同步(非Docker)中所搭建的MySQL主从同步,如果手上没有这套环境的,可以先比着这篇博客进行搭建。但是需要

注意的是,要将8.0版本的MySQL改为5.7。


192.168.43.201:3306 Master

192.168.43.202:3306 Slave


开发环境:


IDE:Eclipse

Spring boot 2.1.7

MySQL 5.7

CentOS 7.3


新建Maven项目


为了演示方便,这里使用SpringBoot作为测试的基础框架,省去了很多Spring需要的xml配置。没有用过SpringBoot的同学也没关系,我会一步一步地进行演示操作。


导入依赖


<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencies>
        <!-- Web相关 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 数据库相关 -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc7</artifactId>
            <version>12.1.0</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 测试相关依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!-- -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>
                spring-boot-configuration-processor
            </artifactId>
            <optional>true</optional>
        </dependency>
</dependencies>

application.yml

为了测试项目尽量简单,所以我们不用去过多地配置其它东西。只有一些基本配置和数据源配置。

server: 
  port: 10001
spring: 
  datasource:
    url: jdbc:mysql://192.168.43.201:3306/springtestdemo?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
    username: Object
    password: Object971103.
    driver-class-name: com.mysql.cj.jdbc.Driver
#MyBatis配置
mybatis:
  mapper-locations: classpath:mapper/*.xml
  configuration:
    map-underscore-to-camel-case: true


编写启动类


@SpringBootApplication
public class ApplicationStarter {
    public static void main(String[] args) {
        SpringApplication.run(ApplicationStarter.class, args);
    }
}


启动


image.png


出现以上信息代表启动成功。嗯……这应该是一个数据库相关的博客,好像讲了太多的SpringBoot


到这里说明我们的SpringBoot项目没有问题,已经搭建成功,如果还不放心,可以自行访问一下http://localhost:10001这个路径,如果出现SpringBoot的404,则代表启动成功。


新建Student实体并创建数据库


package cn.objectspace.springtestdemo.domain;
public class Student {
    private String studentId;
    private String studentName;
    public String getStudentId() {
        return studentId;
    }
    public void setStudentId(String studentId) {
        this.studentId = studentId;
    }
    public String getStudentName() {
        return studentName;
    }
    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }   
}


CREATE TABLE student(
    student_id VARCHAR(32),
    student_name VARCHAR(32)
);
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
26天前
|
负载均衡 监控 关系型数据库
MySQL 官宣:支持读写分离了!!
【10月更文挑战第8天】MySQL的读写分离功能显著提升了数据库性能、可用性和可靠性。通过将读写操作分配至不同服务器,有效减轻单个服务器负载,提高响应速度与吞吐量,并增强系统稳定性。此外,它还支持便捷的扩展方式,可通过增加只读服务器提升读操作性能。实现读写分离的方法包括软件层面(如使用数据库中间件)和硬件层面(使用独立服务器)。使用时需注意数据一致性、负载均衡及监控管理等问题。
|
2月前
|
关系型数据库 MySQL Java
MySQL主从复制实现读写分离
MySQL主从复制(二进制日志)、 Sharding-JDBC实现读写分离
MySQL主从复制实现读写分离
|
3月前
|
SQL 关系型数据库 MySQL
(二十五)MySQL主从实践篇:超详细版读写分离、双主热备架构搭建教学
在上篇《主从原理篇》中,基本上把主从复制原理、主从架构模式、数据同步方式、复制技术优化.....等各类细枝末节讲清楚了,本章则准备真正对聊到的几种主从模式落地实践,但实践的内容通常比较枯燥乏味,因为就是调整各种配置、设置各种参数等步骤。
461 2
|
3月前
|
关系型数据库 MySQL PHP
开发者必看:MySQL主从复制与Laravel读写分离的完美搭配
开发者必看:MySQL主从复制与Laravel读写分离的完美搭配
66 2
|
3月前
|
SQL 关系型数据库 MySQL
mysql读写分离,主从同步
本文介绍了如何在Laravel项目中配置数据库读写分离,并实现MySQL主从同步。主要步骤包括:在`config/database.php`中设置读写分离配置;为主机授予从机访问权限;配置各MySQL服务器的`/etc/my.cnf`文件以确保唯一的`server-id`;以及通过SQL命令设置主从关系并启动从服务。文章还针对一些常见错误提供了排查方法。最后通过验证确认主从同步是否成功。[原文链接](https://juejin.cn/post/6901581801458958344)。版权所有者为作者佤邦帮主,转载请遵循相关规定。
|
3月前
|
cobar 关系型数据库 MySQL
使用MyCat实现MySQL主从读写分离(一)概述
【8月更文挑战第11天】MySQL读写分离通过主从复制分散负载,主库负责写操作,从库承担读查询,以复制技术确保数据一致性。此策略有效缓解锁竞争,提升查询效能并增强系统可用性。实现方式包括应用层处理,简便快捷但灵活性受限;或采用中间件如MyCAT、Vitess等,支持复杂场景但需专业团队维护。
87 0
|
3月前
|
SQL 关系型数据库 MySQL
基于proxysql实现MySQL读写分离
基于proxysql实现MySQL读写分离
|
18天前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
74 6
|
15天前
|
存储 关系型数据库 MySQL
Mysql(4)—数据库索引
数据库索引是用于提高数据检索效率的数据结构,类似于书籍中的索引。它允许用户快速找到数据,而无需扫描整个表。MySQL中的索引可以显著提升查询速度,使数据库操作更加高效。索引的发展经历了从无索引、简单索引到B-树、哈希索引、位图索引、全文索引等多个阶段。
50 3
Mysql(4)—数据库索引
|
18天前
|
SQL Ubuntu 关系型数据库
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
本文为MySQL学习笔记,介绍了数据库的基本概念,包括行、列、主键等,并解释了C/S和B/S架构以及SQL语言的分类。接着,指导如何在Windows和Ubuntu系统上安装MySQL,并提供了启动、停止和重启服务的命令。文章还涵盖了Navicat的使用,包括安装、登录和新建表格等步骤。最后,介绍了MySQL中的数据类型和字段约束,如主键、外键、非空和唯一等。
56 3
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用