推广

Spring Boot demo系列(十二):ShardingSphere + MyBatisPlus 读写分离 + 主从复制

iseeyu3年前 (2024-02-21)推广135

在这里插入图片描述

工作流程如下:

  • 主库修改数据后,将修改日志写入binlog
  • 从库的I/O线程读取主库的binlog,并拷贝到从库本地的binlog中
  • 从库本地的binlog被SQL线程读取,执行其中的内容并同步到从库中

3.3 数据库中间件简介

数据库中间件可以简化对读写分离以及分库分表的操作,并隐藏底层实现细节,可以像操作单库单表那样操作多库多表,主流的设计方案主要有两种:

  • 服务端代理:需要独立部署一个代理服务,该代理服务后面管理多个数据库实例,在应用中通过一个数据源与该代理服务器建立连接,由该代理去操作底层数据库,并返回相应结果。优点是支持多语言,对业务透明,缺点是实现复杂,实现难度大,同时代理需要确保自身高可用
  • 客户端代理:在连接池或数据库驱动上进行一层封装,内部与不同的数据库建立连接,并对SQL进行必要的操作,比如读写分离选择走主库还是从库,分库分表select后如何聚合结果。优点是实现简单,天然去中心化,缺点是支持语言较少,版本升级困难

一些常见的数据库中间件如下:

  • Cobar:阿里开源的关系型数据库分布式服务中间件,已停更
  • DRDS:脱胎于Cobar,全称分布式关系型数据库服务
  • MyCat:开源数据库中间件,目前更新了MyCat2版本
  • Atlas:Qihoo 360公司Web平台部基础架构团队开发维护的一个基于MySQL协议的数据中间层项目,同时还有一个NoSQL的版本,叫Pika
  • tddl:阿里巴巴自主研发的分布式数据库服务
  • Sharding-JDBC:ShardingShpere的一个子产品,一个轻量级Java框架

4 MySQL主从复制环境准备

看完了一些基础理论就可以进行动手了,本小节先准备好MySQL主从复制的环境,基于Docker+MySQL官方文档搭建。

4.1 主库操作

4.1.1 拉取镜像并创建容器运行

docker pull mysql
docker run -itd -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name mysql-master mysql
docker exec -it mysql-master /bin/bash

在主库中进行更新镜像源,安装vim以及net-tools的操作:

cd /etc/apt
echo deb http://mirrors.aliyun.com/debian/ buster main non-free contrib deb-src http://mirrors.aliyun.com/debian/ buster main non-free contrib deb http://mirrors.aliyun.com/debian-security buster/updates main deb-src http://mirrors.aliyun.com/debian-security buster/updates main deb http://mirrors.aliyun.com/debian/ buster-updates main non-free contrib deb-src http://mirrors.aliyun.com/debian/ buster-updates main non-free contrib deb http://mirrors.aliyun.com/debian/ buster-backports main non-free contrib deb-src http://mirrors.aliyun.com/debian/ buster-backports main non-free contrib > sources.list
apt update && apt upgrade
apt install vim net-tools

4.1.2 修改配置文件

vim /etc/mysql/my.cnf

添加下面两行数据:

[mysqld]
server-id=1                # 全局唯一,取值[1,2^32-1],默认为1
binlog-do-db=test          # 表示需要复制的是哪个库

修改完成后重启。

4.1.3 准备数据源

create database test;
use test;
create table user(
    id int primary key auto_increment,
    name varchar(30) not null,
    age int not null
);

4.1.4 创建一个复制操作的用户(可选但推荐)

注意创建用户需要加上mysql_native_password,否则会导致从库一直处于连接状态:

create user 'repl'@'172.17.0.3' identified with mysql_native_password by '123456';
grant replication slave on *.* to 'repl'@'172.17.0.3';

具体的地址请根据从库的地址修改,可以先看后面的从库配置部分。

4.1.5 数据备份(可选)

如果原来的主库中是有数据的,那么这部分数据需要手动同步到从库中:

flush tables with read lock;

开启主库的另一个终端,使用mysqldump导出:

mysqldump -u root -p --all-databases --master-data > dbdump.db

导出完成后,解除读锁:

unlock tables;

4.1.6 查看主库状态

show master status;

在这里插入图片描述

需要把File以及Position记录下来,后面从库的配置需要用到。

4.2 从库操作

4.2.1 拉取镜像并创建容器运行

