01 集群模式

基于主从同步实现高可用、高性能的MySQL架构,有如下三种方案,权衡对比如下。

通常备库设置为readonly模式(对超级权限无效),以此来判断该节点为从节点。可以防止在备库上出现误操作,防止切换逻辑有BUG,在切换过程中出现双写,造成主备不一致。

方案高可用可能丢数据性能
一主一从(异步复制,手动切换)可控
一主一从(异步复制,自动切换)
一主二从(同步复制,自动切换)

MySQL 自身就提供了主从复制的功能,通过配置就可以让一主一备两台 MySQL 的数据库保持数据同步,具体的配置方法可以参考MySQ官方文档

从库的数据是有可能比主库上的数据旧一些的,这个主从之间复制数据的延迟,称为“主从延迟”。正常情况下,主从延迟基本都是毫秒级别,你可以认为主从就是实时保持同步的。麻烦的是不正常的情况,一旦主库或者从库繁忙的时候,有可能会出现明显的主从延迟。

主从架构

MySQL内置有binlog(实时的增量备份)和relay log两种日志文件。

MySQL 也支持同步复制,开启同步复制时,MySQL 主库会等待数据成功复制到从库之后,再给客户端返回响应。配置多个从库来解决从库宕机阻塞主库的问题

实现步骤

  1. 将所有的DML操作记录在binlog
  2. binlog中的数据内容,通过网络发送给从数据库中的relay log
  3. 从数据库通过解析relay log记录,对主数据库进行备份操作

mysqlbinlog工具可以解析并查看binlog中的内容。mysqlbinlog -vv data/master.000001 --start-position=8900;

mysql>  show variables like '%log_bin%';
+---------------------------------+-----------------------------------------+
| Variable_name                   | Value                                   |
+---------------------------------+-----------------------------------------+
| log_bin                         | ON                                      |
| log_bin_basename                | /var/lib/mysql/mysql-master-0-bin       |
| log_bin_index                   | /var/lib/mysql/mysql-master-0-bin.index |
| log_bin_trust_function_creators | OFF                                     |
| log_bin_use_v1_row_events       | OFF                                     |
| sql_log_bin                     | ON                                      |
+---------------------------------+-----------------------------------------+
6 rows in set (0.00 sec)

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

可以看到当前这个数据库已经开启了 binloglog_bin_basename 表示 binlog 文件在服务器磁盘上的具体位置。

show master status命令可查看当前 binlog 的状态,显示正在写入的 binlog 文件,及当前的位置。

假设每天凌晨用 mysqldump 做一个全量备份,然后开启了 binlog,有了这些,就可以把数据恢复到全量备份之后的任何一个时刻。

使用binlog

# 1. 恢复全量备份的数据
mysql -uroot test < dump.sql

# 2. 恢复binlog记录的数据

mysqlbinlog --start-datetime "2020-02-20 00:00:00" --stop-datetime "2020-02-20 15:09:00" /usr/local/var/mysql/binlog.000001 | mysql -uroot

MySQL的官方备份和恢复文档

注意点:

  • 全量备份的数据要保存在不同的服务器上
  • binlog的回放起始时间可以比全量备份的时间稍微早一点,确保恢复数据的完整性

因为回放 binlog 的操作是具备幂等性的(为了确保回放幂等,需要设置 binlog 的格式为 ROW 格式),多次操作和一次操作对系统的影响是一样的,所以重复回放的那部分 binlog 并不会影响数据的准确性。

注意事项

  • 不能把主从同步作为数据备份的唯一操作
  • 主从同步需要依赖良好的网络环境,网络异常会加大备份的延迟,甚至造成备份的失败
  • 对数据的物理文件备份也是必不可少的

海量请求会使数据库的读写操作处于长期的高并发环境中,为了保证高并发环境下的数据安全,需要设计数据库的事务隔离级别,或者采用一些加锁机制

读写分离

将数据库的读操作和写操作分离,将大部分的读操作汇聚到从数据库中,将相对较少的写操作集中在主数据中。读写分离后:

  • 只需要对写操作进行加锁等数据安全处理
  • 对要被读的数据进行冗余备份,从而实现并发读访问的负载均衡

用户与数据库之间的拦截处理:读写分离,分库分表等。

分库分表

  • 分库:(库的容量不够,拆分数据库)
  • 分表:(表的容量不够,拆分单表)

原理:通过算法将对同一对象的写操作映射到多个数据库形成一对多的关系,读操作需要在拆分后的库或者表中进行数据拼接操作。

分库分表都是水平拆分。基于微服务可以采用垂直拆分,让每个微服务独立的存储到一个数据库里边。

中间件

MyCat实现分库分表和读写分离操作。

中间件单点故障问题

部署去中心化的中间件集群,使用多个MyCat实例,通过一个虚拟IP来访问。

  • Zookeeper,选举
  • HAProxy,虚拟IP
  • Keepalived,心跳

MySQL优化

  1. 字段类型选取
  2. 数据库缓存
  3. 关闭无用服务
  4. 数据库参数调优
  5. 选取适合的存储引擎
  6. SQL语句编写
  7. 索引处理

可以借助explain关键字来查询SQL执行计划,在通过SQL执行计划来进行具体的分析和调优。

慢查询日志

使用慢查询日志或者mysqldumpslow等一些慢查询工具,直接找到性能较低的SQL语句,从而有针对性的进行优化。

海量请求处理方案

  • 限流
  • 削峰填谷(使用队列实现)
  • 缓存
  • 非关系型数据库
上次修改: 14 April 2020