从单机到集群

单机问题

  • 容量有限,难以扩容
  • 读写压力,QPS过大,特别是分析类需求会影响业务事务
    • OLTP OnLineTransactionProcessing 联机事务处理,处理一线业务
    • OLAP OnLineAnalyticalProcessing 联机分析处理,分析决策
  • 可用性不足,宕机问题

    技术演进

    技术演进.png

    主从复制

    原理

  • 主库写binlog

  • 从库relaylog,分离IO和SQL线程
  • 后面引入了半同步和MGR

主从复制.png

binlog格式

  • ROW
    • 记录详细但日志量会比较大
  • Statement
    • 只是记录SQL,记录简单
    • 没有查询语句
  • Mixed

    1. # 查看binlog
    2. mysqlbinlog -vv mysql-bin.000005

    0异步复制

  • 传统的主从复制即PrimarySecondaryReplication

  • 异步复制:网络或机器故障,会造成数据不一致
  • 局限性
    • 主从延时问题
      • 只能数据分片,把数据量做小
    • 应用侧需要配合读写分离框架
    • 不解决高可用问题

异步复制.png

1半同步复制

  • 需要启用插件
  • 保证source和replica最终一致性
  • 半同步是指至少有一个从库收到了log主库才能commit

半同步复制.png

2组复制

  • MGR(MySQLGroupReplication)
  • 基于分布式Paxos协议实现,保证数据一致性

组复制.png

演示

  1. ### 主从复制演示
  2. [TOC]
  3. #### 准备两个MySQL服务实例
  4. > windows上可以用压缩版本,例如mysql-5.7.31-winx64.zip,解压文件夹再复制一份,添加my.ini配置文件。假设一个叫mysql-5.7.31-winx64,一个叫mysql-5.7.31-winx64-2,以为分别配置其为主和从。
  5. >
  6. > MacLinux环境,自己想办法,也可以用docker
  7. #### 修改主mysql-5.7.31-winx64的my.ini

basedir = ./ datadir = ./data port = 3306 server_id = 1

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES log_bin=mysql-bin binlog-format=Row




#### 修改从mysql-5.7.31-winx64-2的my.ini

basedir = ./ datadir = ./data port = 3316 server_id = 2

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES log_bin=mysql-bin binlog-format=Row




#### 初始化和启动数据库

空数据库需要执行mysqld --initialize-insecure 进行初始化。

分别启动主和从,在命令行下直接执行mysqld或start mysqld命令即可。



#### 配置主节点

mysql命令登录到主节点:mysql -uroot -P3306

mysql> CREATE USER ‘repl’@’%’ IDENTIFIED BY ‘123456’; Query OK, 0 rows affected (0.11 sec)

mysql> GRANT REPLICATION SLAVE ON . TO ‘repl’@’%’; Query OK, 0 rows affected (0.12 sec)

mysql> flush privileges; Query OK, 0 rows affected (0.10 sec)

mysql> show master status; +—————————+—————+———————+—————————+—————————-+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +—————————+—————+———————+—————————+—————————-+ | mysql-bin.000003 | 305 | | | | +—————————+—————+———————+—————————+—————————-+ 1 row in set (0.00 sec)


创建数据库:create schema db;



#### 配置从节点

mysql命令登录到从节点:mysql -uroot -P3316

CHANGE MASTER TO MASTER_HOST=’localhost’,
MASTER_PORT = 3306, MASTER_USER=’repl’,
MASTER_PASSWORD=’123456’,
MASTER_LOG_FILE=’mysql-bin.000003’, MASTER_LOG_POS=305;

//MASTER_AUTO_POSITION = 1;

创建数据库:create schema db;



#### 验证操作

在主库执行:

mysql> use db Database changed mysql> create table t1(id int); Query OK, 0 rows affected (0.17 sec)

mysql> mysql> mysql> insert into t1(id) values(1),(2); Query OK, 2 rows affected (0.04 sec)




在从库查看数据同步情况

mysql> use db Database changed mysql> mysql> mysql> show tables; +———————+ | Tables_in_db | +———————+ | t1 | +———————+ 1 row in set (0.00 sec)

mysql> mysql> mysql> select * from t1; +———+ | id | +———+ | 1 | | 2 | +———+ 2 rows in set (0.00 sec)




