Недавно наша группа инженеров по надежности сайта начала получать предупреждения о нехватке памяти в некоторых экземплярах Redis с очень маленькими рабочими наборами. было относительно небольшое количество ключей, но сравнительно большой объем памяти, выделенный процессами redis-сервера. Несмотря на то, что изначально это выглядело как утечка, проблема на самом деле была проблемой между альтернативным распределителем памяти и прозрачными огромными страницами.
Почему требуется отключение THP?
Эта кроличья нора началась, когда процесс redis-server
, который недавно был перемещен в LD_PRELOAD jemalloc.so
, начал использовать значительные объемы памяти. Первоначальные признаки указывали на то, что использование альтернативного распределителя может быть частью проблемы, поэтому мы начали копать именно с этого.
Оказывается, jemalloc(3)
широко использует madvise(2)
, чтобы уведомить операционную систему о том, что это делается с диапазоном памяти, который ранее был malloc
обработан. Поскольку машина использовала прозрачные огромные страницы, размер страницы составлял 2 МБ. Таким образом, большая часть памяти, которая была помечена madvise(..., MADV_DONTNEED)
, находилась в пределах диапазонов, существенно меньших 2 МБ. Это означало, что операционная система никогда не могла вытеснить страницы с диапазонами, помеченными как MADV_DONTNEED
, потому что вся страница должна была быть ненужной, чтобы ее можно было использовать повторно.
Итак, несмотря на то, что изначально это выглядело как утечка, сама операционная система не смогла освободить память из-за madvise(2)
и прозрачных огромных страниц. Это привело к постоянному давлению памяти на машине и redis-server
в конечном итоге к уничтожению OOM.
Прозрачные огромные страницы должны быть отключены в вашем ядре. Используйте echo never > /sys/kernel/mm/transparent_hugepage/enabled
, чтобы отключить их, и перезапустите процесс Redis.
Задержка, вызванная прозрачными огромными страницами
К сожалению, когда в ядре Linux включены прозрачные огромные страницы, Redis подвергается большому штрафу за задержку после использования вызова fork для сохранения на диске. Огромные страницы являются причиной следующей проблемы:
- Вызывается форк, создаются два процесса с общими огромными страницами.
- В загруженном экземпляре несколько запусков циклов событий заставят команды нацеливаться на несколько тысяч страниц, вызывая копирование при записи почти всей памяти процесса.
- Это приведет к большой задержке и большому использованию памяти.
jemalloc
имеет проблемы с THP иmadvise MADV_DONTNEED
, как сообщает LuFFy, но также возможен теоретический ложный обмен-подобная проблема на машинах NUMA: lkml.org/lkml/2016/2/25/ 623 старая проблема, из-за которой может быть ложное совместное использование страниц NUMA в пределах границ THP. Рассмотрим, например, если потоки вычисляют блоки размером 4 КБ, а затем они переносятся как THP, включая несвязанные потоки. - person osgx   schedule 03.03.2017