Redis 中出现 OOM(Out of Memory)怎么办?

阅读时长 4 分钟读完

OOM 概述

OOM(Out of Memory),即内存不足,这在应用程序中非常常见。当 Redis 发现内存不足,其会向客户端发送一个错误消息并关闭与客户端的连接,导致服务不可用。当然,Redis 在出现 OOM 时也会拒绝写入操作,并向客户端发送错误消息。

OOM 的原因

1. Redis 运行内存时未设限制

如果 Redis 的运行内存没有设置限制或设置过小,就会导致 Redis 的内存用尽。可以通过修改 redis.conf 中的 maxmemory 参数来解决。

其中 bytes 是可用的最大内存。如果 Redis 超过了最大内存限制,Redis 将会在首次尝试写入时返回错误,并关闭与客户端的连接。

2. Redis 的内存碎片

内存碎片指空闲内存块之间存在无法使用的内存空间。当 Redis 内存碎片较多时,即使有足够的内存,也会出现 OOM 的情况。Redis 内部使用 jemalloc 内存分配器来管理内存,可以使用如下命令来查询 Redis 的内存使用情况:

从输出结果中,可以找到 consumed_memory 和 fragmentation_ratio 两个变量。consumed_memory 表示 Redis 当前消耗内存的大小,而 fragmentation_ratio 表示 Redis 的内存碎片率。

3. Redis 的内存泄漏

内存泄漏分为未释放的动态分配内存和永久性分配内存两种。在 Redis 中,大多数内存泄漏与应用程序本身有关,特别是在使用 Lua 脚本时,容易出现内存泄漏。

解决方案

1. Redis 的内存清理策略

当 Redis 内存不足时,采用以下清理策略:

  • noeviction:当 Redis 内存不足时,直接拒绝写入操作,向客户端发送 OOM 错误消息,阻塞所有命令;
  • allkeys-lru:Redis 会在数据集中搜索哪个键最近最少使用,然后删除该键;
  • allkeys-random:Redis 随机删除数据集中的任意一个键;
  • volatile-lru:Redis 只在数据集中搜索可以过期的键中找到最近最少使用(LRU)的键,并删除该键。如果数据集没有足够的过期键,则尝试更新设置最少使用数字的键,然后再次查找可以过期的键,并重复此过程;
  • volatile-random:Redis 随机搜索可以过期的键,如果数据库没有过期键,则随机删除任意一个键;
  • volatile-ttl:Redis 将键按过期时间排序,并根据空间需求删除尽可能接近过期时间的键。

以上清理策略可以通过以下命令设置:

其中 policy 的类型是字符串,可以是以上清理策略中的任意一种。

2. 压缩 Redis 内存

当 Redis 内存碎片较多时,可以使用以下方法进行压缩:

该命令会输出 Redis 中大的 key,可以使用以下命令删除其它冗余数据:

3. Redis 的监控和诊断

当 Redis 发生 OOM 时,可以使用以下命令进行监控和诊断:

该命令会输出与 Redis 相关的统计信息,包括内存使用情况、操作次数、命中率等。通过该指令可以快速确定 Redis 的性能瓶颈和潜在问题。

总结

Redis 中出现 OOM 错误,通常有以下三个原因:

  • Redis 运行内存未设置限制;
  • Redis 内存碎片过多;
  • Redis 出现内存泄漏。

可以通过以下方法解决 Redis 中 OOM 错误:

  • 通过 Redis 内存清理策略进行内存管理;
  • 压缩 Redis 内存;
  • 监控和诊断 Redis 的内存使用情况。

参考文献

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/648fc0d248841e9894de7d81

纠错
反馈