Сбой 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

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

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

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

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

Благодарю.

4 ответа

Решение

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

/ Proc / SYS / VM / overcommit_memory

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

0: эвристический overcommit (по умолчанию)

1: всегда превышать, никогда не проверять

2: всегда проверяйте, никогда не переусердствуйте

В режиме 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.

Более конкретно из FAQ по Redis

Схема фонового сохранения Redis опирается на семантику "копировать при записи" в современных операционных системах: Redis разветвляется (создает дочерний процесс), который является точной копией родительского. Дочерний процесс выгружает БД на диск и, наконец, завершает работу. Теоретически ребенок должен использовать столько же памяти, сколько родительский объект, являющийся копией, но фактически благодаря семантике "копирование при записи", реализованной большинством современных операционных систем, родительский и дочерний процессы будут совместно использовать страницы общей памяти. Страница будет продублирована только тогда, когда она изменяется в дочернем или родительском элементе. Поскольку теоретически все страницы могут изменяться во время сохранения дочернего процесса, Linux не может заранее определить, сколько памяти займет дочерний процесс, поэтому, если для параметра overcommit_memory задано нулевое значение, ветвь не будет работать, если не будет столько свободной оперативной памяти, сколько требуется действительно дублировать все родительские страницы памяти, в результате чего, если у вас есть набор данных Redis 3 ГБ и всего 2 ГБ свободной памяти, это не удастся.

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

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

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

vm.overcommit_memory=1

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

На FreeBSD:

sudo /etc/rc.d/sysctl reload

В Linux:

sudo sysctl -p /etc/sysctl.conf

Метод моментальных снимков Redis на основе форка может эффективно удвоить использование физической памяти и легко использовать OOM в таких случаях, как ваш. Зависимость от виртуальной памяти Linux для создания моментальных снимков проблематична, поскольку Linux не имеет представления о структурах данных Redis.

Недавно был выпущен новый redis-совместимый проект Dragonfly .Среди прочего, он полностью решает проблему OOM. (раскрытие - я автор этого проекта).

Другие вопросы по тегам