18.4. Управление ресурсами ядра#

18.4. Управление ресурсами ядра

18.4. Управление ресурсами ядра

Tantor SE иногда может исчерпывать различные ограничения операционной системы, особенно когда на одной системе работает несколько копий сервера или в очень больших установках. В этом разделе объясняются ресурсы ядра, используемые Tantor SE, и шаги, которые можно предпринять для решения проблем, связанных с потреблением ресурсов ядра.

18.4.1. Общая память и семафоры

Для работы Tantor SE требуется, чтобы операционная система предоставляла возможности обмена данными между процессами (IPC), в частности общую память и семафоры. В системах, на базе Unix, обычно предоставляются System V IPC, POSIX IPC или оба вида. Windows имеет собственную реализацию этих возможностей, о которой здесь не рассказывается.

По умолчанию, Tantor SE выделяет очень малое количество общей памяти System V, и гораздо больше анонимной общей памяти mmap. Также можно использовать одну большую область общей памяти System V (см. shared_memory_type). Кроме того, при запуске сервера создается значительное количество семафоров, которые могут быть как вида System V, так и POSIX. В настоящее время на системах Linux и FreeBSD используются POSIX-семафоры, в то время как на других платформах используются семафоры System V.

Функции IPC System V обычно ограничены глобальными пределами выделения. Когда Tantor SE превышает один из этих пределов, сервер откажется запускаться и должен выдать информативное сообщение об ошибке, описывающее проблему и что с ней делать. (См. также Раздел 18.3.1). Соответствующие параметры ядра имеют одинаковые имена в разных системах; Таблица 18.1 дает обзор. Однако, методы их установки различаются. Ниже приведены рекомендации для некоторых платформ.

Таблица 18.1. System V IPC Параметры

ИмяОписаниеЗначения, необходимые для запуска одного экземпляра Tantor SE
SHMMAXМаксимальный размер сегмента общей памяти (в байтах)не менее 1 кБ, но по умолчанию обычно гораздо больше
SHMMINМинимальный размер сегмента общей памяти (в байтах)1
SHMALLОбщее количество доступной общей памяти (в байтах или страницах)то же самое, что и SHMMAX, если в байтах, или ceil(SHMMAX/PAGE_SIZE), если в страницах, плюс место для других приложений
SHMSEGМаксимальное количество сегментов общей памяти на процесстребуется только 1 сегмент, но значение по умолчанию гораздо выше
SHMMNIМаксимальное количество общих сегментов памяти в системеаналогично SHMSEG, плюс место для других приложений
SEMMNIМаксимальное количество идентификаторов семафоров (т.е. наборов)как минимум ceil((max_connections + autovacuum_max_workers + max_wal_senders + max_worker_processes + 5) / 16) плюс место для других приложений
SEMMNSМаксимальное количество семафоров в системеceil((max_connections + autovacuum_max_workers + max_wal_senders + max_worker_processes + 5) / 16) * 17 плюс место для других приложений
SEMMSLМаксимальное количество семафоров в наборене менее 17
SEMMAPКоличество записей в карте семафоровсм. текст
SEMVMXМаксимальное значение семафоране менее 1000 (По умолчанию часто устанавливается значение 32767; не изменяйте, если необходимо)

Tantor SE необходимо несколько байтов общей памяти System V (обычно 48 байтов на 64-битных платформах) для каждой копии сервера. На большинстве современных операционных систем достаточно легко выделить такой объем памяти. Однако, если вы запускаете много копий сервера или явно указываете серверу использовать большие объемы общей памяти System V (см. shared_memory_type и dynamic_shared_memory_type), может потребоваться увеличить значение SHMALL, которое представляет собой общий объем общей памяти System V в системе. Обратите внимание, что на многих системах SHMALL измеряется в страницах, а не в байтах.

Меньше вероятность возникновения проблем вызывает минимальный размер для общих сегментов памяти (SHMMIN), который должен быть не более примерно 32 байт для Tantor SE (обычно это всего лишь 1). Максимальное количество сегментов в системе (SHMMNI) или на процесс (SHMSEG) маловероятно вызовет проблемы, если они установлены в ноль.