#### 查看命令

可以通过show master status\G, show slave status\G 查看状态

可以能改过stop slave; start slave;来停止复制。



#### 其他

GTID与复制:

https://blog.51cto.com/13540167/2086045

https://www.cnblogs.com/zping/p/10789151.html

半同步复制:

https://www.cnblogs.com/zero-gg/p/9057092.html

组复制:

https://www.cnblogs.com/lvxqxin/p/9407080.html

相关命令

show master status\G;
show slave status\G;

stop slave;

drop table t1;

CHANGE MASTER TO
    MASTER_HOST='localhost',  
    MASTER_PORT = 3306,
    MASTER_USER='repl',      
    MASTER_PASSWORD='123456',   
    MASTER_LOG_FILE='mysql-bin.000003',
    MASTER_LOG_POS=305;

show tables;
start slave;

create table t3 like test.t2; // 拷贝表结构
show create table t3; //查看表创建语句

show plugins;// 查看插件,半同步和组复制都是插件

读写分离

动态切换数据源版本1.0

  • 基于Spring,配置多个数据源(例如两个,master和slave)
  • 根据具体的service方法是否会操作数据,注入不同的数据源

    改进1.1

  • 基于操作AbstractRoutingDataSource和自定义注解类readOnly之类的,简化自动切换数据源

动态切换数据源.png

改进1.2

  • 支持配置多个从库

    改进1.3

  • 支持多个从库的负载均衡

    不足

  • 侵入性比较强

  • 降低侵入性会导致“写完读”不一致的问题

    数据库框架版本2.0

  • ShardingSphere-jdbc的master-slave功能

  • SQL解析和事务管理,自动实现读写分离
  • 解决“写完读”不一致的问题(遇到写操作后后面的所有操作都走主库)

    不足

  • 对业务系统还是有侵入

  • 对已存在的旧系统改造不友好

ShardingSphere-jdbc.png

数据库中间件版本3.0

  • MyCat/ShardingSphere-Proxy的master/slave功能
  • 需要部署一个中间件,规则配置在中间件,中间件完全替换原来的数据库
  • 模拟一个MySQL服务器,对业务系统无侵入
  • 适用于非Java环境

    高可用

    为什么要高可用

  • 读写分离,提升读的处理能力

  • 故障转移,提供failover能力
  • 业务侧连接池的心跳重试,实现断线重连,业务不间断,降低RTO和RPO

    常见策略

  • 多个实例不在一个主机/机架上

  • 跨机房和可用区部署
  • 两地三中心

    MySQL高可用0:主从手动切换

  • 实现

    • 如果主节点挂掉,手动将某个从改成主
    • 重新配置其他从节点
    • 修改应用数据源配置
  • 问题

    • 可能数据不一致
    • 需要人工敢于
    • 代码和配置的侵入性

      MySQL高可用1:主从手动切换

  • 实现

    • 用LVS+Keepalived实现多个节点的探活+请求路由
    • 配置VIP或DNS实现配置不变更
  • 问题

    • 手工处理主从切换
    • 大量的配置的脚本定义

      MySQL高可用2:MHA

  • 实现

    • MasterHighAvailability
    • 相对成熟的高可用解决方案
    • 基于Perl语言开发,一般能在30s内实现主从切换
    • 切换时直接通过SSH复制主节点的日志
  • 问题

    • 需要配置SSH信息
    • 至少3台

      MySQL高可用3:MGR

  • 实现

    • 如果主节点挂掉,将自动选择某个从改成主
    • 无需人工干预,基于组复制实现的分布式Paxos协议,保证数据一致性
    • 支持单主模式和多主模式
  • 问题

    • 外部获得状态变更需要读取数据库
    • 外部需要使用LVS/VIP配置

      MySQL高可用4:MySQL Cluster

  • 实现

    • 完整的高可用解决方案,包括以下几个组件
      • MGR:提供DB的扩展和自动故障转移
      • MySQL Router:轻量级中间件,提供应用程序连接目标的故障转移
      • MySQL Shell:新的客户端,多种接口模式,可设置MGR和Router

        MySQL高可用5:Orchestrator

  • 实现

    • 高可用和管理工具
    • 提供web界面
    • 检测异常可自动/手动修复