【Redis】Redis 的主从同步
很多企业都没有使用 Redis 的集群,但是至少都做了主从。有了主从,当主节点(Master) 挂掉的时候,运维让从节点 (Slave) 过来接管,服务就可以继续,否则主节点需要经过数据恢复和重启的过程,这就可能会拖延很长的时间,从而影响线上业务的持续服务。
尽管 Redis 的性能很好,但是有时候依旧满足不了应用的需要,比如过多的用户进入主页.导致 Redis 被频繁访问,此时就存在大量的读操作。在一些热门网站,某个时刻(比如促销商品的时候)有每秒成千上万的请求是司空见惯的,这个时候大量的读操作会到达 Redis 服务器.触发许许多多的操作,显然靠一台 Redis 服务器是完全不够用的。一些服务网站对安全性有较高的要求,当主服务器不能正常工作时,需要从服务器代替原来的主服务器作为灾备,以保证系统可以继续正常工作。因此更多的时候我们希望可以读/写分离,读/写分离的前提是读操作远远比写操作频繁得多,如果把数据存放在多台服务器上,就可以从多台服务器中读取数据,从而减轻单台服务器的压力了,读/写分离的技术已经广泛用于数据库中。
在了解 Redis 的主从复制之前,让我们先来理解一下现代分布式系统的理论基石——CAP 原理。
CAP 原理
CAP 原理就好比分布式领域的牛顿定律,它是分布式存储的理论基石。自从CAP的论文发表之后,分布式存储中间件犹如雨后春笋般涌现出来。理解这个原理其实很简单,本节我们首先对这个原理进行简单的讲解。
C
:Consistent,一致性A
:Availability,可用性P
:Partition tolerance ,分区容忍性
分布式系统的节点往往都是分布在不同的机器上进行网络隔离开的,这意味着必然会有网络断开的风险,这个网络断开的场景的专业词汇叫作网络分区
。
如下图所示,在网络分区发生时,两个分布式节点之间无法进行通信,我们对一个节点进行的修改操作将无法同步到另外一个节点,所以数据的一致性
将无法满足,因为两个分布式节点的数据不再保持一致。除非我们牺牲可用性
,也就是暂停分布式节点服务,在网络分区发生时,不再提供修改数据的功能,直到网络状况
完全恢复正常再继续对外提供服务。
用一句话概括 CAP 原理就是: 当网络分区发生时,一致性和可用性两难全
最终一致
Redis的主从数据是异步同步的,所以分布式的 Redis系统并不满足一致性
要求当客户端在 Redis的主节点修改了数据后,立即返回,即使在主从网络断开的情况下主节点依旧可以正常对外提供修改服务,所以 Redis 满足可用性
。
Redis 保证最终一致性
,从节点会努力追赶主节点,最终从节点的状态会和主节点的状态保持一致。如果网络断开了,主从节点的数据将会出现大量不一致,但一旦网络恢复,从节点会采用多种策略努力追赶,继续尽力保持和主节点一致。
主从同步与从从同步
Redis 同步支持主从同步和从从同步,从从同步功能是 Redis 后续版本增加的功能,以减轻主节点的同步负担。后面为了描述上的方便,统一理解为主从同步。
增量同步
Redis 同步的是指令流,主节点会将那些对自己的状态产生修改性影响的指令录在本地的内存 buffer 中,然后异步将 bufer 中的指令同步到从节点,从节点一边执行同步的指令流来达到和主节点一样的状态,一边向主节点反馈自己同步到哪里了(偏移量)。
因为内存的 buffer 是有限的,所以 Redis 主节点不能将所有的指令都记录在内存 buffer 中。Redis 的复制内存 buffer是一个定长的环形数组,如图所示,如果数组内容满了,就会从头开始覆盖前面的内容。
如果因为网络状况不好,从节点在短时间内无法和主节点进行同步,那么当网络状况恢复时,Redis 的主节点中那些没有同步的指令在buffer 中有可能已经被后续的指令覆盖掉了,从节点将无法直接通过指令流来进行同步,这个时候就需要用到更加复杂的同步机制一一快照同步。
快照同步
快照同步是一个非常耗费资源的操作,如图所示,它首先需要在主节点上进行一次 bgsave
,将当前内存的数据全部快照到磁盘文件中,然后再将快照文件的内容全部传送到从节点。从节点将快照文件接受完毕后,立即执行一次全量加载,加载之前先要将当前内存的数据清空,加载完毕后通知主节点继续进行增量同步。
在整个快照同步进行的过程中,主节点的复制 buffer 还在不停地往前移动,如果快照同步的时间过长或者复制 buffer 太小,都会导致同步期间的增量指令在复制 buffer 中被覆盖,这样就会导致快照同步完成后无法进行增量复制,然后会再次发起快照同步,如此极有可能会陷入快照同步的死循环。所以务必配置一个合适的复制 buffer 大小参数,避免快照复制的死循环。
Redis 主从同步基础概念
互联网系统一般以主从架构为基础,所谓主从架构设计的思路大概如下。
- 在多台数据服务器中,只有一台主服务器,而主服务器只负责写入数据,不负责让外部程序读取数据。
- 存在多台从服务器,从服务器不写入数据,只负责同步主服务器的数据,并让外部程序读取数据。
- 主服务器在写入数据后,即刻将写入数据的命令发送给从服务器,从而使得主从数据同先。
- 应用程序可以随机读取某一台从服务器的数据,这样就分摊了读数据的压力。
- 当从服务器不能工作的时候,整个系统将不受影响;当主服务器不能工作的时候,可以方便地从从服务器中选取一台来当主服务器。
请注意上面的思路,我用了“大概”这两个字,因为这只是一种大概的思路,每一种数据存储软件都会根据其自身的特点对上面的这几点思路加以改造,但是万变不离其宗,只要理解了这几点就很好理解 Redis 的复制机制。主从同步机制如下图所示。
这个时候读数据可以随机从从服务器上读取,当从服务器是多台的时候,单台服务器的压力就大大降低了,这十分有利于系统性能的提高,当主服务器出现不能工作的情况时,也可以切换为其中的一台从服务器继续让系统稳定运行,所以也有利于系统运行的安全。当然,由于Redis 自身具备的特点,所以其也有实现主从同步的特殊方式。
首先,明确主机,我们将从主机复制数据发往从机:其次,明确从机。有了这两点后,就可以进行进一步配置了;再次,看 redis.conf 文件,这里要关注的只有 replicaof
这个配置选项,它的配置格式是:
replicaof <masterip> <masterport>
其中,masterip
代表主机,masterport
代表端口。当从机 Redis 服务重启时,就会同步主机的数据。当不想让从机继续复制主机的数据时,可以在从机执行命令
replicaof no one
这样从机就不会再接收主机更新的数据了。又或者原来的主机已经无法工作了,需要复制新的主机,这个时候执行
replicaof <masterip> <masterport>
就能让从机复制另外一台主机的数据了。
在实际的 Linux 环境中,配置文件 redis.conf中还有一个bind 的配置,默认为127.0.0.1
也就是只允许本机访问,这里需要修改它,将其配置为0.0.0.0
,这样其他的服务器就能够访问了。
Redis 主从同步的过程
Redis 主从同步的过程如下图所示。
上图中左边的流程是主服务器,右边的流程是从服务器,这里有必要进行更深层次的描述。
(1)无论如何要先保证主服务器开启,开启主服务器后,从服务器通过命令或者重启配置项可以同步到主服务器。
(2)当从服务器启动时,读取同步的配置,根据配置决定是否使用当前数据响应客户端,然后发送SYNC命令。当主服务器接收到同步命令时,就会执行 bgsave
命令备份数据,但是主服务器并不会拒绝客户端的读/写,而是将来自客户端的写命令写入缓冲区。从服务器未收到主服务器备份的快照文件时,会根据其配置决定使用现有数据响应或者拒绝客户端请求。
(3)当bgsave
命令被主服务器执行完后,开始向从服务器发送备份文件,这个时候从服务器就会丢弃所有现有的数据,开始载入主服务器发送的快照文件。
(4)当主服务器发送完备份文件后,从服务器就会执行这些写入命令。此时就会把 bgsave
执行之后的缓存区内的写命令也发送给从服务器,从服务完成备份文件解析,就开始像往常-样,接收命令,等待命令写入。
(5)缓冲区的命令发送完成后,主服务器执行完一条写命令,就向从服务器发送同步写入命令,从服务器就和主服务器保持一致了。而此时当从服务器完成主服务器发送的缓冲区命令后,就开始等待主服务器的命令了。
以上5步就是 Redis 主从同步的过程。
**在主服务器同步到从服务器的过程中,需要备份文件,所以在配置的时候一般需要预留-些内存空间给主服务器,用以执行备份命令。**一般来说主服务器使用 50%~65%的内存空间,以为主从复制留下可用的内存空间。
多从机同步机制,如下图所示。
如果出现多台同步,那么可能出现频繁等待和操作 bgsave 命令的情况,导致主机在较长时间里性能不佳,这个时候我们会考虑主从链同步的机制,以减少这种可能。
不过复制功能也不是必需的,如果你只用 Redis做缓存,跟 memcache 一样对待也就不需要从节点做备份,挂掉了重新启动一下就行。但是只要你使用了 Redis 的持久化功能,就必须认真对待主从复制,它是系统数据安全的基础保障。