为了账号安全,请及时绑定邮箱和手机立即绑定

关闭删库跑路的后门,打造高可用的MySQL

标签:
Java

0 MySQL HA/Scalability

  • 如何关上“删库跑路”的后门,维护我们的数据安全呢?

数据是当今Web,移动,社交,企业和云应用程序的流行货币。确保数据始终可用是任何组织的头等大事。几分钟的停机时间可能会导致收入和声誉严重损失。

没有提供高可用性(HA)的“一刀切”的方法。独特的应用程序属性,业务需求,运营能力和传统基础架构都可以影响HA技术的选择。技术只是提供HA的要素之一:人员和流程与技术本身一样关键。

MySQL已部署到许多要求可用性和可伸缩性的应用程序中。

  • 可用性是指应对主机故障(包括MySQL,操作系统或硬件和维护活动的故障)的能力,并在必要时从主机故障中恢复,否则可能会导致停机
  • 可伸缩性是指能够在多个MySQL服务器上分布数据库和应用程序查询负载的能力。

由于每个应用程序都有不同的操作和可用性要求,因此MySQL提供了一系列经过认证和受支持的解决方案,可提供适当级别的高可用性(HA)和可伸缩性,以满足服务级别的要求。此类解决方案从复制一直到虚拟化和地理冗余的多数据中心解决方案,可实现99.999%的正常运行时间。

为应用程序选择正确的高可用性解决方案主要取决于:

  • 所需的可用性级别
  • 部署的应用程序类型
  • 在自己的环境中接受的最佳实践

MySQL支持的主要解决方案包括:

  • MySQL复制
  • MySQL集群

用于实现高可用性数据库服务的每种体系结构都通过其提供的正常运行时间级别来区分。这些体系结构可以分为三个主要类别:

  • 数据复制
  • 集群和虚拟化系统
  • 无共享,地理位置复制的群集。

如下图所示,这些体系结构中的每种体系结构都提供了越来越高的正常运行时间,必须将其与可能产生的更高水平的成本和复杂性进行权衡。仅部署高可用性体系结构并不能保证实际交付HA。实际上,与简单的数据复制解决方案相比,实施不当和维护不善的无共享群集可能很容易提供较低级别的可用性。

高可用依赖的是数据复制,数据复制的本质就是从一个库备份数据,然后恢复到另外一个库中去。

我们看向最简单的数据复制方案。

1 数据备份

定期备份数据,这样即使数据丢失,也可以通过备份记录来恢复。

问题来了,如何备份?

1.1 全量备份

最简单的备份方式。
备份的时候,把所有的数据复制,存放到文件中,恢复的时候再把文件中的数据复制回去,这样可以保证恢复之后数据库中的数据和备份时是完全一样的。
在MySQL中,可以使用mysqldump执行全量备份。

比如我们要全量备份数据库shop:

$mysqldump -u root -p shop > shop.sql

备份出来的文件就是一个SQL文件,就是创建数据库、表,写入数据等等这些SQL,如果要恢复数据,直接执行这个备份的SQL文件就可以了:

$mysql -uroot test < test.sql

不过,全量备份的代价非常高

  • 备份文件包含数据库中的所有数据,占用的磁盘空间非常大
  • 每次备份操作都要拷贝大量数据,备份过程中会占用数据库服务器大量的CPU、磁盘IO资源
  • 为了保证数据一致性,还有可能会锁表,这些都会导致备份期间,数据库本身的性能严重下降。

不能经常全量备份。

一般来说,每天执行一次全量备份已是非常频繁。如果数据库中的数据丢了,那只能恢复到最近一次全量备份的那个时间点,这个时间点之后的数据还是丢了。
也就是说,全量备份不能做到完全无损地恢复。

有没更好方法,少丢甚至不丢数据?

1.2 增量备份

每次只备份相对于上一次备份变化的那部分数据,所以每次增量备份速度更快。

1.2.1 Binlog

MySQL自带的Binlog,就是实时的增量备份。

Binlog里面记录的就是MySQL数据的变更的操作日志,开启Binlog之后,我们对MySQL中的每次更新数据操作,都会被记录到Binlog。

1.2.1.1 基本原理

