Un serveur redis v2.8.4 fonctionne sur un VPS Ubuntu 14.04 avec 8 Go de RAM et 16 Go d'espace de swap (sur les SSD). Cela htop
montre cependant que redis
seul prend 22.4 G
de la mémoire!
redis-server
s'est finalement écrasé en raison de la rupture de mémoire. Mem
et les Swp
deux frappent à 100% puis redis-server
sont tués avec d'autres services.
De 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
Le redis-server
redémarrage depuis etiher entraîne un plantage du MOO ou une service redis-server force-reload
baisse de l'utilisation de la mémoire à <100 Mo.
Question: Pourquoi redis-server
occupe- t-il de plus en plus de mémoire jusqu'à ce qu'il se bloque? Comment éviter cela?
Est-il vrai que le réglage maxmemory
ne fonctionnera pas car une fois que redis atteint la maxmemory
limite, il commencera à supprimer les données?
Après avoir redémarré redis-server
Version redis: Redis server v=2.8.4 sha=00000000:0 malloc=jemalloc-3.4.1 bits=64 build=a44a05d76f06a5d9
Mise à jour
Lorsque le htop
rapport indique que l'utilisation de la mémoire redis-server
est de 4,4 Go de RAM et 22,6 Go de swap, la quantité d'espace occupée par toutes les clés dans redis est seulement 60.59636307 MB
, comme indiqué par rdbtools . C'est également la quantité de RAM occupée redis-server
juste après le redémarrage.
INFO ALL
quand redis-server
prend des tonnes de mémoire
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
redémarrageredis-server
entraîne une baisse de l'utilisation de la mémoire à une valeur plus raisonnable de 70 Mo. Serait-ce une fuite de mémoire?INFO ALL
. Si ma supposition est correcte, lamem_fragmentation_ratio
volonté va très haut.redis-server
monopolise toute la mémoire et plante tous les jours. Il est sur le point d'utiliser toute la mémoire maintenant, j'ai donc capturé la sortie deINFO ALL
et ajouté à l'OP.mem_fragmentation_ratio:0.19
maxmemory
sont définis sur 1 Go, cela signifie-t-il que lorsque l'utilisation de mem de redis atteint 1 Go, l'expulsion supprimera toujours les données? Étant donné que le redismem_fragmentation_ratio
est0.19
, cela signifie-t-il qu'il y a trop de fragmentation, ou trop est stocké dans le swap, ou les deux? Une façon de réduire la fragmentation?Il s'agit presque certainement d'une fragmentation de la mémoire, car redis est bien connu et apprécié en production et vous n'avez probablement pas trouvé de fuite de mémoire.
Les recommandations sur la définition de la taille du pool n'aideront pas à la fragmentation. Vous devrez spécifiquement réduire la taille de Redis - inférieure à la taille réelle de votre mémoire - car Redis ne peut pas tenir compte de la fragmentation - mais, en termes de réponse courte, vous devrez le faire et commencer à planifier le redémarrage de votre serveurs fréquemment.
Ma règle de base pour travailler avec une variété de systèmes d'exploitation et de bases de données en mémoire est que vous avez besoin de 2x votre mémoire réelle, et la taille de la mémoire se stabilisera dans environ 2 semaines.
Cependant, cela dépend de vos modèles d'allocation réels et de l'allocateur de mémoire que vous utilisez.
À l'heure actuelle, le meilleur allocateur de mémoire que j'ai trouvé pour les serveurs est JEMalloc. Nous l'utilisons maintenant chez Aerospike pour réduire (presque supprimer) la fragmentation de la mémoire à long terme. JEMalloc a une fonctionnalité qui vous permet de créer une "arène" de mémoire (pool), et sur n'importe quelle allocation, choisissez quel pool, vous donnant ainsi des allocations de même taille et pour gérer des allocations de durée de vie de mémoire similaires. Cela a été une grande victoire pour nous dans le genre de cas dont vous discutez.
Le moteur PHP Zend est sophistiqué à cet égard, car toutes les allocations à l'intérieur du moteur sont soit dans la mémoire par transaction, soit dans la mémoire globale. Par transaction, la mémoire est libérée d'un coup à la fin de la transaction et peut donc être très efficace.
Si vous êtes sous Linux, l'allocateur de mémoire du noyau (Clib) a pris un certain nombre de rebondissements, et la version sur laquelle vous vous trouvez déterminera considérablement la quantité de fragmentation, tout comme le modèle d'application réel. Par exemple, certains allocateurs sont bien meilleurs lorsque vous faites légèrement pousser des objets, certains sont bien pires. Malheureusement, même discuter avec d'autres utilisateurs de Redis signifie parler du système d'exploitation et de la version du système d'exploitation que vous utilisez.
Le fait que vous puissiez redémarrer le serveur (à partir de la persistance) et récupérer votre mémoire peut signifier une fuite, mais indique plus probablement une fragmentation.
la source
maxmemory
?