docker pull mysql
docker run -itd -p 3307:3306 -p 33061:33060 -e MYSQL_ROOT_PASSWORD=123456 --name mysql-slave mysql
docker exec -it mysql-slave /bin/bash

进入容器后,像主库一样更新源然后安装vim和net-tools:

cd /etc/apt
echo deb http://mirrors.aliyun.com/debian/ buster main non-free contrib deb-src http://mirrors.aliyun.com/debian/ buster main non-free contrib deb http://mirrors.aliyun.com/debian-security buster/updates main deb-src http://mirrors.aliyun.com/debian-security buster/updates main deb http://mirrors.aliyun.com/debian/ buster-updates main non-free contrib deb-src http://mirrors.aliyun.com/debian/ buster-updates main non-free contrib deb http://mirrors.aliyun.com/debian/ buster-backports main non-free contrib deb-src http://mirrors.aliyun.com/debian/ buster-backports main non-free contrib > sources.list
apt update && apt upgrade
apt install vim net-tools

4.2.2 修改配置文件

vim /etc/mysql/my.cnf

添加如下两行:

[mysqld]
server-id=2            # 全局唯一,不能与主库相同
replicate-do-db=test   # 与主库相同,表示对该库进行复制

修改完成后重启。

4.2.3 查看ip地址

查看从库的ip地址,用于给主库设置同步的用户:

ifconfig

输出:

inet 172.17.0.3  netmask 255.255.0.0  broadcast 172.17.255.255

那么主库中用于复制的用户就可以是repl@172.17.0.3。

4.2.4 导入数据(可选)

如果主库有数据可以先导入到从库:

mysqldump -u root -p --all-databases < dbdump.db

4.2.5 准备数据源

create database test;
use test;
create table user(
    id int primary key auto_increment,
    name varchar(30) not null,
    age int not null
);

4.2.6 设置主库

可以使用change master to/change replication source to(8.0.23+)命令:

change replication source to 
source_host='172.17.0.2',                   # 可以使用ifconfig查看主库ip
source_user='repl',                         # 之前主库创建的用户
source_password='123456',                   # 密码
source_log_file='binlog.000003',            # 之前在主库上使用show master status查看的日志文件
source_log_pos=594;                         # 同样使用show master status查看

4.2.7 开启从库

start slave;
show slave status\G

新版本(8.0.22+)可使用:

start replica;
show replica status\G

需要IO和SQL线程显示Yes才算成功:

在这里插入图片描述

4.3 测试

主库选择插入一条数据:

insert into user values(1,"name",3);

然后从库就能select到了:

在这里插入图片描述

5 搭建Spring Boot环境

5.1 新建项目并引入依赖

新建Spring Boot项目,并引入如下依赖:

implementation 'com.baomidou:mybatis-plus-boot-starter:3.4.3.1'
implementation 'com.baomidou:mybatis-plus-generator:3.5.0'
implementation 'org.apache.velocity:velocity-engine-core:2.3'
implementation 'org.realityforge.org.jetbrains.annotations:org.jetbrains.annotations:1.7.0'
implementation 'com.alibaba:druid:1.2.6' # 注意不能使用druid的starter依赖,会出现模板找不到的问题
implementation 'org.apache.shardingsphere:sharding-jdbc-spring-boot-starter:4.1.1'

Maven版本:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3.1</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.0</version>
</dependency>
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.3</version>
</dependency>
<dependency>
    <groupId>org.realityforge.org.jetbrains.annotations</groupId>
    <artifactId>org.jetbrains.annotations</artifactId>
    <version>1.7.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.6</version>
</dependency>
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>

5.2 使用生成器

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;

public class MyBatisPlusGenerator {
    public static void main(String[] args) {
        DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder("jdbc:mysql://localhost:3306/test","root","123456").build();
        String projectPath = System.getProperty("user.dir");
        GlobalConfig globalConfig = new GlobalConfig.Builder().outputDir(projectPath+"/src/main/java").openDir(false).build();
        PackageConfig packageConfig = new PackageConfig.Builder().moduleName("test").parent("com.example.demo").build();
        AutoGenerator autoGenerator = new AutoGenerator(dataSourceConfig);
        autoGenerator.global(globalConfig).packageInfo(packageConfig);
        autoGenerator.execute();
    }
}

直接运行main方法即可生成代码,配置请根据个人需要进行更改,更详细的配置可以参考笔者的另一篇文章。

5.3 配置文件