При использовании семафоров System V Tantor SE использует один семафор для каждого разрешенного соединения (max_connections), разрешенного рабочего процесса автоочистки (autovacuum_max_workers) и разрешенного фонового процесса (max_worker_processes), в наборах по 16. Каждый такой набор также будет содержать 17-й семафор, который содержит магическое число, чтобы обнаружить столкновение с наборами семафоров, используемыми другими приложениями. Максимальное количество семафоров в системе устанавливается параметром SEMMNS, который, следовательно, должен быть не меньше, чем max_connections плюс autovacuum_max_workers плюс max_wal_senders, плюс max_worker_processes, плюс один дополнительный для каждых 16 разрешенных соединений и рабочих процессов (см. формулу в Таблица 18.1). Параметр SEMMNI определяет ограничение на количество наборов семафоров, которые могут существовать в системе одновременно. Следовательно, этот параметр должен быть не меньше, чем ceil((max_connections + autovacuum_max_workers + max_wal_senders + max_worker_processes + 5) / 16). Уменьшение количества разрешенных соединений является временным обходным решением для сбоев, которые обычно имеют запутанную формулировку No space left on device из функции semget.

В некоторых случаях может потребоваться увеличить значение параметра SEMMAP до значения, по крайней мере, порядка значения SEMMNS. Если в системе присутствует этот параметр (многие системы его не имеют), он определяет размер карты ресурсов семафоров, в которой каждый непрерывный блок доступных семафоров требует записи. При освобождении набора семафоров он либо добавляется к существующей записи, смежной с освобожденным блоком, либо регистрируется в новой записи карты. Если карта заполнена, освобожденные семафоры теряются (до перезагрузки). Фрагментация пространства семафоров со временем может привести к меньшему количеству доступных семафоров, чем должно быть.

Различные другие настройки, связанные с отменой семафора, такие как SEMMNU и SEMUME, не влияют на Tantor SE.

При использовании семафоров POSIX количество необходимых семафоров такое же, как и для System V, то есть один семафор на разрешенное соединение (max_connections), разрешенный рабочий процесс автоматической очистки (autovacuum_max_workers) и разрешенный фоновый процесс (max_worker_processes). На платформах, где предпочтительна эта опция, нет конкретного ограничения ядра на количество семафоров POSIX.

AIX

Необходимости в особой настройке для таких параметров, как SHMMAX, не должно возникать, так как, по-видимому, они настроены таким образом, чтобы позволить использовать всю память в качестве общей памяти. Такая конфигурация обычно используется для других баз данных, таких как DB/2.

Может быть необходимо изменить глобальную информацию ulimit в файле /etc/security/limits, так как значения по умолчанию для жестких ограничений размера файлов (fsize) и количества файлов (nofiles) могут быть слишком низкими.

FreeBSD

Настройки общей памяти по умолчанию обычно достаточно хороши, если только вы не установили shared_memory_type в sysv. Системные семафоры V не используются на этой платформе.

Настройки IPC по умолчанию можно изменить с помощью интерфейсов sysctl или loader. Следующие параметры можно установить с помощью sysctl:

# sysctl kern.ipc.shmall=32768
# sysctl kern.ipc.shmmax=134217728

Чтобы сделать эти настройки постоянными после перезагрузки, измените файл /etc/sysctl.conf.

Если вы установили shared_memory_type в значение sysv, вам также может потребоваться настроить ядро для блокировки System V общей памяти в оперативной памяти и предотвращения ее выгрузки в подкачку. Это можно сделать с помощью параметра sysctl kern.ipc.shm_use_phys.

Если вы работаете в тюрьме FreeBSD, вы должны установить параметр sysvshm в значение new, чтобы у него было собственное отдельное пространство имен System V для общей памяти. (До FreeBSD 11.0 было необходимо разрешить общий доступ к пространству имен IPC хоста из тюрем и принимать меры для избежания конфликтов).

NetBSD

Настройки общей памяти по умолчанию обычно достаточно хороши, если только вы не установили shared_memory_type в значение sysv. Обычно вам потребуется увеличить значения kern.ipc.semmni и kern.ipc.semmns, так как значения по умолчанию в NetBSD для этих параметров слишком малы и вызывают дискомфорт.

