Redis占用了所有内存和崩溃


12

Redis服务器v2.8.4在具有8 GB RAM和16 GB交换空间(在SSD上)的Ubuntu 14.04 VPS上运行。但是,htop表明redis独自占用了22.4 G内存!

redis-server最终由于内存不足而崩溃。Mem并且Swp两个命中率均达到100%,然后redis-server与其他服务一起被杀死。

来自dmesg

[165578.047682] Out of memory: Kill process 10155 (redis-server) score 834 or sacrifice child
[165578.047896] Killed process 10155 (redis-server) total-vm:31038376kB, anon-rss:5636092kB, file-rss:0kB

redis-server从其他方面重新启动可能service redis-server force-reload会导致OOM崩溃或导致内存使用量降至<100MB。

问题:为什么在redis-server崩溃之前会占用越来越多的内存?我们如何防止这种情况?

是真的,maxmemory因为redis达到maxmemory极限后,设置将无法删除,因此设置将无法工作吗?

在此处输入图片说明 在此处输入图片说明

重启redis-server后

在此处输入图片说明 在此处输入图片说明

Redis版本: Redis server v=2.8.4 sha=00000000:0 malloc=jemalloc-3.4.1 bits=64 build=a44a05d76f06a5d9


更新资料

htop报告的内存使用量redis-server是4.4G RAM和22.6G交换,所有的钥匙,redis的占用的空间量仅为60.59636307 MB,所报告的rdbtools。这也是redis-server重启后立即占用的RAM量。

INFO ALL什么时候redis-server占用大量内存

mem_fragmentation_ratio:0.19

127.0.0.1:6379> INFO all

# Server
redis_version:2.8.4
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:a44a05d76f06a5d9
redis_mode:standalone
os:Linux 3.13.0-24-generic x86_64
arch_bits:64
multiplexing_api:epoll
gcc_version:4.8.2
process_id:26858
run_id:4d4a507b325e567d5ada203a0c65891bcf4d02de
tcp_port:6379
uptime_in_seconds:100011
uptime_in_days:1
hz:10
lru_clock:165668
config_file:/etc/redis/redis.conf

# Clients
connected_clients:60
client_longest_output_list:768774
client_biggest_input_buf:0
blocked_clients:0

# Memory
used_memory:23973468008
used_memory_human:22.33G
used_memory_rss:4563857408
used_memory_peak:24083474760
used_memory_peak_human:22.43G
used_memory_lua:33792
mem_fragmentation_ratio:0.19
mem_allocator:jemalloc-3.4.1

# Persistence
loading:0
rdb_changes_since_last_save:127835154
rdb_bgsave_in_progress:0
rdb_last_save_time:1406716479
rdb_last_bgsave_status:err
rdb_last_bgsave_time_sec:1
rdb_current_bgsave_time_sec:-1
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok

# Stats
total_connections_received:110
total_commands_processed:386765263
instantaneous_ops_per_sec:3002
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
evicted_keys:0
keyspace_hits:1385878
keyspace_misses:23655
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:82

# Replication
role:master
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

# CPU
used_cpu_sys:10547.48
used_cpu_user:8240.36
used_cpu_sys_children:201.83
used_cpu_user_children:914.86

# Commandstats
cmdstat_del:calls=136,usec=1407,usec_per_call=10.35
cmdstat_exists:calls=161428,usec=1391252,usec_per_call=8.62
cmdstat_zadd:calls=64149642,usec=936323882,usec_per_call=14.60
cmdstat_zrem:calls=137,usec=2131,usec_per_call=15.55
cmdstat_zremrangebyscore:calls=2293,usec=111905082,usec_per_call=48802.91
cmdstat_zrange:calls=7925,usec=285907448,usec_per_call=36076.65
cmdstat_zrangebyscore:calls=921434,usec=292731002,usec_per_call=317.69
cmdstat_zcount:calls=8,usec=172,usec_per_call=21.50
cmdstat_zrevrange:calls=191184,usec=965447,usec_per_call=5.05
cmdstat_zcard:calls=5180,usec=13502,usec_per_call=2.61
cmdstat_zscore:calls=29856,usec=576044,usec_per_call=19.29
cmdstat_hset:calls=64145124,usec=199407095,usec_per_call=3.11
cmdstat_hget:calls=248487,usec=501220,usec_per_call=2.02
cmdstat_hincrby:calls=128339355,usec=2071112929,usec_per_call=16.14
cmdstat_hgetall:calls=193747,usec=1608260,usec_per_call=8.30
cmdstat_select:calls=1,usec=5,usec_per_call=5.00
cmdstat_rename:calls=134,usec=1090,usec_per_call=8.13
cmdstat_keys:calls=4503,usec=4997628,usec_per_call=1109.84
cmdstat_bgsave:calls=2,usec=20012,usec_per_call=10006.00
cmdstat_type:calls=603,usec=2736,usec_per_call=4.54
cmdstat_multi:calls=64181979,usec=383633610,usec_per_call=5.98
cmdstat_exec:calls=64181979,usec=4403181204,usec_per_call=68.60
cmdstat_info:calls=126,usec=28675,usec_per_call=227.58

