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

https://redis.io/topics/lru-cache

https://tech.meituan.com/2017/03/17/cache-about.html

posted @ 2020-09-16 09:51  江湖小小白  阅读(7223)  评论(0编辑  收藏  举报