Параметры IPC могут быть настроены с помощью команды sysctl, например:

# sysctl -w kern.ipc.semmni=100

Чтобы сделать эти настройки постоянными после перезагрузки, измените файл /etc/sysctl.conf.

Если вы установили shared_memory_type в значение sysv, вам также может потребоваться настроить ядро для блокировки System V общей памяти в оперативной памяти и предотвращения ее выгрузки в подкачку. Это можно сделать с помощью параметра sysctl kern.ipc.shm_use_phys.

OpenBSD

Настройки общей памяти по умолчанию обычно достаточно хороши, если только вы не установили shared_memory_type в sysv. Обычно вам захочется увеличить kern.seminfo.semmni и kern.seminfo.semmns, так как значения по умолчанию в OpenBSD для этих параметров слишком малы и вызывают дискомфорт.

Параметры IPC могут быть настроены с помощью команды sysctl, например:

# sysctl kern.seminfo.semmni=100

Чтобы сделать эти настройки постоянными после перезагрузки, измените файл /etc/sysctl.conf.

HP-UX

Настройки по умолчанию обычно достаточны для обычных установок.

Параметры IPC могут быть установлены в Менеджере администрирования системы (SAM) под Конфигурация ядраНастройка параметров . Выберите Создание нового ядра когда вы закончите.

Linux

Настройки общей памяти по умолчанию обычно достаточно хороши, если только вы не установили shared_memory_type в sysv, и даже тогда только в старых версиях ядра, которые поставлялись с низкими значениями по умолчанию. Системные семафоры System V не используются на этой платформе.

Настройки размера общей памяти можно изменить через интерфейс sysctl. Например, чтобы разрешить 16 ГБ:

$ sysctl -w kernel.shmmax=17179869184
$ sysctl -w kernel.shmall=4194304

Чтобы сделать эти настройки постоянными после перезагрузки, см. /etc/sysctl.conf.

macOS

Настройки общей памяти и семафоров по умолчанию обычно достаточно хороши, если вы не установили shared_memory_type в значение sysv.

Рекомендуемый способ настройки общей памяти в macOS - создать файл с именем /etc/sysctl.conf, содержащий присваивания переменных, например:

kern.sysv.shmmax=4194304
kern.sysv.shmmin=1
kern.sysv.shmmni=32
kern.sysv.shmseg=8
kern.sysv.shmall=1024

Обратите внимание, что в некоторых версиях macOS все пять параметров общей памяти должны быть установлены в файле /etc/sysctl.conf, иначе значения будут проигнорированы.

SHMMAX может быть установлено только как кратное числу 4096.

SHMALL измеряется в страницах размером 4 кБ на данной платформе.

Возможно изменить все, кроме SHMMNI, на лету, используя sysctl. Однако лучше всего настроить предпочтительные значения через /etc/sysctl.conf, чтобы значения сохранялись после перезагрузки.

Solaris
illumos

Настройки общей памяти и семафоров по умолчанию обычно оптимальны для большинства приложений Tantor SE. В Solaris значение SHMMAX составляет одну четверть от общего объема RAM системы. Чтобы дополнительно настроить это значение, используйте настройки проекта, связанные с пользователем postgres. Например, выполните следующую команду от имени пользователя root:

projadd -c "PostgreSQL DB User" -K "project.max-shm-memory=(privileged,8GB,deny)" -U postgres -G postgres user.postgres

Эта команда добавляет проект user.postgres и устанавливает максимальный объем общей памяти для пользователя postgres в 8 ГБ. Изменения вступят в силу при следующем входе пользователя или при перезапуске Tantor SE (не перезагрузке). Предполагается, что Tantor SE запущен пользователем postgres в группе postgres. Перезагрузка сервера не требуется.

Другие рекомендуемые изменения настроек ядра для серверов баз данных, которые будут иметь большое количество соединений, включают:

project.max-shm-ids=(priv,32768,deny)
project.max-sem-ids=(priv,4096,deny)
project.max-msg-ids=(priv,4096,deny)

Кроме того, если вы запускаете Tantor SE внутри зоны, вам может потребоваться увеличить лимиты использования ресурсов зоны. См. "Глава 2: Проекты и задачи" в Руководство системного администратора для получения дополнительной информации о projects и prctl.

