(2022.06.28 Tues)
Redis高可用有多种表现形式,分别是持久化persistence,备份replica,哨兵sentinel和集群cluster。
持久化Persistence
内存型数据库的Redis提供了将内存中的数据写入持久存储的功能。Redis为数据持久化提供了如下选项:
- RDB(Redis DataBase):RDB持久化执行对某一时刻的数据集的记录(point-in-time snapshots of dataset),按照指定的时间间隔
- AOF(Append Only File):AOF持久化记录服务器接收到的写操作,并在服务器启动时完整执行所有操作,用以重建数据集。写入命令格式与Redis协议格式相同,以append-only的形式记录。当log足够大时,Redis可以在后台重写log
- 无持久化:除了前面的选项,可设置关闭持久化,服务器运行时才有数据
- RBD+AOF:在同一个Redis实例中可以联合使用RDB和AOF。当Redis重启时,会使用AOF文件重建数据库,因为AOF在重建数据库时比RDB更加完整
对比RDB和AOF
RDB的特点是记录瞬间(point-in-time)数据,单独文件便于传输,在备机上RDB支持重启和失效自动备份(failover)之后部分再同步(partial resynchronisation)。缺点是恢复数据时不能保证完整的保存,因为无法实现对所有数据和操作命令的备份。另一个缺点是RDB持久化数据需要子进程使用fork()
方法,如果数据集很大,则fork()
方法更加耗时,并可能导致Redis在毫秒时间级别上无法响应客户端,甚至更久。AOF同样需要fork()
方法但并不频繁,并且可以调节写入log的频率。
AOF中有多种频率策略(fsync),比如无fsync,每秒,每次查询。以默认的每秒fsync备份,写入性能依然优秀。fsync是后台进程运行且主线程在没有fsync运行时执行写入,所以最多只丢失一秒的写入数据。
AOF的log是只加log(append-only log),没有崩溃问题。即便log命令只写入一半指令,redis AOF检测工具可以轻易解决。
AOF变大时Redis自动在后台重写AOF。重写完全安全因为Redis持续的对老文件做append操作,而一个全新的文件在当前数据集的基础之上经过操作的最小集生成,一旦新文件准备好了,Redis转向这个文件并开始对这个新文件做append操作。
AOF包含了所有操作,易于理解和解析,甚至可以轻易的输出为AOF文件。即便使用了FLUSHALL
指令清空了数据,只要log的重写命令没有执行,仍然可以通过停止服务器并移除最后一条命令(FLUSHALL
),并重启Redis来实现信息找回。
备份replica
(2022.06.30 Thur)
Redis的备机可以保持与主机instance完全相同的数据。在主备读断联时,备机自动与主机重连,并试图复制主机的完整数据。
Redis主备系统有三种机制:
- 主备机连接时,主机通过向备机发送命令流(stream of commands)保持备机的数据更新,命令包括客户写、键过期和删除以及其他改变主机数据库的操作。
- 断联时,备机发起重连并做部分重同步(partial resynchronisation),即获得断联时错过的部分命令流。
- 部分重同步不可行时,备机会请求完全重同步(full resynchronisation)。此时主机创建所有数据的snapshot,发送给备机,之后在数据集有数据变动时发送命令流给备机。
Redis备份的事实
- Redis使用异步复制,备机向主机发送数据量的异步确认
- 主机可以有多个备机
- 备机可以连接其他备机,以级联的形式(cascading-like)。从Redis 4.0版本开始,所有子备机从主机接收完全相同的命令流
- 主机向备机发送数据备份是非阻塞式的,也就是主机在备机进行初始同步或部分重同步时仍然处理客户查询
- 备机的备份数据基本上也是非阻塞式的。备机在执行初始同步时,仍然可以使用本身的旧版数据对查询做出响应,根据redis.conf文件中的设计。此外,可以设置在备份流断联时备机对用户查询返回错误。在初始同步后,删除旧版数据加载新版数据。备机在这个短暂的窗口屏蔽连接请求,这个过程对于大数据集来说可能长达数秒。从Redis 4.0开始可以设置在另一个线程删除旧版数据,而加载新初始数据仍然在主线程进行并阻塞备机
- 数据备份可用于扩展,即创建多个只读备机,也可用于提高数据安全和高可用性
- 使用数据备份可以避免持久化所有主机数据到本地存储中,但是这种设置需要小心,因重启主机会清空数据集,而此时如果备机继续从主机同步数据,备机数据也将清空
主机持久化关闭时数据复制安全问题
强烈建议在Redis备份时设置主、备机打开持久化。当持久化关闭时,由于硬盘写入的延迟,应设置系统重启后(reboot)避免自动重启Redis。
考虑下面的重启案例
- 设置节点a为主机,持久化关闭,节点b和c为备机
- 节点a崩溃,因为有自动重启系统,重启了Redis进程。因为持久化关闭,节点a以空数据集开始了运行
- 节点b和c从a复制数据,获得了空数据,失去了数据备份功能
当数据安全在项目中被关注时,如果用于复制数据的主机没有设置持久化,则自动重启该Redis实例也应设置禁用。
Redis数据备份如何工作
(placeholder)
This is how a full synchronization works in more details:
The master starts a background saving process to produce an RDB file. At the same time it starts to buffer all new write commands received from the clients. When the background saving is complete, the master transfers the database file to the replica, which saves it on disk, and then loads it into memory. The master will then send all buffered commands to the replica. This is done as a stream of commands and is in the same format of the Redis protocol itself.
设置
设置数据备份简单易行,在备机的Redis设置文件中加入如下内容
replicaof 192.168.1.1 6379
需要用主机的IP和port代替上面指令中的对应部分。或者使用REPLICAOF
命令之后主机开始与备机的同步流程。
同时可以在主机的复制backlog中设置参数定制部分重同步,参数设置在redis.conf文件中。
在设置时激活无盘复制功能,可以使用repl-diskless-sync
参数,和repl-diskless-sync-delay
参数。
集群基础
(2022.07.17 Sun)
Redis集群除了应用了上面介绍的主备/主从架构,还用到了分布式系统中其他技术,下面先介绍相关概念。
Gossip protocol
Gossip协议,也叫epidemic protocol,源自流行病传播领域(epidemic spread),初始论文是Epidemic Algorithms for Replicated Database Maintenance。Gossip协议是一种通信协议,常用于去中心化、分布式系统,典型应用如Redis cluster、Bitcoin、Apache Cassandra和P2P网络应用等。
Gossip协议是最终一致性算法、弱一致性算法,只能保证最终的一致性,而达成一致的时间不可控。
Gossip协议是六度分割理论(six degrees of separation)的实践化,该理论认为,一个人可以通过6个中间人/认识的人,联系到世界上任何一个人。
Gossip协议的执行过程如下:
- 一个初始节点(种子节点)以周期向网络中的节点散播消息
- 被感染的节点随机选择特定数目个临近节点传播消息,每个被感染的节点都只接收而不做反馈
- 每个被感染的节点重复传播消息的过程
- 一个已经接收到消息的节点A,当其他节点B再一次向其发送消息时,A不再继续做信息传播,而B也不将A包含在特定数目之中
上面的过程中,向临近个节点传播消息,这个数字定义为fanout参数,如果则成为六度分割理论的实践案例。
可以看到Gossip协议与通信网络中的flooding方式传播完全一致,但差别在于因为无线信道的限制通信网络中flooding方式会导致对信道的大量占用生成冗余信息并严重影响其他信息的传输,是通信网络中极力避免的一种传播手段。
Gossip协议有三种通信方式,Push、Pull和Push/Pull。
Push模式下,一个节点将信息发给多个节点。一旦某个节点接收到消息,便将信息发给给没有接收过消息的节点,所有接收到消息的节点重复这个过程,直到整个网络中的所有节点都收到消息。具体来说是节点A将数据(key, value, version)推送给其他节点,其他节点更新自身保存的数据,如果A传递来的数据比较新的话。一次操作。
Pull模式下,一个节点将查询信息发给其他节点,查看在收到最后一次gossip信息之后是否有需要更新信息,如果有更新,则接收到信息的节点发送更新的部分给查询发送者。两次操作。
Push/Pull模式,类似于Pull模式。一个节点A向其他节点B发送信息查看有无更新,如果有更新,则B将更新信息发送给A,A收到之后再执行一个Push操作,将完整的最新信息发给接受者。三次操作。
Gossip协议实现最终一致性的三种方式,直接邮寄(Direct Mail)、反熵(Anti-entropy)和谣言传播(Rumor mongering)。
直接邮寄:
每个节点更新都会立即从其变更节点邮寄通知到所有其他节点。
反熵:
每个节点都会定期随机选择节点池中的一些节点,通过交换数据内容来解决两者之间的任何差异。
所有参与节点只有两种状态:Suspective(病原)、Infective(感染)
过程是种子节点会把所有的数据都跟其他节点共享,以便消除节点之间数据的任何不一致
缺点是消息数量非常庞大,且无限制;通常只用于新加入节点的数据初始化。
反熵是一种通过异步修复实现最终一致性的方法。
谣言传播(Rumor mongering):
所有的节点在最开始没有产生数据变更时都假设是未知状态,它是不知道任何谣言信息的
当节点收到其他节点更新数据通知时,相当于听到了一条谣言,并将其视为热门开始传播给周边节点
当某个节点谣言盛行时,它会定期随机选择其他节点,并确保另一个节点知道
当某个节点发现周边节点都知道这个谣言时,该节点将停止将该谣言视为热点,并保留更新,而不会进一步传播。
Reference
1 redis点io/docs
网友评论