Redis数据淘汰与持久化机制

young 475 2021-10-18

数据淘汰与内存回收

redis的内存满了,会进行内存的回收

回收的对象:

  1. key过期了,会回收,采用过期策略
  2. 当redis使用的内存达到了设置的max_memory,会触发内存回收(淘汰)策略

过期策略

定时过期:到了key的过期时间,立即删除(为每个设定了过期时间属性的key创建一个定时器,过期了马上删除),会大量占用cpu的字段,影响redis的响应时间和吞吐量

惰性过期:key被访问的时候才判断是否过期,过期则删除。会节省cpu资源,但是会占用大量内存

定期过期:每隔一段时间,清除一定数量的过期的key

淘汰策略

redis内存上限设置

在conf文件中设置值maxmemory,不设置或者0,在64位系统中是不限制的,在32位 系统中最多为3G内存

或者在客户端执行config set maxmemory2GB

LRU/LFU

LRU:Least Recently Used 最近最少使用,根据最后被使用的时间,时间最远的先淘汰

LFU:Least Frequently Used 最不常用的数据,根据一定时间内的访问频率,将使用最少的淘汰

random:随机在设置了过期时间,即将过期的key中选一些key进行删除

ttl:设置了过期时间的key,优先删除即将过期的key

noeviction:没有淘汰策略

volatile/allkeys

volatile 有过期时间属性的key

allkeys 所有key

volatile-lru

allkeys-lru

volatile-lfu

allkeys-lfu

volatile-random

allkeys-random

volatile-ttl

noeviction

默认是不淘汰的

推荐用volatile-lru

LRU

传统实现:链表+HashMap实现

如果访问key,将key放到链表的头部,当长度不够时,优先删除链表末尾的节点

Redis中采用随机采样的方式

maxmemory-samples 5

从数据库中随机选取5个值,将热度最低的值淘汰

redis中,所有的key都有一个LRU的属性字段,用了保存时间戳的值

这个LRU为全局变量 server.lruclock拿到的值

serverCron 会每隔100ms更新一次server.lruclock

热度计算是取LRU属性和server.lruclock差值,差值越大,说明越久没有被访问


LFU

  1. key最后被访问的时间
  2. key被访问的频率(计数器counter)增长不是每次访问都加一,有增加因子决定,在redis中是配置中的lfu-log-factor,lfu-log-factor越大,counter增加的越慢。lfu-decay-time衰减因子,单位是分钟,默认是1,表示1分钟没有被访问,counter就减一(配置在redis.conf中)

持久化机制

RDB:Redis DataBase

AOF:Append Only File

RDB

默认方案 ,在满足一定条件的时候,redis里的数据会写入到RDB文件中,系统重启的时候,根据RDB文件将数据恢复的redis中

  1. 配置规则触发/shutdown触发/flushall触发

    通过redis.conf中的save配置自动触发的规则

    save 900 1 :900代表秒数,1代表key的数量,表示900秒之内至少有1个key修改了,就会触发一次

    文件生成路径在dir配置,文件名称在dbfilename配置

    rdbcompression 如果开启了,会通过LZF算法对rdb文件进行压缩,会消耗一定cpu的计算时间,但会节省存储空间

    rdbchecksum 如果开启,会用CRC64的的算法,对RDB文件的完整性进行校验

    shutdown时会触发写入

    flushall 触发会清空rdb文件

  2. 手动触发:save/bgsave

    在客户端执行save指令,在生成快照时会阻塞服务器,redis就不能处理其他客户端的数据了

    bgsave=backgroud save,redis会在后台异步的进行生成快照的操作,此时服务端可以响应客户端的请求

服务启动时会找rdb文件,恢复数据

特点

  1. 内容紧凑,保存redis在某个时间节点的全部数据集
  2. 不影响主进程,会用子进程处理
  3. 恢复大数据集时速度快
  4. 同步频率,不能实时持久化,不能秒级持久化,在持久化之前宕机,会导致数据丢失

AOF

默认不开启

使用日志的形式记录操作,追加到文件中

回复数据时,将AOF记录的日志从头到尾执行一次

AOF的开关是redis.conf中的appendonly

文件名在appendfilename配置

目录与rdb相同

AOF不会实时写入,会先放入到系统磁盘的缓存

appendsync everysec/always/no

no表示在某些情况下触发这个操作,把系统缓存写到AOF文件中,速度最快,但是不安全

always表示每次操作都会执行一次,效率低

everysec表示每秒钟执行一次

重写机制

当AOF文件大小超过一定阈值的时候,redis会对AOF文件进行压缩,只会保留用来恢复数据的最小指令集

可以通过bgrewriteaof命令来手动触发重写

在配置中通过两个参数来配置

auto-aof-rewrite-percentace 100

在上一次重写之后,如果当前AOF文件达到了上次文件重写之后大小的100倍会自动触发重写

auto-aof-rewrite-min-size 64mb

如果文件到达了多少大小的时候就会进行重写,如果到达了百分比的比例,但是没有到达最小大小的,也不会触发重写

开启了AOF后,会优先使用AOF恢复数据,不会用到RDB

如果AOF是空的,其实重启服务,会清空redis的数据,所以执行重启前,先执行AOF的重写

特点

  1. 同步频率,最多丢失1秒的数据
  2. 文件大小,aof的体积比rdb更大
  3. 性能,高并发的情况下,rdb的性能比aof更好,如果可以忍受一部分数据丢失,可以使用RDB恢复,一般是同时使用的