为什么在del键的一半时redis内存使用不会减少

时间:2012-07-28 06:38:21

标签: memory-management redis

Redis用于保存数据,但它占用大量内存,内存使用率高达52.5%。 我在redis中删除了一半的密钥,删除操作的返回代码没问题,但其内存使用量没有减少。

是什么原因?在此先感谢。

我的操作代码如下:

// 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> info
redis_version:2.4.8
redis_git_sha1:00000000
redis_git_dirty:0
arch_bits: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
connected_slaves:0
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0
used_memory: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
loading:0
aof_enabled:0
changes_since_last_save:177467
bgsave_in_progress:0
last_save_time:1343456339
bgrewriteaof_in_progress:0
total_connections_received:820
total_commands_processed:2412759064
expired_keys:0
evicted_keys:0
keyspace_hits:994257907
keyspace_misses:32760132
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:11672476
vm_enabled:0
role:slave
master_host:192.168.252.103
master_port:6479
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
db0:keys=66372158,expires=0

3 个答案:

答案 0 :(得分:12)

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

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

我在这里引用它:

  

当按键时,Redis不会总是释放(返回)内存到操作系统   除去。这对Redis来说并不是特别之处,但它是最重要的   malloc()实现工作。例如,如果您填写实例   用5GB的数据,然后删除相当于2GB的数据,   驻留集大小(也称为RSS,即数量)   该进程消耗的内存页面可能仍然存在   5GB,即使Redis声称用户内存大约为3GB。这个   之所以发生,是因为底层分配器无法轻松释放   记忆。例如,通常会分配大多数已删除的密钥   与仍然存在的其他键相同的页面。

答案 1 :(得分: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碎片问题。

答案 2 :(得分:0)

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

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

示例:

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