18.4.2. systemd RemoveIPC

Если systemd используется, необходимо обратить внимание на то, чтобы ресурсы IPC (включая общую память) не были преждевременно удалены операционной системой. Это особенно важно при установке PostgreSQL из исходного кода. Пользователи пакетов распространения PostgreSQL меньше подвержены этому влиянию, так как пользователь postgres обычно создается как системный пользователь.

Настройка RemoveIPC в logind.conf определяет, будут ли удалены IPC-объекты при полном выходе пользователя. Системные пользователи не подпадают под это правило. По умолчанию эта настройка в стандартной версии systemd включена, но в некоторых операционных системах она отключена.

Типичным наблюдаемым эффектом при включении этой настройки является то, что объекты общей памяти, используемые для параллельного выполнения запросов, удаляются на видимо случайные моменты времени, что приводит к ошибкам и предупреждениям при попытке открытия и удаления их, например

WARNING:  could not remove shared memory segment "/PostgreSQL.1450751626": No such file or directory

Различные типы объектов IPC (общая память против семафоров, System V против POSIX) обрабатываются немного по-разному systemd, поэтому можно заметить, что некоторые ресурсы IPC не удаляются так же, как другие. Однако не рекомендуется полагаться на эти тонкие различия.

Пользователь выходит из системы может происходить в рамках обслуживания задания или вручную, когда администратор входит в систему от имени пользователя postgres или что-то подобное, поэтому в общем случае его сложно предотвратить.

Что такое системный пользователь определяется во время компиляции systemd из настройки SYS_UID_MAX в файле /etc/login.defs.

Упаковочные и развертывающие скрипты должны быть осторожными при создании пользователя postgres в качестве системного пользователя с использованием команды useradd -r, adduser --system или аналогичной.

В противном случае, если учетная запись пользователя была создана неправильно или не может быть изменена, рекомендуется установить

RemoveIPC=no

в файле /etc/systemd/logind.conf или другом соответствующем файле конфигурации.

Предостережение

По крайней мере, одно из этих двух условий должно быть обеспечено, иначе сервер PostgreSQL будет очень ненадежным.

18.4.3. Ограничения ресурсов

Unix-подобные операционные системы применяют различные виды ограничений ресурсов, которые могут помешать работе вашего сервера Tantor SE. Особенно важны ограничения на количество процессов на пользователя, количество открытых файлов на процесс и объем памяти, доступный каждому процессу. Каждый из них имеет "жесткий" и "мягкий" пределы. Мягкий предел - это то, что на самом деле учитывается, но его можно изменить пользователем до жесткого предела. Жесткий предел может быть изменен только root-пользователем. Вызов системы setrlimit отвечает за установку этих параметров. Встроенная команда оболочки ulimit (для оболочек Bourne) или limit (для оболочки csh) используется для управления ограничениями ресурсов из командной строки. В системах, основанных на BSD, файл /etc/login.conf управляет различными ограничениями ресурсов, установленными при входе в систему. См. документацию операционной системы для получения подробной информации. Соответствующие параметры - maxproc, openfiles и datasize. Например:

default:\
...
        :datasize-cur=256M:\
        :maxproc-cur=256:\
        :openfiles-cur=256:\
...

(-cur - это мягкий предел. Добавьте -max для установки жесткого предела).

Ядра также могут иметь системные ограничения на некоторые ресурсы.

  • На Linux параметр ядра fs.file-max определяет максимальное количество открытых файлов, которое поддерживает ядро. Его можно изменить с помощью sysctl -w fs.file-max=N. Чтобы сохранить настройку после перезагрузки, добавьте присваивание в /etc/sysctl.conf. Максимальное ограничение файлов на процесс устанавливается во время компиляции ядра; см. /usr/src/linux/Documentation/proc.txt для получения дополнительной информации.

Сервер Tantor SE использует один процесс на соединение, поэтому вам следует предусмотреть не менее столько процессов, сколько разрешено соединений, в дополнение к тому, что вам нужно для остальной части вашей системы. Обычно это не является проблемой, но если вы запускаете несколько серверов на одной машине, могут возникнуть проблемы с ресурсами.