# Keyspace
db0:keys=2109,expires=0,avg_ttl=0

Answers:


8
  1. 使用maxmemory来设置您的Redis数据库也可以增长的限制。如果不这样做,Redis将一直增长,直到内存耗尽后操作系统将其杀死为止(根据您当前的经验)。
  2. 的使用maxmemory应结合使用maxmemory-policy-您可以根据用例的要求从不同的驱逐策略中进行选择。例如,如果您使用allkeys-lru逐出策略,maxmemory则在达到数据后,Redis确实会开始逐出(最近最少使用)数据。或者,您可以使用volatile-lruvolatile-random策略指示Redis仅逐出可过期的数据。最后,您可以将策略设置为,noeviction但这意味着一旦内存用完,Redis将拒绝使用OOM消息进行进一步的写入。

编辑:

首先禁用交换-Redis和交换不容易混合,这肯定会导致速度变慢。

另外,也不free -m要用top来查看RAM状态的完整图片(http://www.linuxatemyram.com/)。


谢谢,我对为什么内存使用率持续增长感到困惑,但是执行a bgsave然后重新启动redis-server会导致内存使用率下降到更合理的70 MB值。这可能是内存泄漏吗?
Nyxynyx

可能但不太可能(或其他人会报告)...更可能出现碎片问题。下次发生这种情况时,请发布Redis'的输出INFO ALL。如果我的猜测是正确的,那么mem_fragmentation_ratio意志将是空前的。
Itamar Haber 2014年

redis-server占用所有内存并每天崩溃。现在它将要用完所有内存,因此我已经捕获INFO ALL了OP 的输出并将其添加到OP。mem_fragmentation_ratio:0.19
Nyxynyx

如果redis数据集不超过250MB且maxmemory设置为1 GB,这是否意味着当redis的内存使用量达到1GB时,逐出仍会删除数据吗?由于redis mem_fragmentation_ratio0.19,这是否意味着碎片太多,或在swap中存储太多,或两者都存在?有什么办法可以减少碎片?
Nyxynyx

当redis-server由于OOM而崩溃时,rdbtools显示redis中的密钥仅占用60MB。这看起来非常严重吗?考虑到它占用了4.4GB的RAM和22.4G的Swap。
Nyxynyx

5

几乎可以肯定这是内存碎片,因为redis在生产中广为人知并广受喜爱,您可能还没有发现内存泄漏。

有关设置池大小的建议不会帮助您解决问题。您必须专门降低Redis的大小-低于您的实际内存大小-因为Redis无法解决碎片问题-但是,就简短的回答而言,您必须这样做,然后开始重新启动您的计划服务器频繁。

我在各种操作系统和内存数据库中使用的经验法则是,您需要的实际内存是实际内存的2倍,并且内存大小将在大约2周内稳定下来。

但是,这取决于您的实际分配模式以及所使用的内存分配器。

现在,我为服务器找到的最好的内存分配器是JEMalloc。我们现在在Aerospike上使用它来减少(几乎消除)长期内存碎片。JEMalloc具有允许您创建内存“舞台”(池)的功能,并且可以在任何分配上选择哪个池,从而为您提供大小相同的分配并管理类似的内存生存期分配。在您正在讨论的案例中,这对我们来说是一个巨大的胜利。

Zend PHP引擎在这方面很复杂,因为引擎内部的所有分配都位于每个事务内存或全局内存中。每个事务的内存在事务结束时以一次一次刷新的方式释放,因此非常高效。

如果您使用的是Linux,则内核内存分配器(Clib)经历了许多曲折,而您所使用的版本将像实际的应用程序模式一样,极大地决定碎片的数量。例如,当您稍微增加对象时,有些分配器会更好,而有些则更差。遗憾的是,即使与其他Redis用户进行讨论也意味着要谈论您正在使用哪个OS,以及哪个OS版本。

您可以(从持久性)重新启动服务器并恢复内存,这一事实可能意味着泄漏,但更可能表明存在碎片。

  1. 禁止交换(对于OOM,比对Redis进行交换要好得多)
  2. 减少Redis的内存大小
  3. 按计划重启

通过调整如何减少内存大小maxmemory
Nyxynyx
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.