专栏首页JavaEdge关闭删库跑路的后门,打造高可用的MySQL

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

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复制到备用库并立即回放,这样就可以让备用库里面的数据和主库中的数据一直保持是一样的。一旦主库宕机,就可以立即切换到备用库上继续提供服务。

  • MySQL本身提供了主从复制 https://dev.mysql.com/doc/refman/8.0/en/replication.html

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

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

主从延迟

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

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

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

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

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

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

3.2 同步复制

自动切换,性能最差。

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

一主一从的隐患

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

一主双从

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

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

代价

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • IT文档中总出现的"hooks" 是什么? "钩子" ? 回调 ?

    就像一些外来的钩子,在源代码之间钩取一些信息,当捕捉到感兴趣的事时,就拦截下来,让自己的代码执行一下,处理一下这个信息,然后再放出去继续之前的进程。 这样就可...

    JavaEdge
  • 突破Java面试(50)-MySQL读写分离及主从同步延时解决方案

    针对现状,写一个主库,挂着多个从库,然后从多个从库来读,那不就可以支撑更高的读并发压力了吗?

    JavaEdge
  • CopyOnWriteArrayList 源码解析

    我们知道 ArrayList 非线程安全,需要自己加锁或者使用 Collections.synchronizedList 包装.

    JavaEdge
  • 容灾备份的7个等级

    国际标准SHARE 78将容灾系统定义成七个层次,这七个层次对应的容灾方案在功能、适用范围等方面都有所不同,所以用户选型应分清层次。

    孙杰
  • MySQL主从网络延迟解决

    由于业务要求,需要在国外和国内两台服务器之间做数据库主从,由于业务也不是很大,就简单部署了个主从就用了,开始也没什么问题,最近一段时间,可能是跨国网络不稳定,在...

    李俊鹏
  • javascript实现一行文字随不同设备自适应改变字体大小至完全展示

    产品提了一个小需求,希望一行能展示用户输入的所有文字,因为最多限制为25字符,但是如果夹杂英文/韩文/日文等,即使字符数是一样的,但是展示的长度不一样,则有些t...

    蓓蕾心晴
  • 这就是传说中你不了解的的气泡图

    今天我们来聊一聊传说中的气泡图,气泡图是散点图的一种形式,是预测数据趋势的一种图形,一般在大量的数据调研和数据分析的时候会用到散点或者气泡,但是散点和气泡的...

    王佩军
  • Arcgis for Javascript API下类似于百度搜索A、B、C、D marker的实现方式

    看到了效果,是不是各位有点小鸡动,是不是也宠宠欲动,有木有?但是具体是怎么实现的呢?下面我来详细的给各位说说我的实现思路吧。

    lzugis
  • 给最后一周下个猛料,JavaScript 2017 使用调查!

    "The State of JavaScript" 是由stateofjs发起,对Javascript生态现状进行的一个在线调查。至今一共进行了两次,分别是20...

    企鹅号小编
  • 【学习底层原理系列】重读spring源码1-建立基本的认知模型

    从0-1的过程,是建立在自己已有认知基础上,去用自己熟悉的方式构建一件作品。也就是说,

    小端

扫码关注云+社区

领取腾讯云代金券