Ограничение по умолчанию на количество открытых файлов в фабрике часто устанавливается на "социально дружественные" значения, которые позволяют множеству пользователей сосуществовать на одной машине, не используя неподходящую долю системных ресурсов. Если вы запускаете много серверов на одной машине, то это, возможно, то, что вам нужно, но на выделенных серверах вы можете захотеть увеличить это ограничение.

С другой стороны, некоторые системы позволяют отдельным процессам открывать большое количество файлов; если это делают более нескольких процессов, то легко можно превысить системное ограничение. Если вы обнаружите, что это происходит и вы не хотите изменять системное ограничение, вы можете установить параметр конфигурации Tantor SE max_files_per_process, чтобы ограничить количество открытых файлов.

Другое ограничение ядра, которое может вызывать беспокойство при поддержке большого количества клиентских соединений, - это максимальная длина очереди сокетных соединений. Если в очень короткий период времени поступает больше запросов на соединение, чем может обработать постмастер, некоторые из них могут быть отклонены, и клиенты получат неинформативные ошибки подключения, такие как "Ресурс временно недоступен" или "Соединение отклонено". По умолчанию максимальная длина очереди составляет 128 на многих платформах. Чтобы увеличить ее, измените соответствующий параметр ядра с помощью sysctl, а затем перезапустите постмастер. Параметр имеет различные имена: net.core.somaxconn в Linux, kern.ipc.soacceptqueue в новых версиях FreeBSD и kern.ipc.somaxconn в macOS и других вариантах BSD.

18.4.4. Перераспределение памяти в Linux

По умолчанию, поведение виртуальной памяти в Linux не является оптимальным для Tantor SE. Из-за того, как ядро реализует перераспределение памяти, ядро может завершить работу постмастера Tantor SE (супервизора серверного процесса), если требования к памяти как у Tantor SE, так и у другого процесса приведут к исчерпанию виртуальной памяти системы.

Если это произойдет, вы увидите сообщение ядра, которое будет выглядеть примерно так (обратитесь к документации и конфигурации вашей системы, чтобы узнать, где искать такое сообщение):

Out of Memory: Killed process 12345 (postgres).

Это указывает на то, что процесс postgres был завершен из-за нехватки памяти. Хотя существующие подключения к базе данных будут продолжать функционировать нормально, новые подключения не будут приниматься. Для восстановления необходимо перезапустить Tantor SE.

Один из способов избежать этой проблемы - запустить Tantor SE на машине, где вы можете быть уверены, что другие процессы не будут использовать всю память. Если память ограничена, увеличение пространства подкачки операционной системы может помочь избежать проблемы, поскольку убийца процессов из-за нехватки памяти (OOM) вызывается только тогда, когда физическая память и пространство подкачки исчерпаны.

Если сама Tantor SE является причиной нехватки памяти в системе, вы можете избежать проблемы, изменив конфигурацию. В некоторых случаях может помочь снижение параметров конфигурации, связанных с памятью, особенно shared_buffers, work_mem и hash_mem_multiplier. В других случаях проблема может быть вызвана разрешением слишком большого количества подключений к самому серверу базы данных. Во многих случаях лучше уменьшить max_connections и вместо этого использовать внешнее программное обеспечение для пула подключений.

Возможно изменить поведение ядра так, чтобы оно не перераспределяло память. Хотя эта настройка не предотвратит полное вызова OOM killer, она значительно снизит вероятность его вызова и, следовательно, обеспечит более надежное поведение системы. Для этого выбирается строгий режим перераспределения памяти с помощью sysctl:

sysctl -w vm.overcommit_memory=2

или разместите эквивалентную запись в /etc/sysctl.conf. Вы также можете изменить связанный параметр vm.overcommit_ratio. Подробности см. в документации ядра файл https://www.kernel.org/doc/Documentation/vm/overcommit-accounting.

Другой подход, который можно использовать с изменением или без изменения параметра vm.overcommit_memory, заключается в установке процесс-специфического значения приоритета коррекции OOM для процесса постмастер в значение -1000, тем самым гарантируя, что он не будет выбран OOM-убийцей. Самый простой способ сделать это - выполнить следующую команду

