首发博客地址
Redis高可靠靠什么保证?
为什么要提这个呢,因为Redis主从库目的呢其实就是为了实现高可靠。上篇文章中我们说过Redis的AOF、RDB日志其实就是为了减少数据丢失,这是高可靠的一部分。
这篇文章呢,我们聊聊Redis实现高可靠的另一方面:尽量减少服务中断。这里Redis是怎么做的呢?Redis的做法是增加副本冗余,将一份数据同时保存在多个实例上。这样某个实例挂掉并不影响其它实例提供对外服务,保证我们的业务正常运行。
Redis有哪些手段提高高可用呢?
- 数据持久化:Redis 支持多种数据持久化方式,包括快照(snapshotting)和日志(append-only file)。快照会定期将内存中的数据保存到磁盘文件,而日志会记录每次写操作,以便在重启时进行恢复。这些持久化方式可以确保即使服务器意外关闭,数据也不会丢失。
- 主从复制:Redis 支持主从复制机制,其中一个 Redis 实例作为主节点,负责写操作,而其他实例作为从节点,负责复制主节点的数据。这种方式可以实现数据的备份和负载均衡,从而提高可靠性和性能。
- Sentinel 哨兵:Redis Sentinel 是一个监控和自动故障恢复系统,可以监控 Redis 实例的健康状态并在主节点故障时自动进行故障切换。它可以确保系统在主节点发生故障时能够自动切换到备用的从节点,保证服务的连续性。
- Cluster 集群:Redis Cluster 是一种分布式系统,将数据分布在多个节点上,以提高可用性和扩展性。每个节点都持有部分数据,并且可以容忍部分节点的故障。当节点发生故障时,集群可以自动重新分配数据,确保服务的可靠性和高可用性。
如何保证副本数据一致?
首先我们要知道,Redis提供了主从库模式,以保证副本一致,主从库之间采用的是读写分离的方式。
Redis主从库和读写分离
Redis中的读写分离基本原理和步骤
Redis 读写分离是一种架构设计,将读操作和写操作分别路由到不同的 Redis 节点上,以提高性能和扩展性。在 Redis 读写分离中,通常会有一个主节点负责写操作,多个从节点负责读操作。
- 主节点(写节点):
- 主节点负责处理所有的写操作,包括写入、更新和删除等。
- 写操作在主节点上执行,然后主节点将写操作的结果同步到所有从节点。
- 从节点(读节点):
- 从节点负责处理读操作,例如获取数据、查询等。
- 从节点从主节点复制数据,并在本地保存一份与主节点相同的数据副本。
- 读写分离的实现:
- 客户端根据需要的操作类型将请求分发到主节点或从节点。
- 读操作可以通过负载均衡策略,将请求分发到不同的从节点,实现负载分担。
- 写操作仍然发送给主节点,确保数据的一致性和完整性。
需要注意的是,Redis 读写分离并不是完全的数据实时同步,因为从节点的数据可能会有一定的延迟。另外,读写分离适用于大多数场景下的负载均衡和性能优化,但在一些特定情况下,例如有序集合等复杂数据结构的查询,仍然需要访问主节点。
实现 Redis 读写分离需要正确配置主从节点的关系,以及在客户端中使用合适的策略进行读写操作的路由。同时,需要注意主节点和从节点之间的数据同步和故障处理,以确保系统的稳定性和可靠性。
Redis主从库第一次同步是如何实现的?
- 建立连接: 从服务器会向主服务器发送
PSYNC
命令,表示要进行同步。主服务器收到PSYNC
命令后,会创建一个专门用于复制的后台线程(replication thread),并等待从服务器的连接。 - 全量复制(第一次同步):当从服务器连接到主服务器后,主服务器会将自己的数据发送给从服务器。这个过程叫做全量复制,主服务器会遍历自己的数据集,将所有数据发送给从服务器。
- 主服务器会在一个 RDB 文件中保存当前数据集的快照,然后将这个 RDB 文件发送给从服务器。从服务器接收到 RDB 文件后,会加载这个文件,将自己的数据集替换成主服务器的数据集。
- 在 RDB 文件传输的过程中,主服务器会将在传输期间的写操作记录下来,称为命令传播(command propagation)。这样一来,主服务器就能够在发送完 RDB 文件后,将期间的写操作重新发送给从服务器,以保证从服务器的数据集与主服务器保持一致。
- 增量复制: 在完成全量复制后,主从服务器之间会保持一个 TCP 连接,主服务器会将自己的写操作发送给从服务器,从服务器执行这些写操作,从而保持数据一致性。增量复制的数据同步是异步的,但通过记录写操作,主从服务器之间的数据最终会达到一致状态。
需要注意的是,在第一次全量复制的过程中,可能会有一些网络故障、主从服务器负载等情况影响同步。为了提高稳定性和安全性,Redis 提供了一些配置选项和机制,如持久化、复制偏移量、主服务器验证等,来确保主从复制的正常进行。
PSYNC命令
当 Redis 主从复制中的从服务器(Slave)需要与主服务器(Master)进行数据同步时,可以使用 PSYNC(Partial SYNC)命令。PSYNC 命令在 Redis 2.8 版本引入,用于提高数据同步的效率和可靠性。
PSYNC 命令包括两种模式:完全同步(Full Sync)和部分同步(Partial Sync)。
- 完全同步(Full Sync):完全同步在以下情况下发生:
- 从服务器初次连接主服务器时。
- 从服务器需要进行初次同步,或者复制偏移量与主服务器的偏移量差距较大时。
- 主服务器没有保存 RDB 快照文件,所以无法进行部分同步。
- 完全同步的过程如下:
- 从服务器向主服务器发送一条 PSYNC 命令,并附带上自己的复制积压缓冲区的偏移量(offset)和 replid(复制 ID)。
- 主服务器使用
bgsave
命令,生成RDB文件,接着将文件发给从库。 - 从库接收到RDB文件后,会先清空当前数据库,然后加载RDB文件。
- 部分同步(Partial Sync):部分同步在以下情况下发生:
- 从服务器已经复制了一部分数据,并且复制偏移量与主服务器的偏移量差距较小时。
- 部分同步的过程如下:
- 主库将后续所有 写操作记录到内存中的replication buffer中
- 从服务器向主服务器发送一条 PSYNC 命令,并附带上自己的复制积压缓冲区的偏移量和 replid。
- 主库将所有保存的写操作发送给从库,具体来说,就是当RDB发送完成后,就会把此时replication buffer中的修改发给从库,从库再重新执行这些操作。这样一来,主从库就实现同步了
PSYNC 命令的目标是在保证数据一致性的前提下,尽可能地减少数据同步所需的数据传输量,从而提高复制效率。完全同步和部分同步的选择取决于从服务器与主服务器之间的复制状态和数据差距。
主库的烦恼
这里我们能分析得到主库做全量同步时的两个耗时操作:
- 生成RDB文件
- 传输RDB文件
这里设想一个场景,如果是一主多从的架构,那么主节点就要生成多份RDB并传输给从节点,很显然,这种操作是非常耗时的。这里主要占用两块资源
- 通过fork子进程生成RDB快照会 阻塞主线程处理请求
- 传输RDB文件会占用 网络带宽
那么有什么方法可以解决这些问题呢? 这里呀,我们就引入了“主-从-从”架构,很容易理解,就是主库只需要同步一份给某从库A,其他从库从从库A同步数据。
如何理解 主-从-从 架构?
主从(Master-Slave)架构是一种常见的数据库复制和数据备份方案。在这种架构中,存在一个主数据库(主服务器)和一个或多个从数据库(从服务器),主数据库负责处理写操作和读操作,从数据库负责复制主数据库的数据,以提供读取操作和备份。
主从架构的工作方式如下:
- 主数据库(主服务器):
- 主数据库是系统的主要数据库,负责处理所有的写操作(数据的插入、更新、删除)和部分读操作。
- 当主数据库接收到写操作时,会将这些写操作记录到自己的日志文件(例如 MySQL 的二进制日志)中,并发送给从数据库。
- 主数据库也会保存一个复制积压缓冲区(replication backlog buffer),其中存储了一部分的写操作数据,用于满足部分同步和断线重连的需求。
- 从数据库(从服务器):
- 从数据库是主数据库的复制副本,负责从主数据库复制数据以供读取操作和备份。
- 从数据库会连接到主数据库,并发送复制请求(如 PSYNC 命令)以获取主数据库的数据更新。
- 从数据库会持续地复制主数据库的写操作,将写操作应用到自己的数据副本中,以保持与主数据库的数据一致性。
- 从数据库可以处理读取请求,从而减轻主数据库的读取压力。
主从架构的优势:
- 负载均衡: 通过将读操作分发给从数据库,可以分担主数据库的读取压力,提高整体系统的吞吐量。
- 高可用性: 当主数据库出现故障时,可以将其中一个从数据库提升为新的主数据库,从而实现快速故障切换。
- 数据备份: 从数据库可以作为主数据库的数据备份,用于恢复数据和灾难恢复。
- 数据分析: 从数据库可以用于读取操作,以进行数据分析、报表生成等工作,而不影响主数据库的性能。
需要注意的是,主从架构并不是完全实时的,因为从数据库需要时间来同步主数据库的数据更新。因此,在考虑使用主从架构时,需要权衡数据一致性和性能之间的需求。