Мы в Jooble активно используем Redis как кеш и быструю базу данных. У нас два master-slave-кластера, которые выполняют в среднем 12 000 операций в секунду. А дальше — история о том, как наш кластер стал падать по «out of memory», и о сложном поиске причины.
На тот момент в Redis кешировались в основном такие данные:
В какой-то момент мы заметили, что наш кластер становится нестабильным. Redis часто падал по «out of memory».
Мы рассчитали, что на каждом из серверов должно быть занято около 20 Гб RAM. Вот только info memory
показывала совсем другое. В пиковые моменты Redis занимал 80 Гб оперативной памяти:
used_memory:59681435584 used_memory_human:55.58G used_memory_rss:65407717376 used_memory_rss_human:60.92G used_memory_peak:85893162568 used_memory_peak_human:79.99G total_system_memory:134991085568 total_system_memory_human:125.72G used_memory_lua:71680 used_memory_lua_human:70.00K maxmemory:0 maxmemory_human:0B maxmemory_policy:allkeys-lru mem_fragmentation_ratio:1.10 mem_allocator:jemalloc-3.6.0
Вначале мы решили разобраться, из-за чего падал кластер. Redis занимал максимум 80 Гб RAM, но на сервере доступно 126 Гб. В чем тогда проблема?
Ответ нашли довольно быстро – это RDB Snapshots. В момент создания снепшота Redis делает fork()
текущего процесса, а это может потребовать выделения дочернему процессу такого же количества памяти, как и у родителя.
Пока проблема с большим потреблением ОЗУ не была решена — мы просто выключили сохранение RDB-снепшотов.
Далее мы выдвинули первую гипотезу увеличения потребления ОЗУ: в Redis попадает много больших по размеру записей. Решили проанализировать данные, которые хранили в Redis, найти самые тяжеловесные ключи, сгруппировать и определить виновника.
К счастью, свою утилиту для анализа писать не пришлось — мы воспользовались Redis Memory Analyzer и командой DEBUG OBJECT
для этих целей.
Результат получился неутешительный.Больше всего памяти занимали кеши результатов поиска, причем они занимали столько места на 1 элемент, сколько мы и ожидали. Наша первая гипотеза провалилась.
Используя Redis Memory Analyzer, мы наткнулись на странное явление. Каждый раз когда запускали анализ, уменьшалось потребление памяти.
Из документации мы знали, что Redis удаляет просроченные объекты двумя способами:
Все указывало на то, что Redis Memory Analyzer активирует первый способ. Мы провели простой тест: просканировали все ключи в Redis и снизили объем потребляемой ОЗУ до ожидаемого размера (20 Гб).
Тогда выдвинули вторую гипотезу: что-то повлияло на активный механизм очистки данных, и Redis просто не успевает удалять весь мусор.
Документация к EXPIRE описывает активный механизм очистки ключей:
Redis 10 раз в секунду проделывает следующее: 1. Тестирует 20 случайных ключей из всего набора ключей в БД с проставленным TTL. 2. Удаляет все ключи с просроченным сроком жизни. 3. Если более 25% ключей удалены, возвращаемся к пункту 1.
Значит, большое количество долгоживущих ключей могло влиять на качество очистки ключей в целом.
Мы просмотрели ключи с самым большим сроком жизни и обнаружили, что не так давно начали кешировать легковесную запись для каждого пользователя на 14 дней. В количественном отношении это была самая большая группа ключей в нашем кластере.
В этот раз мы попали в точку:
В результате для решения проблемы с очисткой ключей мы сделали следующее:
Теперь один экземпляр Redis занимает в 2-3 раза меньше места, как мы и ожидали изначально:
used_memory:23734192088 used_memory_human:22.10G used_memory_rss:27195826176 used_memory_rss_human:25.33G used_memory_peak:45282896632 used_memory_peak_human:42.17G total_system_memory:134991085568 total_system_memory_human:125.72G used_memory_lua:59392 used_memory_lua_human:58.00K maxmemory:0 maxmemory_human:0B maxmemory_policy:allkeys-lru mem_fragmentation_ratio:1.15 mem_allocator:jemalloc-3.6.0
В благословенные офисные времена, когда не было большой войны и коронавируса, люди гораздо больше общались…
Вот две истории из собственного опыта, с тех пор, когда только начинал делать свою карьеру…
«Ты же программист». За свою жизнь я много раз слышал эту фразу. От всех. Кто…
Отличные новости! Если вы пропустили, GitHub Copilot — это уже не отдельный продукт, а набор…
Несколько месяцев назад мы с командой Promodo (агентство инвестировало в продукт более $100 000) запустили…
Пару дней назад прочитал сообщение о том, что хорошие курсы могут стать альтернативой классическому образованию.…