Redis 占用所有内存和崩溃

Nyx*_*nyx 16 nosql performance memory ubuntu redis

redis 服务器 v2.8.4 在 Ubuntu 14.04 VPS 上运行,具有 8 GB RAM 和 16 GB 交换空间(在 SSD 上)。但是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
Run Code Online (Sandbox Code Playgroud)

redis-server从 OOM 崩溃或service redis-server force-reload导致内存使用量下降到 <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-server4.4G RAM和22.6G Swap时,redis中所有key所占用的空间量仅为rdbtools60.59636307 MB报告的那样。这也是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
Run Code Online (Sandbox Code Playgroud)

Ita*_*ber 10

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

编辑:

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

也可以free -m代替 top 来查看 RAM 状态的全貌(http://www.linuxatemyram.com/)。


Bri*_*ski 5

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

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

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

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

现在,我为服务器找到的最好的内存分配器是 JEMalloc。我们现在在Aerospike使用它来减少(几乎消除)长期内存碎片。JEMalloc 有一个特性,它允许你创建一个内存“竞技场”(池),并在任何分配上,选择哪个池,从而为你提供类似大小的分配并管理类似的内存生命周期分配。在你所讨论的那种情况下,这对我们来说是一个巨大的胜利。

Zend PHP 引擎在这方面很复杂,因为引擎内部的所有分配要么在每个事务内存中,要么在全局内存中。每个事务的内存在事务结束时一举释放,因此非常高效。

如果您使用的是 Linux,内核内存分配器 (Clib) 会经历许多曲折,您使用的版本将极大地决定碎片量,实际应用程序模式也是如此。例如,当您稍微增加对象时,有些分配器要好得多,有些则要差得多。遗憾的是,即使与其他 Redis 用户讨论也意味着谈论您正在使用的操作系统和操作系统版本。

您可以重新启动服务器(从持久性)并恢复内存的事实可能意味着泄漏,但更有可能指向碎片。

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