echo -1000 > /proc/self/oom_score_adj

в скрипте запуска постмастера, непосредственно перед вызовом постмастера. Обратите внимание, что это действие должно быть выполнено от имени root, иначе оно не будет иметь эффекта; поэтому наиболее простым местом для этого является скрипт запуска, принадлежащий root. Если вы сделаете это, вы также должны установить эти переменные среды в скрипте запуска перед вызовом постмастера:

export PG_OOM_ADJUST_FILE=/proc/self/oom_score_adj
export PG_OOM_ADJUST_VALUE=0

Эти настройки приведут к тому, что дочерние процессы постмастер будут работать с нормальной настройкой OOM score, равной нулю, чтобы OOM -убийца все еще мог на них нацеливаться при необходимости. Вы можете использовать другое значение для PG_OOM_ADJUST_VALUE, если вы хотите, чтобы дочерние процессы работали с другой настройкой OOM score. (PG_OOM_ADJUST_VALUE также можно опустить, в этом случае оно устанавливается по умолчанию равным нулю). Если вы не установите PG_OOM_ADJUST_FILE, дочерние процессы будут работать с той же настройкой OOM score, что и постмастер, что не рекомендуется, поскольку весь смысл заключается в том, чтобы обеспечить постмастеру предпочтительную настройку.

18.4.5. Огромные страницы Linux

Использование огромных страниц снижает издержки при использовании больших непрерывных блоков памяти, как это делает Tantor SE, особенно при использовании больших значений shared_buffers. Чтобы использовать эту функцию в Tantor SE, вам понадобится ядро с параметрами CONFIG_HUGETLBFS=y и CONFIG_HUGETLB_PAGE=y. Вам также придется настроить операционную систему для предоставления достаточного количества огромных страниц нужного размера. Чтобы определить количество необходимых огромных страниц, используйте команду postgres, чтобы увидеть значение shared_memory_size_in_huge_pages. Обратите внимание, что сервер должен быть выключен, чтобы просмотреть этот параметр, вычисляемый во время выполнения. Это может выглядеть следующим образом:

$ postgres -D $PGDATA -C shared_memory_size_in_huge_pages
3170
$ grep ^Hugepagesize /proc/meminfo
Hugepagesize:       2048 kB
$ ls /sys/kernel/mm/hugepages
hugepages-1048576kB  hugepages-2048kB

В этом примере значение по умолчанию составляет 2 МБ, но вы также можете явно запросить либо 2 МБ, либо 1 ГБ с помощью huge_page_size, чтобы адаптировать количество страниц, рассчитанных по shared_memory_size_in_huge_pages. В этом примере нам необходимо как минимум 3170 огромных страниц, но более крупное значение будет соответствующим, если другие программы на машине также нуждаются в огромных страницах. Мы можем установить это с помощью:

# sysctl -w vm.nr_hugepages=3170

Не забудьте добавить эту настройку в /etc/sysctl.conf, чтобы она применялась после перезагрузки. Для нестандартных размеров больших страниц мы можем использовать вместо этого:

# echo 3170 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

Также возможно указать эти настройки при загрузке системы, используя параметры ядра, такие как hugepagesz=2M hugepages=3170.

Иногда ядро не может сразу выделить желаемое количество больших страниц из-за фрагментации, поэтому может потребоваться повторить команду или перезагрузить систему. (Сразу после перезагрузки большая часть памяти машины должна быть доступна для преобразования в большие страницы). Чтобы проверить ситуацию с выделением больших страниц определенного размера, используйте:

$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

Может потребоваться также предоставить пользователю операционной системы сервера баз данных разрешение на использование огромных страниц, установив vm.hugetlb_shm_group через sysctl и/или предоставив разрешение на блокировку памяти с помощью ulimit -l.

По умолчанию Tantor SE использует huge pages, если это возможно, с размером huge page, установленным по умолчанию в системе, и в случае неудачи переходит на обычные страницы. Чтобы обеспечить использование huge pages, вы можете установить huge_pages в on в файле postgresql.conf. Обратите внимание, что с этой настройкой Tantor SE не сможет запуститься, если недостаточно huge pages.

Для подробного описания функции Linux huge pages ознакомьтесь с https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt.