> For the complete documentation index, see [llms.txt](https://xiaobaiha.gitbook.io/tech-share/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xiaobaiha.gitbook.io/tech-share/engineering/shu-ju-ku-rong-zai.md).

# 数据库容灾

一个系统可能包含很多模块，如数据库、前端、缓存、搜索、消息队列等，每个模块都需要做到高可用，才能保证整个系统的高可用。 对于数据库服务而言，高可用的实现可能更加复杂，对用户的服务可用，不仅仅是能访问，还需要有正确性保证，因此讨论数据库的高可用方案时，在容灾之外，还要同时考虑方案中数据一致性问题。

## 高可用数据库

高可用数据库是由一系列数据库构成的总体系统，在任何时刻，至少有一个节点可以接受用户的请求并提供数据库服务。 大多数数据库架构中，有一个主节点处理主要请求，还有若干备用节点用于容灾切换，当主节点不能提供服务时，备用节点成为主节点继续提供服务，用以保证整个系统的可用和稳定。

## 高可用数据库有很多优点

* 方便读写分离

数据库请求当中，一般读操作的请求次数远大于写操作，高可用数据库可以通过将写操作放在主数据库节点上进行，将读操作分担到若干从库上，来提升读操作吞吐量，进而提升读写效率；

* 变更不停服

当整个高可用数据库架构或者主节点升级时，可以让高可用数据库先进行主库切换，让备用节点替换原主节点提供数据库服务，当主节点升级完毕后，再将主从库服务切换回来，这样能有效避免系统升级或变更时对用户服务质量产生影响

* 备份不影响服务性能

高可用数据库架构包含多个从库，在不影响主节点服务性能的情况下，能非常方便地实现数据的容灾备份。

一般，高可用数据库地架构设计时，也需要考虑三个问题：

1. 如何同步各数据库之间的节点数据

同步需要保证切换后的数据库是最新数据，以及在切换过程中数据不会丢失，同时还要考虑同步过程对主库和备库的影响。

1. 高可用数据库的容灾切换如何进行

架构不同容灾切换的复杂度也不一样，且切换以后需要保证主、从库数据的一致性，这可能需要开发者在设计之初就尽量优化和简化容灾切换逻辑。

1. 如何提高高可用的运维效率

## 业界典型高可用数据库架构

按照数据同步方式，我们可以将业界主流的高可用架构划分成四种，每一种数据同步方式可以衍生出不同的架构。

* 共享存储方案
* 操作系统实时数据块复制
* 数据库级别的主从复制
* 高可用数据库集群

### 共享存储共享存储指若干

DB 服务使用同一份存储，一个为主 DB，其他的为备用 DB，若主服务崩溃，则系统启动备用 DB，成为新的主 DB，继续提供服务。一般共享存储采用比较多的是 SAN/NAS 方案。这种方案的优点是没有数据同步的问题，但也有一些限制，如对于共享存储的实时性和网络性能有较高要求。因为共享存储一般是通过网络来访问存储当中的数据，在网络性能较差的情况下，数据库的性能也无法达到令人满意的效果。不过，随着硬件性能的不断提升，将计算存储分离、和 DB 深度结合的共享存储亦是高可用数据库未来发展的趋势之一。

### 操作系统实时数据块复制

这个方案的典型场景是 DRBD，可以把它理解为远程的 RAID1，一侧数据库写入数据以后立即同步到另一侧的存储设备当中。如果写入边数据库崩溃，系统可以直接激活另一侧的数据库存储设备，启动新的数据库服务，实现容灾切换。这个方案同样有一些问题，如系统只能有一个数据副本提供服务，无法实现读写分离；另外，如果系统崩溃，主库进程中断，容灾切换后需要在挂掉的数据库上做数据库崩溃恢复，系统需要的容灾恢复时间较长。

### 数据库主从复制

这种方案我认为是最经典的数据同步模式，系统采用一个主库和多个从库方式，其实现原理主要是基于日志的主从复制，主库操作以日志的形式发送给各个从库，从库接收到日志后进行数据备份。这种方式的好处是一个主库可以连接多个从库，能很方便地实现读写分离，同时，因为每个备库都在运行中，所以备库里面的数据基本上都是热数据，容灾切换也非常快。不过，这个方案也并非完美无缺，如容灾切换时，从库一定要同步完最新数据以后才能升级为主库，否则极有可能发生数据丢失的情况。针对传统主从架构的一些问题，业界也逐渐研发出对应的改进技术。

1. 双主架构问题

经典主从架构里面，原主库崩溃恢复的过程中，新的数据无法及时同步到该数据库当中，原主库恢复后，需要重新设置为从库，并将容灾过程中的数据重新同步进行。改进措施：为了保证容灾后的数据一致性，业界对这种架构做了一些改进，其中一种改进措施就叫双主架构，双主架构一般会选择两个 DB 做一对主库，这两个 DB 之间互相为对方的从库，无论往哪个 DB 写入数据，另一个都会自动同步。容灾时系统只需要把流量从左边切换到右边，容灾后数据同步依旧自动进行，这样，就保证了容灾后原主库的数据一致性。

1. 日志自动寻址问题

容灾备份时，当某一从库提升为主库后，其他备库需要自动定位新主库的日志同步点，同步新主库的日志。早期数据库日志中，MySQL 是通过文件名加上文件的偏移量进行寻址，因此，主库的自动定位并不好实现。改进措施：为了解决此问题，MySQL 提供了一种叫做 GTID 的全局事务标志技术，一个事务对应一个 ID，所有的日志都带有唯一的标识符，主从库切换后，其余从库只要根据新主库的日志 ID，就可以辨别新的日志同步点，然后根据这个日志同步数据，这对于搭建一主库多从库的架构来说寻址非常便捷。

1. 异步复制改进问题

默认情况下，MySQL 的复制是异步的，主库将新生成的日志发送给各从库后，无需等待从库的 ack 回复(从库将接收到的日志写进 relay log 后，才会回复 ack)，直接就认为这次 DDL/DML 成功了。但在极端情况下，如主库刚提交日志，其他从库还没有接收到相关日志时，数据库发生故障，此时，该日志的内容就会全部丢失。改进措施：半同步复制机制。半同步复制是指主库在将新生成的日志发送给各从库前，需发送日志到一个(默认)从库，等待从库返回 ack 信息后，主库再提交日志发送给各从库,这就防止了上述情况下的数据丢失。半同步复制是一种提升数据一致性的有效方式，也是比较关键的技术。

### 数据库高可用集群

前面三种方案主要是通过日志的复制模式实现高可用，第四种方案则是基于一致性算法来做数据的同步，数据库提供多节点一致性同步机制，利用该机制构建多节点同步集群。这种方式比较经典的案例包括 MGR（MySQL Group Replication）和 Galera 等，最近业内也有一些类似的尝试，如使用一致性协议算法，自研高可用数据库的架构等。节点之间是构建成了一个一致性的同步集群，客户端可以读写其中的任何一个节点，任意一节点写入，其他节点都能够将数据进行同步，因此，理论上每个节点都可以进行读写操作。这种方式的容灾实现也比较简单，假设第二个节点出现故障，系统只需要断开客户端对第二个节点的访问路径，其他节点照常访问就可以了，这也是业界近年来比较流行的高可用集群方案。
