Подтвердить что ты не робот

Redis bgsave не удалось, потому что fork не может выделить память

все: вот информация о памяти моего сервера с 'free -m'

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

мой redis-сервер использовал память 46 ГБ, почти 15 ГБ памяти осталось свободным

Насколько мне известно, fork является копией при записи, он не должен завершаться сбоем, когда имеется 15 ГБ свободной памяти, что достаточно для размещения необходимых структур ядра.

кроме того, когда redis-сервер использовал 42G памяти, bgsave в порядке и fork тоже в порядке.

Есть ли параметр vm, который я могу настроить, чтобы форк возвращал успех?

4b9b3361

Ответ 1

Из справочных страниц proc (5):

/proc/sys/vm/overcommit_memory

Этот файл содержит режим учета виртуальной памяти ядра. Значения:

0: heuristic overcommit (this is the default)

1: always overcommit, never check

2: always check, never overcommit

В режиме 0 вызовы mmap (2) с установленным MAP_NORESERVE не проверяются, и проверка по умолчанию очень слабая, что приводит к риску получения процесса "OOM-kill". Под Linux 2.4 любое ненулевое значение подразумевает режим 1. В режиме 2 (доступно с Linux 2.6) общее виртуальное адресное пространство в системе ограничено (SS + RAM * (r/100)), где SS - размер пространства подкачки, RAM - размер физической памяти, а r - содержимое файла /proc/sys/vm/overcommit_ratio.

Ответ 2

В частности, из часто задаваемых вопросов о Redis

Redis background saving schema полагается на семантику fork для копирования в современных операционных системах: Redis forks (создает дочерний процесс), который является точной копией родителя. Детский процесс выгружает БД на диск и, наконец, выходит. Теоретически ребенок должен использовать столько же памяти, сколько и родительский экземпляр, но на самом деле благодаря семантике copy-on-write, реализованной большинством современных операционных систем, родительский и дочерний процессы будут совместно использовать общие страницы памяти. Страница будет дублироваться только тогда, когда она изменяется в дочернем или родительском. Так как теоретически все страницы могут меняться при сохранении дочернего процесса, Linux не может заранее сказать, сколько памяти будет принимать ребенок, поэтому, если параметр overcommit_memory установлен на ноль, fork будет терпеть неудачу, если не будет столько свободной ОЗУ, сколько требуется, чтобы действительно дублировать все родительские страницы памяти, в результате чего, если у вас есть набор данных Redis объемом 3 ГБ и всего 2 ГБ свободной памяти, он не сработает.

Установка overcommit_memory в 1 говорит Linux, чтобы расслабиться и выполнить вилку в более оптимистичном режиме размещения, и это действительно то, что вы хотите для Redis.

Redis не нуждается в такой большой памяти, как OS думает, что она делает для записи на диск, поэтому может предварительно прервать вилку.

Ответ 3

Измените /etc/sysctl.conf и добавьте:

vm.overcommit_memory=1

Затем перезапустите sysctl с помощью:

В FreeBSD:

sudo /etc/rc.d/sysctl reload

В Linux:

sudo sysctl -p /etc/sysctl.conf