Binlog可以回放,回放Binlog,就相当于把之前对数据库所有数据更新操作按照顺序重新执行了一遍,回放完成之后数据自然就恢复了。
很多数据库都有类似于MySQL Binlog的日志,原理和Binlog是一样的,备份和恢复方法也类似。

1.2.1.2 开启

  • show variables like ‘%log_bin%’;

    可以看到当前这个数据库已经开启了Binlog
  • log_bin_basename
    Binlog文件在服务器磁盘上的具体位置

1.2.1.3 查看状态

  • show master status

    显示正在写入的Binlog文件,及当前的位置。
    假设我们每天凌晨用mysqldump做一个全量备份,然后开启了Binlog,有了这些,就可以把数据恢复到全量备份之后的任一时刻。

用Binlog把数据恢复到删库跑路之前的那个时刻:

$mysqlbinlog --start-datetime "2020-05-16 00:00:00" 
--stop-datetime "2020-05-16 18:00:00" 
/usr/local/var/mysql/binlog.000001 | mysql -uroot

这时候,数据已经恢复到当天的18点了。

定期的全量备份 + Binlog,就可以把数据恢复到任一历史时间点。

2 最佳实践

  • 无论全量备份还是Binlog,都不要和数据库存放在同一服务器
  • 在回放Binlog时,指定的起始时间可以比全量备份的时间稍微提前,确保全量备份之后的所有操作都在恢复的Binlog范围内,保证恢复的数据的完整性。
    因为回放Binlog操作是幂等的(需要设置Binlog为ROW格式),所以重复回放的那部分Binlog并不会影响数据的准确性。

3 打造高可用的MySQL

恢复数据时间很长,这期间系统一直不可用,怎么搞?
不要等着数据库宕机,才开始做恢复,平时就要恢复。

3.1 异步复制

一主一从,性能佳。

实时地在主备数据库之间来同步Binlog,主库做了一次数据变更,生成一条Binlog,我们就把这一条Binlog复制到备用库并立即回放,这样就可以让备用库里面的数据和主库中的数据一直保持是一样的。一旦主库宕机,就可以立即切换到备用库上继续提供服务。

方案的问题。当我们对主库执行一次更新操作的时候,主从两个数据库更新数据实际的时序是这样的:

  • 在主库的磁盘上写入Binlog
  • 主库更新存储引擎中的数据
  • 给客户端返回成功响应
  • 主库把Binlog复制到从库
  • 从库回放Binlog,更新存储引擎中的数据。

主从延迟

从库的数据有可能比主库上的数据旧。
正常情况下,主从延迟基本都是毫秒级别,可认为就是实时保持同步。
不正常的,一旦主库或者从库繁忙的时候,会出现明显的主从延迟。

很多情况下,数据库都不是突然宕机的,而是先繁忙,性能下降,最终宕机。这种情况下,很有可能主从延迟很大,如果我们把业务直接切到从库上继续读写,主从延迟这部分数据就丢了,并且这个数据丢失是不可逆的。即使事后你找回了当时主库的Binlog也是没法做到自动恢复的,因为它和从库的数据是冲突的。

简单地说,如果主库宕机并且主从存在延迟的情况下,切换到从库继续读写,可以保证业务的可用性,但是主从延迟这部分数据就丢失了。

这个时候你就需要做一个选择题了

  1. 保证不丢数据,牺牲可用性,暂时停止服务,想办法把主库的Binlog恢复到从库上之后再提供服务
  2. 冒着丢一些数据的风险,保证可用性,第一时间切换到从库继续提供服务

能不能既保证数据不丢,还高可用?

3.2 同步复制

自动切换,性能最差。

MySQL支持同步复制,开启同步复制时,MySQL主库会等待数据成功复制到从库之后,再给客户端返回响应。

一主一从的隐患

从库宕机了怎么办?本来从库宕机对主库是完全没影响的,因为现在主库要等待从库写入成功再返回,从库宕机,主库就会一直等待从库,主库也卡死了。

一主双从

得加一个从库,主库配置成:成功复制到任意一个从库就返回,只要有一个从库还活着,就不会影响主库写入数据,这样就解决了从库宕机阻塞主库的问题。

如果主库发生宕机,在两个从库中,至少有一个从库中的数据是和主库完全一样的,可以把这个库作为新的主库,继续提供服务。

代价

至少用三台数据库服务器,但这三台的服务性能,还不如一台。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消