【问题标题】:why does the redis memory usage not reduce when del half of keys为什么删除一半键时redis内存使用量没有减少
【发布时间】:2012-07-26 18:54:14
【问题描述】:

Redis 是用来保存数据的,但是它消耗大量内存,它的内存使用率高达 52.5%。 我在redis中删除了一半的key,删除操作的返回码是ok的,但是它的内存使用并没有减少。

这是什么原因?提前致谢。

我的操作代码如下:

// save data
m_pReply = (redisReply *)redisCommand(m_pCntxt, "set %b %b", mykey.data(), mykey.size(), &myval, sizeof(myval));
// del data
m_pReply = (redisReply *)redisCommand(m_pCntxt, "del %b", mykey.data(), mykey.size());

redis 信息:

redis 127.0.0.1:6979> 信息 redis_version:2.4.8 redis_git_sha1:00000000 redis_git_dirty:0 拱位:64 multiplexing_api:epoll gcc_version:4.4.6 process_id:28799 uptime_in_seconds:1289592 uptime_in_days:14 lru_clock:127925 used_cpu_sys:148455.30 used_cpu_user:38023.92 used_cpu_sys_children:23187.60 used_cpu_user_children:123989.72 connected_clients:22 连接的奴隶:0 client_longest_output_list:0 client_biggest_input_buf:0 阻塞的客户端:0 已用内存:31903334872 used_memory_human:29.71G used_memory_rss:34414981120 used_memory_peak:34015653264 used_memory_peak_human:31.68G mem_fragmentation_ratio:1.08 mem_allocator:jemalloc-2.2.5 加载:0 aof_enabled:0 changes_since_last_save:177467 bgsave_in_progress:0 最后保存时间:1343456339 bgrewriteaof_in_progress:0 total_connections_received:820 total_commands_processed:2412759064 expired_keys:0 驱逐键:0 keyspace_hits:994257907 keyspace_misses:32760132 pubsub_channels:0 pubsub_patterns:0 latest_fork_usec:11672476 vm_enabled:0 角色:奴隶 主主机:192.168.252.103 主端口:6479 master_link_status:up master_last_io_seconds_ago:0 master_sync_in_progress:0 db0:keys=66372158,expires=0

【问题讨论】:

  • 不幸的是,您必须重新启动 redis-server 进程。看stackoverflow.com/a/5994981/1089294
  • 系统正在运行,无法重启。也许你是对的,redis del 键并不是真正的免费 malloc。

标签: memory-management redis


【解决方案1】:

一个好的起点是使用 Redis CLI 命令:MEMORY DOCTOR
它可以为您提供非常有价值的信息并指出潜在问题。

一些有用的链接:
MEMORY DOCTOR command docs
What is defragmentation and what are the Redis defragmentation configs

示例:

  • 内存峰值:过去此实例使用的内存超过当前使用的内存的 150%。分配器通常无法在峰值之后释放内存,因此您可以预期会看到很大的碎片率,但这实际上是无害的,只是由于内存峰值,如果 Redis 实例驻留集大小 (RSS) 为目前比预期的要大,一旦你用更多的数据填充 Redis 实例,内存就会被使用。如果内存峰值只是偶尔出现,并且您想尝试回收内存,请尝试 MEMORY PURGE 命令,否则唯一的其他选择是关闭并重新启动实例。
  • 总 RSS 高:此实例的内存碎片和 RSS 开销大于 1.4(这意味着 Redis 进程的 Resident Set Size 远大于 Redis 执行的逻辑分配的总和)。此问题通常是由于较大的峰值内存(检查报告中是否存在峰值内存条目)或可能是由于工作负载导致分配器大量碎片内存造成的。如果问题是大的峰值内存,那么就没有问题。否则,请确保您使用的是 Jemalloc 分配器,而不是默认的 libc malloc。注意:当前使用的分配器是“jemalloc-5.1.0”。
  • 高分配器碎片:此实例的分配器外部碎片大于 1.1。此问题通常是由于较大的峰值内存(检查报告中是否存在峰值内存条目)或可能是由于工作负载导致分配器大量碎片内存造成的。您可以尝试启用“activedefrag”配置选项。

【讨论】:

    【解决方案2】:

    从 Redis 4.0.0 开始有一个命令:

    MEMORY PURGE
    

    应该做的伎俩:https://redis.io/commands/memory-purge

    但是请注意,命令文档状态:

    此命令目前仅在使用 jemalloc 作为分配器时执行,并且对所有其他命令评估为良性 NOOP。

    the README 提醒我们:

    Redis 是针对 libc 编译和链接的 malloc 默认情况下,除了 jemalloc 是 Linux 上的默认值 系统。之所以选择此默认值,是因为 jemalloc 已被证明具有更少 碎片问题比 libc malloc 好。

    【讨论】:

      【解决方案3】:

      请参考以下链接的内存分配部分:

      http://redis.io/topics/memory-optimization

      我在这里引用了它:

      Redis 不会总是释放(归还)内存给操作系统。 删除。这对 Redis 来说并没有什么特别之处,但它是最 malloc() 实现工作。例如,如果您填充一个实例 使用 5GB 的数据,然后删除相当于 2GB 的数据, 驻留集大小(也称为 RSS,即 进程消耗的内存页面)可能仍然存在 5GB,即使 Redis 会声称用户内存在 3GB 左右。这 发生是因为底层分配器不能轻易释放 记忆。例如,大多数删除的键通常分配在 与仍然存在的其他键相同的页面。

      【讨论】:

      • 谢谢。那么这里的'解决方案'是redis的硬重启吗?
      • @stevejalim,我想是这样,但我不确定是否有任何可配置的方式来释放分配的内存。
      • @SteveJalim 如果你发现你的设置总是有很多创建和删除的键,我建议编译一个使用内存分配器的 redis 构建,它可以更好地避免碎片,例如 jemalloc。它不会释放已分配的内存,但有助于进一步减少内存使用量。
      • Doesn't used_memory_human:29.71G 和 used_memory_peak_human:31.68G 表示redis报告的用户内存释放不到50%? OS上报的RSS不是跟它没有关系吗?
      猜你喜欢
      • 1970-01-01
      • 2017-11-06
      • 2018-02-15
      • 1970-01-01
      • 1970-01-01
      • 2020-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多