Redis第二篇——持久化

Redis之所以高性能,速度快,其中一个原因就是其数据是存储在内存中的,而对于内存中的数据就会遇到以下几个问题:
(1)内存中数据过期了怎么处理?
(2)内存满了怎么处理?
(3)服务故障内存数据丢了怎么处理?
过期处理 常见的对于设置有过期时间的数据处理方式如下:
定时清理
在放入数据的时候,为设置了过期时间的数据启动一个定时器,当数据到期时去清理数据。这种方式好处是可以及时清理过期数据,对内存非常友好,但缺点是如果大量的数据在同一时间过期,需要占据非常多的cpu时间去执行清理任务,而Redis是单线程的,cpu时间应该更多的分配给业务处理
惰性清理 每次访问到具体的数据时再去判断当前数据是否已经过期了,如果过期了就进行清理。这种方式如果过期的数据长期不被访问,对会长期占用内容,优势是将过期数据清理的过程分散了,对cpu比较友好
定期清理 定期更像是一种折中的方案,Redis在每个时间周期内会调用下清理函数,每次从设置了过期时间的key中选出20个,判断是否需要清理
Redis使用的清理方式是:惰性清理 + 定期清理的方案
内存满了的处理 当redis的内存空间已经用满时,需要依据淘汰策略,进行相应的key的淘汰
(1)volatile-lru
从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。redis并不是保证取得所有数据集中最近最少使用的键值对,而只是随机挑选的几个键值对中的, 当内存达到限制的时候无法写入非过期时间的数据集。
(2)volatile-ttl
从已设置过期时间的数据集中挑选将要过期的数据淘汰。redis 并不是保证取得所有数据集中最近将要过期的键值对,而只是随机挑选的几个键值对中的, 当内存达到限制的时候无法写入非过期时间的数据集。
(3)volatile-random
从已设置过期时间的数据集中任意选择数据淘汰。当内存达到限制的时候无法写入非过期时间的数据集。
(4)allkeys-lru
从数据集中挑选最近最少使用的数据淘汰。当内存达到限制的时候,对所有数据集挑选最近最少使用的数据淘汰,可写入新的数据集。
(5)allkeys-random
从数据集中任意选择数据淘汰,当内存达到限制的时候,对所有数据集挑选随机淘汰,可写入新的数据集。
(6)no-enviction
当内存达到限制的时候,不淘汰任何数据,不可写入任何数据集,所有引起申请内存的命令会报错。
思考:被淘汰的数据又被访问怎么办?
持久化处理 为了避免服务故障导致内存的数据全丢失,Redis提供了两种持久化机制RDB和AOF
RDB RDB是将内存中的数据以快照的方式存储到磁盘中,以二进制文件进行存储,默认文件名为dump.rdb,RDB的触发命令有如下几种:
(1)save命令
调用此命令时Redis线程会阻塞直到快照执行完成。对于线上环境,因Redis是单线程的,这种方式基本不可用
(2)bgsave
调用此命令,Redis主进程会fork出一个子进程,剩下的快照生成导出功能就交给子进程去完成,父进程继续接收客户端的请求。这里主要用到了COW(copy on write)技术。但fork子进程的过程是阻塞的(一般时间很短),cow技术是利用父子进程会共享物理空间,只有当父子进程有对数据页进行改动时,才会为子进程复制对应的页
(3)自动触发
通过修改Redis的配置文件,save m n 表示在m的时间内发生n此变更操作,可配置多个
使用RDB持久化的优缺点:
优点:生成的文件紧凑,非常适合备份和故障恢复,恢复速度快
缺点:缺点是全量备份过程中,由fork的子进程完成,在此期间的改动会丢失
AOF 不同于RDB备份的是内存数据,AOF记录的是改变数据的命令,其主要包含三个过程:命令追加、文件写入、文件同步
所有变更命令会记录到aof_buff缓冲区中,并按照一定的策略持久化到AOF文件中,其文件同步时机有三种:
(1)aways。每次文件写入后立马同步到磁盘,但刷磁盘的IO操作比较耗时
(2)everysec。每次文件写入后每隔一分钟同步到磁盘,可能会丢失1s的数据
(3)no。每次文件写入后就不管了,具体什么时候同步,由操作系统来决定
使用AOF的优缺点:
优点:更好的保护数据不丢失。
缺点:AOF文件过大,针对同一条数据需要保存多条记录,需要AOF的重写。
AOF重写
将AOF文件中的命令进行整合,在整合期间新的数据变更,写入aof_rewrite_buff缓冲区,当新的AOF文件生成之后,将缓冲区的文件追加到文件,AOF文件重写也是在子进程中完成的。
【Redis第二篇——持久化】注意bgsave和bgrewriteaof不能同时进行

    推荐阅读