单机MySQL面临的问题

问题 解决方案
读写压力 多机集群 主从复制
高可用性 故障转移 主从切换
容量不够 数据库拆分 分库分表

为了解决以上问题,引入集群后,带来一个事务问题。
一致性事务问题,主要有两个方向的解决方案:

  • XA事务(强一致性事务)
  • 柔性事务(弱一致性事务)

    主从复制

    核心:

  • 主库 写binlog

  • 从库订阅binlog,将其拉取到本地存为relay log

    主从复制原理

    异步复制

    从库拉倒binlog后,执行情况与主库是完全隔离的,是否执行完整、成功,主库是不知道的。
    这就可能导致主从库数据不一致
    image.png

半同步复制

需要手动启用插件,mysql默认不开启。
image.png

  1. 只有主库收到了任一从库的ack后,才会继续提交。
  2. 当主库速度比从库快很多

    组复制 MySQL Group Replication (MGR)

    image.png

  3. 基于分布式Paxos协议实现组复制,保证数据一致性

  4. 加入了certify验证环节,保证数据一致性

读写分离

Spring版本

  1. 基于Spring/Spring Boot 配置多个数据源,使用 AbstractRoutingDataSource
  2. 在Service层根据业务操作数据

问题:

  1. 侵入性太强,配置代码太多
  2. 如果降低侵入性,会有”写完读”不一致问题

    写完读不一致 读写分离场景下,写数据走主库,再自动同步给从库;读数据走从库。 而主从同步需要一定时间,而如果插入一条数据后,立马读取这条数据,很可能在读的时候,还没同步到从库,就会出现写完读不一致问题

解决方式:
引入ShardingSphere-jdbc的Master-Slave功能

版本2.0

引入框架
使用ShardingSphere-jdbc

问题:

  1. 还是要修改原有业务系统
  2. 旧系统不好升级

版本3.0

引入中间件
ShardingSphere-Proxy

  1. 部署中间件,规则配置在中间件中
  2. 模拟一个MySQL服务器,对业务系统无侵入

MySQL高可用

故障转移
灾难恢复
容灾:热备/冷备
常见策略:

  1. 多机部署
  2. 跨机房、跨地区部署
  3. 两地三中心容灾高可用方案

高可用方案

方案0

简单的主从复制,分散压力,增加节点备份。

如果主节点挂掉,手动切换节点,主动修改配置
问题:

  1. 主从不一致
  2. 需要人工干预

    方案1

    具备自动故障转移的组从复制

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

问题:

  1. 手工处理主从切换
  2. 大量的配置和脚本

方案2:MHA

Master High Available
高可用环境下用于故障切换和主从提升。
一般30s内实现主动切换,切换时,直接通过SSH复制主节点日志

问题

  1. 需要配置SSH
  2. 至少3台机器(1主2从)

方案3 MGR

MGR
MySQL Group Replication,组复制
如果主节点挂掉,自动选择某个从库为主库。
无需人工干预,基于组复制,保证数据一致性

特点:

  • 高一致性:基于分布式Paxos协议实现组复制
  • 高容错性:自动检测机制,只要不是大多数节点宕机就可以继续工作,内置防脑裂保护机制
  • 高扩展性:节点的增加、移除会自动更新组成员信息,新节点加入后可自动同步增量数据
  • 高灵活性:提供单主模式和多主模式
    • 单主模式在主库宕机后能够自动选主,所有写入都在主节点进行
    • 多主模式支持多节点写入

问题

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

方案4 MySQL Cluster

image.png

分库分表

主要围绕以下几个问题

  1. 为什么要拆分数据库
  2. 垂直拆分
  3. 水平拆分
  4. 分库分表的的框架与中间件
  5. 如何做数据迁移

为什么要拆分数据库?

单库、单表数据量太大会导致数据库性能、可操作性下降

具体例子:

  1. 单表数据量太大无法执行DDL操作,比如新增一列、增加索引,单表数据量越大,需要时间越长
  2. 无法备份,备份会自动lock数据库所有表
  3. 影响响应速度,主库延迟高、主从延迟高

    仅靠读写分离无法提升单机性能

  4. 采用主从架构,能够实现读写分离、解决高可用问题,但是单机容量不变、单机写性能瓶颈没有解决。

  5. 分库分表,可以提升整体容量,每个数据库作为一个数据分片为集群提供服务。
  6. 降低了单个节点的压力后,也提升了整个集群的性能。

垂直拆分

MySQL集群 - 图5

拆库

将一个数据库拆分成多个提供不同业务数据处理能力的数据库。

最初所有的业务在一个库,慢慢地拆分数据库,不同业务的数据库拆到不同的系统中,行程分布式服务,再演变成微服务架构

拆表

如果单表数据量过大,可以对单表进行拆分

比如原有订单主表,有200个字段,拆分成10+字表:订单表、订单详情表、订单支付表、产品快照表等。 但这种方式,改动过大,故障风向高,一般尽量少用这种方法。 (所以初期的数据库模型设计十分重要)

❓分库还是分表?如何选择

分库还是分表? 如果数据本身的读写压力较大,磁盘IO已成为瓶颈,那么分库比分表好。分库将数据分散到不同的数据库实例、使用不同的磁盘,从而提升整个集群的性能 反之,可以选择分表,降低单表数据量,缩短响应时间

水平拆分

不考虑业务系统,对数据进行分片,降低单个节点数据量,但不改变库表结构。

水平拆分方式

1. 按时间分库分表

有的数据有时间属性,可以按自然时间维度进行分库分表。

比如,1月1日的数据一张表,data_0101;1月2日的数据一张表,data_0102

2. 强制条件指定分库分表

不同的用户数据存入不同数据

3. 自定义方式

指定条件

水平拆分带来的影响

  1. 集群规模大,管理复杂
  2. 复杂SQL支持难
  3. 数据迁移问题(扩容、缩容)
  4. 一致性问题

数据分片算法

哈希分片

范围分片

融合算法

shardingsphere举例

生成分片键

数据的分类管理

随着业务发展,数据肯定是越积越多,慢慢的无效数据、低频数据也就多了,将这些数据与高频热点数据分类管理,提供不同的查询策略。让有限的资源为最有价值的数据服务

将数据分为 热温冷冰 四个类别

数据迁移

全量迁移

  1. 业务停机
  2. 数据库迁移,检验一致性
  3. 系统接入新数据库

    全量+增量

    依赖数据本身的时间戳

  4. 先同步数据到最近的某个时间戳a

  5. 停机维护,将时间a到现在的增量数据复制增益
  6. 最后系统升级,接入新数据库

    binlog+全量+增量

    shardingsphere-calling