持久化:持久化是最简单的高可用方法,主要作用:数据备份,即将数据存储在硬盘保证数据不会因进程退出而丢失
主从模式:主从复制时高可用Redis的基础。主动复制主要实现了数据的多机备份,以及对于读操作的负载均衡和简单的故障恢复。
哨兵:在主从复制的基础上实现了自动化的故障恢复
Cluster集群:通过集群,Redis解决了写操作无法负载均衡,以及存储能力受到单机限制的问题
一、Redis持久化
1.1 redis的功能
redis是内存数据库,数据都是存储在内存中,为了避免下次断电而导致数据丢失,需要定期将数据从内存保存到硬盘;当下次重启时,利用持久化完成数据备份。以防万一还可以将持久化文件拷贝到远端。
1.2 实现持久化的方式
- RDB持久化:原理是将Redis在内存中数据库记录定时保存到磁盘上。
- AOF持久化:原理是将Redis的操作日志以追加的方式写入文件(主流)
1.2.1 RDB持久化
指定的时间间隔内将内存中当前进程中的数据生成快照保存到硬盘,用二进制压缩存储,保存的文件后缀是rdb;当redis重启时,可以读取快照中的文件恢复数据
1.2.1.1触发条件
RDB持久化的触发条件分为手动触发和自动触发
- 手动触发
save命令和bgsave命令都可以生成RDB。
save命令会阻塞redis服务器进程,直到RDB文件创建完毕为止。在阻塞期间,服务器无法处理任何请求、bgsave会创建一个子进程,子进程来负责创建RDB文件,父进程会处理该请求。在命令执行过程中,只有fork子进程会阻塞服务器。
- 自动触发
在自动触发RDB持久化时,redis会选择bgsave来进行持久化
1.2.1.2 其他自动触发机制
除了save m n以外,还有一些其他情况也会触发bgsave
-
在主从复制的情况下,如果从节点执行全量复制操作,则主节点会执行bgsave命令,并将rdb文件发送给从节点。
-
执行shutdown命令时,自动执行rdb持久化
1.3 执行流程
- Redis父进程首先判断当前是否在执行save,bgsave或者bgrewriteaof的子进程,如果在执行bgsave命令直接返回。bgsave/bgrewriteaof子进程不能同时执行,如果两个子进程同时执行大量的磁盘读写操作,会引起性能的问题。
- 父进程执行fork操作创建子进程,这个进程父进程处于阻塞状态,Redis不能接收任何从客户端发来的命令
- 父进程fork后,bgsave命令返回"Background Saving started"信息不再阻塞父进程
- 子进程创建RDB文件。根据父进程内存快照生成临时快照文件,完成后在原有文件进行原子进程替换
- 子进程发送信号给父进程表示完成,父进程更新统计信息
1.4 启动时加载
RDB文件载入服务器时自动执行。但是AOF的优先级更高,当载入AOF时,Redis会优先载入AOF来恢复数据。只有当AOF关闭后,服务器才会检测RDB文件并载入。Redis载入RDB文件时,会对RDB文件校验,如果文件损坏,在日志中打印错误,进入Redis启动失败
二、AOF持久化
2.1 AOF功能
将Redis执行的写、删操作记录到单独的日志文件中,查询操作不会记录。当Redis重启时再次执行AOF来恢复数据
2.2 执行流程
执行流程包括
- 文件追加:将redis的写命令追加到缓冲区aof_buf
- 文件写入和文件同步:根据不同的同步策略将aof_buf中的内容同步到硬盘
- 文件重写:定期重写AOF文件,来达到压缩的目的
2.2.1 命令追加
Redis现将写命令追加到缓冲区,主要为了避免每次有写命令都直接写入硬盘,导致因IO成为Redis负载的瓶颈。追加的格式是Redis命令请求的协议格式。 在AOF除了用于指定数据库的select命令是由redis添加的,其余的都是客户端发来的写命令。
特点:
- 读写性强
- 兼容性强
- 易处理
- 操作简单
- 避免二次开销
2.2.2 文件写入和文件同步
当用户调用write写入文件时,操作系统通常会将数据暂存到一个内存缓冲区里,当缓冲区被填满后,才将缓冲区的数据写入到硬盘中,但会代理一个安全问题,一旦计算机停机,内存缓冲区的数据会丢失。因此提供了fsync,fdatasync,而可以强制将缓冲区中的数据写到硬盘中,来确保安全性。
2.2.2.1 缓冲区同步文件策略存在三种同步方式
- appendfsync always:总是触发持久化
- appendfsync no: 不进行持久化
- appendfsync everysecond:每秒会触发一次持久化
2.2.3 文件重写
目的:将所有的数据进行解压再压缩,为了节省空间
文件重写的原因:
- 过期的数据不在写入文件
- 无效的命令不再写入文件:例如重复数据、删除数据
- 多余的命令可以合并为一个
2.2.3.1 文件触发规则
- 手动触发:直接调用bgrewriteaof命令。都是fork自进程能进行具体的工作,且都只有在fork时阻塞
- 自动触发:通过设置auto-aof-rewrite-min-size选项和auto-aof-rewrite-percentage满足来执行bgrewriteaof
2.2.3.2 文件重写的注意事项
- 重写由父进程fork子进程进行
- 重写期间redis执行写的命令,需要追加到新的AOF文件中,为此引入了aof_rewrite_buf缓存
2.2.3.3 文件重写的流程
(1)Redis父进程首先判断当前是否存在正在执行bgsave/bgrewriteaof子进程,如果存在bgrewriteaof直接返回,存在bgsave命令会等它执行完后再执行
(2)父进程执行fork操作创建子进程,整个过程中父进程是阻塞的
(3.1)父进程fork后,bgrewriteaof命令返回"background append only file rewrite started"信息不在阻塞父进程,并可以响应其他的命令。redis所有写命令写入AOF缓冲区,并根据appendsync策略同步到硬盘中,使得原有AOF机制正确
(3.2)由于fork操作使用写时,子进程只能共享fork操作时的内存数据。但是父进程响应命令,因此Redis使用AOF重写缓冲区保存着部分数据防止AOF生成期间再丢失。再bgrewriteaof执行期间,redis写命令同步追加到aof_buf(原数据区)和auf_rewrite_buf(重写数据区)
(4)子进程根据内存快照,会将规则合并到新的AOF文件
(5.1)子进程写完新的AOF文件后,想父进程发送信号来更新统计信息,具体可以通过info persistence查看
(5.2)父进程把AOF重写缓冲区的数据写到新的AOF文件,可以保证新的AOF数据库状态和服务器当前状态一致
(5.3)使用新的AOF文件替换老文件,完成AOF重写
三、 RDB和AOF优缺点
优点 | 缺点 | |
---|---|---|
RDB |
|
|
AOF |
|
|