Ein Redis Server v2.8.4 läuft auf einem Ubuntu 14.04 VPS mit 8 GB RAM und 16 GB Swap Space (auf SSDs). htop
Zeigt jedoch , dass redis
allein 22.4 G
Speicherplatz beansprucht!
redis-server
stürzte schließlich wegen aus dem Gedächtnis. Mem
und Swp
beide Treffer 100% werden dann redis-server
zusammen mit anderen Diensten getötet.
Von 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
Ein Neustart redis-server
von einem OOM-Absturz oder einem führt dazu, service redis-server force-reload
dass die Speichernutzung auf <100 MB sinkt.
Frage: Warum belegt es redis-server
immer mehr Speicher, bis es abstürzt? Wie können wir das verhindern?
Stimmt es, dass die Einstellung maxmemory
nicht funktioniert, denn sobald Redis das maxmemory
Limit erreicht, werden Daten entfernt?
Nach dem Neustart von redis-server
Redis-Version: Redis server v=2.8.4 sha=00000000:0 malloc=jemalloc-3.4.1 bits=64 build=a44a05d76f06a5d9
Aktualisieren
Wenn htop
Berichte über die Speicherauslastung redis-server
4.4G RAM und 22,6 g Swap zu sein, ist die Menge an Raum , der durch alle Schlüssel in redis aufgenommen nur 60.59636307 MB
, wie berichtet rdbtools . Dies ist auch die Menge an RAM, die redis-server
direkt nach dem Neustart belegt wird.
INFO ALL
Wann redis-server
nimmt Tonnen von Speicher in Anspruch
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
bgsave
und einen Neustart durchführenredis-server
, sinkt die Speichernutzung auf einen vernünftigeren Wert von 70 MB. Könnte dies ein Speicherverlust sein?INFO ALL
. Wenn meine Vermutung richtig ist, ist dermem_fragmentation_ratio
Wille himmelhoch.redis-server
verschlingt die ganze Erinnerung und stürzt jeden Tag ab. Es ist dabei, den gesamten Speicher zu verbrauchen, also habe ich die Ausgabe von erfasstINFO ALL
und zum OP hinzugefügt.mem_fragmentation_ratio:0.19
maxmemory
auf 1 GB festgelegt sind, bedeutet dies, dass bei einer Redis-Mem-Nutzung von 1 GB durch die Räumung weiterhin Daten entfernt werden? Da redis dermem_fragmentation_ratio
ist0.19
, bedeutet es , dass zu viel Fragmentierung Theres, oder zu viel ist in Swap oder beides gespeichert? Wie kann die Fragmentierung reduziert werden?Dies ist mit ziemlicher Sicherheit eine Speicherfragmentierung, da Redis in der Produktion bekannt und beliebt ist und Sie wahrscheinlich kein Speicherleck gefunden haben.
Die Empfehlungen zum Festlegen der Größe des Pools helfen nicht bei der Fragmentierung. Sie müssen die Redis-Größe gezielt verringern - niedriger als Ihre tatsächliche Speichergröße -, da Redis keine Fragmentierung berücksichtigen kann. In Bezug auf eine kurze Antwort müssen Sie dies jedoch tun und einen Neustart planen Server häufig.
Meine Faustregel bei der Arbeit mit einer Vielzahl von Betriebssystemen und In-Memory-Datenbanken lautet, dass Sie das Zweifache Ihres tatsächlichen Speichers benötigen und sich die Speichergröße in etwa 2 Wochen stabilisieren wird.
Dies hängt jedoch von Ihren tatsächlichen Zuordnungsmustern und dem von Ihnen verwendeten Speicherzuweiser ab.
Derzeit ist JEMalloc der beste Speicherzuweiser, den ich für Server gefunden habe. Wir verwenden es jetzt bei Aerospike , um die Fragmentierung des Langzeitgedächtnisses zu reduzieren (fast zu entfernen). JEMalloc verfügt über eine Funktion, mit der Sie eine Speicher- "Arena" (Pool) erstellen und bei jeder Zuweisung auswählen können, welcher Pool verwendet werden soll. Auf diese Weise erhalten Sie Zuordnungen gleicher Größe und können ähnliche Zuordnungen für die Speicherlebensdauer verwalten. Es war ein großer Gewinn für uns in den Fällen, die Sie diskutieren.
Die Zend PHP-Engine ist in dieser Hinsicht hochentwickelt, da sich alle Zuordnungen innerhalb der Engine entweder im Transaktionsspeicher oder im globalen Speicher befinden. Pro Transaktion wird der Speicher am Ende der Transaktion auf einen Schlag freigegeben und kann daher sehr effizient sein.
Wenn Sie unter Linux arbeiten, hat der Kernel-Speicherzuweiser (Clib) eine Reihe von Drehungen und Wendungen vorgenommen. Welche Version Sie verwenden, bestimmt den Grad der Fragmentierung ebenso wie das tatsächliche Anwendungsmuster erheblich. Zum Beispiel sind einige Allokatoren viel besser, wenn Sie Objekte leicht wachsen lassen, andere sind viel schlechter. Selbst wenn Sie mit anderen Redis-Benutzern diskutieren, müssen Sie leider darüber sprechen, welches Betriebssystem und welche Betriebssystemversion Sie verwenden.
Die Tatsache, dass Sie den Server neu starten können (aus Gründen der Persistenz) und Ihren Speicher zurückerhalten können, könnte ein Leck bedeuten, deutet jedoch eher auf eine Fragmentierung hin.
quelle
maxmemory
?