Redis prend toute la mémoire et plante

12

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 htopmontre cependant que redisseul prend 22.4 Gde la mémoire!

redis-servers'est finalement écrasé en raison de la rupture de mémoire. Memet les Swpdeux frappent à 100% puis redis-serversont 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-serverredémarrage depuis etiher entraîne un plantage du MOO ou une service redis-server force-reloadbaisse de l'utilisation de la mémoire à <100 Mo.

Question: Pourquoi redis-serveroccupe- 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 maxmemoryne fonctionnera pas car une fois que redis atteint la maxmemorylimite, il commencera à supprimer les données?

entrez la description de l'image ici entrez la description de l'image ici

Après avoir redémarré redis-server

entrez la description de l'image ici entrez la description de l'image ici

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


Mise à jour

Lorsque le htoprapport indique que l'utilisation de la mémoire redis-serverest 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-serverjuste après le redémarrage.

INFO ALLquand redis-serverprend 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
Nyxynyx
la source

Réponses:

8
  1. Utilisez le maxmemorypour définir une limite à la croissance de votre base de données Redis. Sinon, Redis grandira jusqu'à ce que le système d'exploitation le tue une fois la mémoire épuisée (selon votre expérience actuelle).
  2. L'utilisation de maxmemorydoit être associée à maxmemory-policy- vous pouvez choisir parmi différentes politiques d'expulsion en fonction des exigences de votre cas d'utilisation. Par exemple, si vous utilisez la allkeys-lrupolitique d'expulsion, Redis commencera en effet à expulser les données (les moins récemment utilisées) une fois qu'elles auront maxmemoryété atteintes. Vous pouvez également demander à Redis d'expulser uniquement les données expirables avec les politiques volatile-lruou volatile-random. Enfin, vous pouvez définir la stratégie sur noevictionmais cela signifierait qu'une fois la mémoire épuisée, Redis refusera les écritures supplémentaires avec un message OOM.

Éditer:

Tout d'abord désactiver le swap - Redis et swap ne se mélangent pas facilement, ce qui peut certainement provoquer une lenteur.

free -mFaites également au lieu de top pour l'image complète de l'état de votre RAM ( http://www.linuxatemyram.com/ ).

Itamar Haber
la source
Merci, je ne comprends pas pourquoi l'utilisation de la mémoire continue de croître, mais faire un bgsaveredémarrage redis-serverentraîne une baisse de l'utilisation de la mémoire à une valeur plus raisonnable de 70 Mo. Serait-ce une fuite de mémoire?
Nyxynyx
Possible mais peu probable (ou d'autres personnes l'auraient signalé) ... Plus probablement un problème de fragmentation. La prochaine fois que cela se produira, postez la sortie de votre Redis ' INFO ALL. Si ma supposition est correcte, la mem_fragmentation_ratiovolonté va très haut.
Itamar Haber
redis-servermonopolise 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 de INFO ALLet ajouté à l'OP. mem_fragmentation_ratio:0.19
Nyxynyx du
Si les jeux de données redis ne dépassent pas 250 Mo et maxmemorysont 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 redis mem_fragmentation_ratioest 0.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?
Nyxynyx
Lorsque redis-server est sur le point de se bloquer en raison d'un MOO, rdbtools montre que les clés de redis ne prennent que 60 Mo. Cela ressemble à une fragmentation extrêmement grave? Compte tenu de sa prise de 4,4 Go de RAM et 22,4 G de Swap.
Nyxynyx
5

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.

  1. Interdire le swap (c'est mieux pour MOO que pour swap, pour redis)
  2. Diminue la taille de la mémoire de redis
  3. Redémarrez selon un calendrier
Brian Bulkowski
la source
Comment diminueriez-vous la taille de la mémoire en ajustant maxmemory?
Nyxynyx