web-dev-qa-db-fra.com

échec de redis bgsave car fork ne peut pas allouer de mémoire

tous: voici mes informations sur la mémoire du serveur avec 'free -m'

              total       used       free     shared    buffers     cached
 Mem:         64433       49259      15174          0          3         31
 -/+ buffers/cache:      49224      15209
 Swap:         8197        184       8012

mon serveur redis a utilisé de la mémoire 46G, il reste presque 15G de mémoire libre

Comme je le sais, fork est une copie en écriture, il ne devrait pas échouer quand il y a de la mémoire libre de 15G, ce qui est suffisant pour malloc les structures de noyau nécessaires.

en outre, lorsque redis-server a utilisé de la mémoire 42G, bgsave est ok et fork est ok aussi.

Y a-t-il un paramètre vm que je peux régler pour réussir le retour de fork?

44
Jim Gray

Depuis proc (5) pages de manuel:

/ proc/sys/vm/overcommit_memory

Ce fichier contient le mode de comptabilité de la mémoire virtuelle du noyau. Les valeurs sont:

0: surcharge heuristique (c'est la valeur par défaut)

1: toujours surcharger, ne jamais vérifier

2: vérifiez toujours, ne surchargez jamais

En mode 0, les appels de mmap (2) avec MAP_NORESERVE définis ne sont pas vérifiés, et la vérification par défaut est très faible, entraînant le risque d'obtenir un processus "OOM-kill". Sous Linux 2.4, toute valeur non nulle implique le mode 1. En mode 2 (disponible depuis Linux 2.6), l'espace d'adressage virtuel total sur le système est limité à (SS + RAM * (r/100)), où SS est la taille de l'espace de swap, et RAM est la taille de la mémoire physique, et r est le contenu du fichier/proc/sys/vm/overcommit_ratio.

26
Utoah

Plus précisément, à partir de la FAQ Redis

Le schéma d'enregistrement en arrière-plan de Redis repose sur la sémantique de copie sur écriture de fork dans les systèmes d'exploitation modernes: les fourches Redis (créent un processus enfant) qui est une copie exacte du parent. Le processus enfant vide la base de données sur le disque et se termine finalement. En théorie, l'enfant devrait utiliser autant de mémoire que le parent étant une copie, mais en fait grâce à la sémantique de copie sur écriture implémentée par la plupart des systèmes d'exploitation modernes, le processus parent et enfant partagera les pages de mémoire communes. Une page ne sera dupliquée que lorsqu'elle change chez l'enfant ou chez le parent. Étant donné qu'en théorie, toutes les pages peuvent changer pendant que le processus enfant enregistre, Linux ne peut pas dire à l'avance la quantité de mémoire que l'enfant prendra, donc si le paramètre overcommit_memory est défini sur zéro, fork échouera à moins qu'il y ait autant de _ RAM comme requis pour vraiment dupliquer toutes les pages de mémoire parent, avec pour résultat que si vous avez un jeu de données Redis de 3 Go et seulement 2 Go de mémoire libre, il échouera.

Mettre overcommit_memory à 1 indique à Linux de détendre et d'effectuer le fork d'une manière d'allocation plus optimiste, et c'est en effet ce que vous voulez pour Redis.

Redis n'a pas besoin d'autant de mémoire que le système d'exploitation le pense pour écrire sur le disque, il peut donc échouer de manière préventive.

74
Jeff Atwood

Modifier /etc/sysctl.conf et ajouter:

vm.overcommit_memory=1

Redémarrez ensuite sysctl avec:

Sur FreeBSD:

Sudo /etc/rc.d/sysctl reload

Sous Linux:

Sudo sysctl -p /etc/sysctl.conf
58
Ganesh Krishnan