spring:
  shardingsphere:
    datasource:
      names: master,slave                                   # 数据源名字
      master:
        type: com.alibaba.druid.pool.DruidDataSource        # 连接池
        url: jdbc:mysql://127.0.0.1:3306/test               # 主库地址
        username: root                                      # 主库用户名
        password: 123456                                    # 主库密码
      slave:
        type: com.alibaba.druid.pool.DruidDataSource        # 连接池
        url: jdbc:mysql://127.0.0.1:3307/test               # 从库地址
        username: root
        password: 123456
    masterslave:
      load-balance-algorithm-type: round_robin              # 负载均衡算法,
      name: ms
      master-data-source-name: master                       # 主库数据源名字
      slave-data-source-names: slave                        # 从库数据源名字
    props:
      sql:
        show: true                                          # 打印SQL

关于负载均衡算法,目前只支持两种:

在这里插入图片描述

5.4 准备Controller

@RestController
@RequestMapping("/test/user")
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class UserController {
    private final UserServiceImpl userService;
    @GetMapping("/write")
    public boolean write(){
        return userService.save(User.builder().age(3).name("234").build());
    }

    @GetMapping("/read")
    public User read(){
        return userService.getById(1);
    }
}

6 测试

访问http://localhost:8080/test/user/write,可以看到写操作在主库进行:

在这里插入图片描述

访问http://localhost:8080/test/user/read,可以看到读操作在从库进行:

在这里插入图片描述

这样读写分离就算是可以了。

7 参考源码

Java版:

  • Github
  • 码云
  • CODE CHINA

Kotlin版:

  • Github
  • 码云
  • CODE CHINA

8 参考

  • MySQL 官方文档
  • 腾讯云-面试题:你们有没有做 MySQL 读写分离?如何实现 MySQL 的读写分离?
  • 知乎-数据库中间件详解(精品长文)

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/57506.html

相关文章

西安企业做百度推广,一个月花三千和花三万到底差在哪?

4|最近跟几个西安的老板聊天,发现一个挺有意思的现象:同样做百度推广,有人一个月花三千块,询盘不断;有人一个月砸三万,水花都没见着。问他们区别在哪,大多数人说不清楚,只知道'钱花了,没效果'。 5| 6|百度推广这东西,说复杂也复杂,说简单也简单。核心就一件事:让你的潜在客户搜某个词的时候,你的信息...

我想当策划,大学应该选什么专业?

我想当策划,大学应该选什么专业?

学,广告,传播,公关,这些专业其实都可以。另外也可以学像汉语言文学,以及一些跟文学相关的一些专业,会对你找工作有帮助。但是,你想从事这个这份职业,除了专业的学习之外,更多的是,你要在上学的时候积极参与一些更营销策划相关的社会实践。比如说你可以做一些兼职,比如说帮别人去写稿,...

服装市场营销策略分析,“定位不慎满盘皆输”

服装市场营销策略分析,“定位不慎满盘皆输”

不同的区域需要不同的策略,而不同的营销策略需要不同的销售思路来配合。因此,在研究女装产品销售思路之前,最好先对于市场与营销策略做一次深入地了解。1.市场区域化(market segmentation):目标营销的第一步,是将整个市场拆分成若干个同性质的小市场。2.目标市场的...

晚间悦读丨你的思维方式,决定你的人生高度!

晚间悦读丨你的思维方式,决定你的人生高度!

越长大,越发现,能够决定你人生高度的,往往是你的认知层次。 你的认知在哪个层级,你的人生就处在什么状态。你认知的高度,决定了你人生的高度。 那如何才能升级方式、提升认知能力呢?可以从这三个方面做出改变。 NO. 1 改变态度 有人...

编写项目营销策划方案六大要点

编写项目营销策划方案六大要点

现在商业发展非常迅速,的需求非常的大,但是要做好营销策划是有一定难度的,我把自己做营销策划的一些体会在这里分享给朋友们。营销策划方案六大要点我们先说项目营销策划方案这个话题。大部分的营销策划人都是在企业里工作,大部分项目之初都是来源于一个想法,创始人、老板或者创始团队的一个...

【商场营销策划】如何进行商场营销策划?

【商场营销策划】如何进行商场营销策划?

商场是策划者们关注的永恒话题,那么究竟该如何作好商场营销策划呢?掌握以下这几点营销策略设计原则,至关重要!1.义利兼顾的原则。商场在获取利润的同时要充分考虑到消费者的合法利益和商场的长远利益。在作商场活动营销策略方案的时候应该将这一点作为首要的原则。对商场有利而对顾客不利的...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片