Redis 内存大小限制与 key 删除策略
限制内存大小
查看当前运行的 Redis 所使用的配置文件
windows
直接打开任务管理器查看
linux
ps -ef | grep redis
没有配置内存大小或配置为 0 的话,32 位系统上默认为 3G,64 位系统上无限制。所以一般都要配置一下,单位是 bytes 字节。推荐设置为物理内存的 3/4,类似 HashMap 的负载因子。
取消持久化
先删除原有的 dump.rdb,不然启动后会加载
# 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合 # 满足以下条件将会同步数据: # 900秒(15分钟)内有1个更改 # 300秒(5分钟)内有10个更改 # 60秒内有10000个更改 # 可以把所有“save”行注释掉,这样就取消同步操作了 #save "" #save 900 1 #save 300 10 #save 60 10000 # 如果用户开启了RDB快照功能,那么在 redis 持久化数据到磁盘时如果出现失败,默认情况下,redis 会停止接受所有的写请求 stop-writes-on-bgsave-error yes # 指定存储至本地数据库时是否压缩数据,默认为 yes,Redis 采用 LZF 压缩,如果为了节省 CPU 时间,可以关闭该选项,但会导致数据库文件变的巨大 rdbcompression yes # 在存储快照后,可以让 redis 使用 CRC64 算法来进行数据校验,这样做会增加大约 10% 的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能 rdbchecksum yes # 转储数据库的文件名,默认值为 dump.rdb dbfilename dump.rdb # 工作目录,指定本地数据库存放目录,文件名由上一个 dbfilename 配置项指定,这里只能指定一个目录,不能指定文件名 dir ./
限制最大内存
windows 的 maxmemory-policy 策略可能会少一些
# 指定 Redis 最大内存限制,Redis 在启动时会把数据加载到内存中,达到最大内存后,Redis 会先尝试清除已到期或即将到期的 Key,移除规则可以通过 maxmemory-policy 来指定,当处理后,仍然到达最大内存,将无法再进行写入操作,但仍然可以进行读取操作 # Redis 新的 vm 机制,会把 Key 存放内存,Value 会存放在 swap 区 # maxmemory <bytes> # 3GB = 3*1024*1024*1024=3221225472 maxmemory 3221225472 # 当内存使用达到最大值时,redis 使用的清除策略: # LRU 表示最近最少使用,LFU 意味着最少使用 # volatile-lru -> 利用 LRU 算法移除设置过过期时间的 key # allkeys-lru -> 利用 LRU 算法移除任何 key(常用) # volatile-lfu -> 利用 LFU 算法移除设置过过期时间的 key # allkeys-lfu -> 利用 LFU 算法移除任何 key # volatile-random -> 移除设置过过期时间的随机 key # allkeys-random -> 移除随机 key # volatile-ttl -> 移除即将过期的 key(minor TTL) # noeviction -> 不移除任何 key,只是返回一个写错误(默认) maxmemory-policy noeviction # LRU,LFU 和最小 TTL 算法不是精确的算法,而是近似算法(为了节省内存),默认 Redis 将检查 5 个键并选择最近使用的键,可以配置指令更改样本大小获得速度或精度。默认值 5 会产生足够好的结果,10 非常接近真实的 LRU,但耗 CPU,3 更快,但不是很准确。 maxmemory-samples 5
重启服务
windows
net stop redis
net start redis
linux
systemctl restart redis
命令行方式修改
# 设置 100M config set maxmemory 104857600 config set maxmemory-policy allkeys-lru # 查看 config get maxmemory # maxmemory_human:总共,used_memory_human:已使用 info memory # 查看所有配置 config get *
过期删除策略
数据删除策略的目标
在内存占用与 CPU 占用之间寻找一种平衡,顾此失彼都会造成整体 Redis 性能的下降,甚至发服务器宕机或内存泄露
时效性存储结构
主要就是操作 expires 空间
数据删除策略
定时删除
- 创建一个定时器,当 key 设置有 过期时间,且过期时间到达时,由定时器任务立即执行对键的删除操作
- 优点:节约内存,到时就删除,快速释放掉不必要的内存占用
- 缺点:CPU 压力很大,无论 CPU 此时负载量多高,均占用 CPU,会影响 Redis 服务器响应时间和指令吞吐量
- 总结:用处理器性能换取存储空间(拿时间换空间)
惰性删除
- 数据到达过期时间,不做处理。等下次访问该数据时。如果未过期,返回数据。发现已过期,删除,返回不存在
- 优点:节约 CPU 性能,发现必须删除的时候才删除
- 缺点:内存压力很大,出现长期占用内存的数据
- 总结:用存储空间换取处理器性能(拿空间换时间)
定期删除
Redis 启动服务器初始化时,读取配置 server.hz 的值,默认为 10
每秒钟执行 server.hz 次 serverCron() -> databasesCron() -> activeExpireCycle()
activeExpireCycle() 对每个 expires[*] 逐一进行检测,每次执行 250ms/server.hz
对某个 expires[*] 检测时,随机挑选 W 个 key 检测
- 如果 key 超时,删除 key
- 如果一轮中删除的 key 的数量 > W*25%,循环该过程
- 如果一轮中删除的 key 的数量 ≤ W*25%,检查下一个 expires[*],0-15 循环
- W 取值 = ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 属性值
参数 current_db 用于记录 activeExpireCycle() 进入哪个 expires[*] 执行
如果 activeExpireCycle() 执行时间到期,下次从 current db 继续向下执行
周期性轮询 Redis 库中的时效性数据,采用随机抽取的策略,利用过期数据占比的方式控制删除频度
- 特点 1:CPU 性能占用设置有峰值,检测频度可自定义设置
- 特点 2:内存压力不是很大,长期占用内存的冷数据会被持续清理
总结:周期性抽查存储空间(随机抽查,重点抽查)
删除策略比对
定时删除:节约内存、无占用。不分时段占用 CPU 资源,频度高。拿时间换空间
惰性删除:内存占用严重、延时执行,CPU 利用率高、拿空间换时间
定期删除:内存定期随机清理。每秒花费固定的 CPU 资源维护内存。随机抽查,重点抽查。CPU 和内存的折中方案
Redis 默认使用定期和惰性两种。
数据逐出策略
Redis 使用内存存储数据,在执行每一个命令前,会调用 freeMemorylfNeeded() 检测内存是否充足。
如果内存不满足新加入数据的最低存储要求,Redis 要临时删除些数据为当前指令清理存储空间。
清理数据的策略称为逐出算法。
逐出数据的过程不是 100% 能够清理出足够的可使用的内存空间,如果不成功则反复执行。
当对所有数据尝试完毕后,如果不能达到内存清理的要求,将出现错误信息。
影响数据逐出的相关配置
# 最大可使用内存,占用物理内存的比例,默认值为 0,标不限制。生产环境中根据需求设定,通常设置在 50% 以上 maxmemory # 每次选取待删除数据的个数,选取数据时并不会全库扫描,导致严重的性能消耗,降低读写性能。因此采用随机获取数据的方式作为待检测删除数据 maxmemory-samples # 删除策略,达到最大内存后的,对被挑选出来的数据进行删除的策略 maxme mory-policy # 逐出策略 maxmemory-policy volatile-lru
LRU(Least Recently Used):一个时间段里最长时间没有被使用的数据
LFU(Least Frequently Used):一个时间段里使用次数最少的数据
检测易失数据(可能会过期的数据集 server.db[i].expires)
- volatile-lru:挑选最近最少使用的数据淘汰
- volatile lfu:挑选最近使用次数最少的数据淘汰
- volatile-ttl:挑选将要过期的数据淘汰
- volatile-random:任意选择数据淘汰
检测全库数据(所有数据集server.db[i].dict)
- allkeys-lru:挑选最近最少使用的数据淘汰
- allkeys-lfu:挑选最近使用次数最少的数据淘汰
- allkeys-random:任意选择数据淘汰
放弃数据驱逐
- no-enviction(驱逐):禁止驱逐数据(Redis4.0 中默认策略),会引发错误 OOM(Out Of Memory)
建议设置 volatile-lru
数据逐出策略配置依据可以使用 INFO 命令输出监控信息,查询缓存 hit 和 miss 的次数,根据业务需求调优 Redis 配置
http://www.redis.cn/topics/config.html
http://www.redis.cn/topics/persistence.html
https://redis.io/commands/expire