Приходя к продукту, который разрабатывался не одно десятилетие, совсем не удивительно обнаружить в нем устаревшие технологии.
А что, если через полгода вам придется держать нагрузку в 10 раз большую, а стоимость падений увеличится в сотни раз? В этом случае вам нужен крутой Highload Engineer. Но из-за отсутствия служанка Поэтому мне доверили решить проблему.
В первой части статьи я расскажу, как мы перешли с Redis на Redis-кластер, а во второй части дам советы, как начать использовать кластер и на что обратить внимание при его использовании.
Выбор технологии Это так плохо? отдельный Redis (автономный Redis) в конфигурации из 1 ведущего и N ведомых устройств? Почему я называю это устаревшей технологией?
Нет, Redis не так уж плох.Однако есть и недостатки, которые нельзя игнорировать.
- Во-первых, Redis не поддерживает механизмы аварийного восстановления после главного сбоя.
Для решения этой проблемы мы использовали конфигурацию с автоматическим переносом ВИПов на новый мастер, изменением роли одного из слейвов и переключением остальных.
Этот механизм работал, но надежным решением его назвать нельзя.
Во-первых, возникали ложные срабатывания, во-вторых, он был одноразовым и после срабатывания требовались ручные действия по взводу пружины.
- Во-вторых, наличие всего одного мастера приводило к проблеме шардинга.
Пришлось создать несколько независимых кластеров «1 мастер и N слейвов», затем вручную распределить базы по этим машинам и надеяться, что завтра одна из баз не раздуется настолько, что ее придется выносить в отдельный инстанс.
- Самое дорогое и богатое решение — Redis-Enterprise. Это коробочное решение с полной технической поддержкой.
Несмотря на то, что с технической точки зрения он выглядит идеально, нас он не устроил по идеологическим соображениям.
- Redis-кластер.
«Из коробки» есть поддержка главного аварийного переключения и шардинга.
Интерфейс почти не отличается от обычной версии.
Выглядит многообещающе, о подводных камнях поговорим позже.
- Tarantool, Memcache, Aerospike и другие.
Все эти инструменты делают примерно одно и то же.
Но у каждого есть свои недостатки.
Мы решили не класть все яйца в одну корзину.
Memcache и Tarantool мы используем для других задач, и, забегая вперед, скажу, что с ними в нашей практике проблем было больше.
- Кэшировать перед запросами к удаленным сервисам типа 2ГИС | Голанг
GET SET MGET MSET «ВЫБРАТЬ БД»
- Кэш перед MySQL | PHP
ПОЛУЧИТЬ НАСТРОЙКУ MGET MSET СКАНИРОВАНИЕ «КЛЮЧ ПО ШАБЛОНУ» «ВЫБРАТЬ БД»
- Основное хранилище для сервиса работы с сессиями и координатами драйверов | Голанг
GET SET MGET MSET «ВЫБРАТЬ БД» «ДОБАВИТЬ КЛЮЧ ГЕО» «ПОЛУЧИТЬ КЛЮЧ ГЕО» СКАНИРОВАНИЕ
В чем же тогда трудность? Давайте рассмотрим каждый метод отдельно.
Метод | Описание | Особенности Redis-кластера | Решение |
---|---|---|---|
ПОЛУЧИТЬ НАБОР | Ключ записи/чтения | ||
МГЭТ МСЭТ | Запись/чтение нескольких ключей | Ключи будут на разных узлах.
Готовые библиотеки могут выполнять мультиоперации только в пределах одного узла.
|
Замените MGET конвейером операций N GET. |
ВЫБРАТЬ БД | Выберите базу, с которой мы будем работать | Не поддерживает несколько баз данных | Поместите все в одну базу данных.
Добавляйте префиксы к ключам |
СКАНИРОВАНИЕ | Перебрать все ключи в базе данных | Так как у нас одна база данных, перебирать все ключи в кластере слишком затратно.
|
Сохраняйте инвариант в пределах одного ключа и выполняйте HSCAN для этого ключа.
Или отказаться полностью |
ГЕО | Операции с геокеем | Геокей не сегментирован | |
КЛЮЧ ПО ШАБЛОНУ | Поиск ключа по шаблону | Поскольку у нас одна база данных, мы будем искать по всем ключам в кластере.
Слишком дорого |
Отказаться от инварианта или сохранить его, как в случае со SCAN. |
- Недостатки: мы теряем функциональность нескольких баз данных.
- Если мы хотим хранить логически несвязанные данные в одном кластере, нам придётся сделать костыли в виде префиксов.
- Теряем все «базовые» операции, такие как SCAN, DBSIZE, CLEAR DB и т.д.
- Мультиоперации стало гораздо сложнее реализовать, поскольку для этого может потребоваться доступ к нескольким узлам.
- Если мы хотим хранить логически несвязанные данные в одном кластере, нам придётся сделать костыли в виде префиксов.
- Преимущества:
- Отказоустойчивость в виде главного аварийного переключения.
- Шардинг на стороне Redis.
- Передавайте данные между узлами атомарно и без простоев.
- Добавляйте и перераспределяйте мощности и нагрузки без простоев.
- Отказоустойчивость в виде главного аварийного переключения.
Но если вы изначально выбираете между отдельной версией и кластерной версией, то вам следует выбрать кластерную, так как она ничем не хуже и к тому же избавит вас от части головной боли.
Подготовка к переезду Начнем с требований к переезду:
- Это должно быть бесшовно.
Полная остановка сервиса на 5 минут нас не устраивает.
- Это должно быть максимально безопасно и постепенно.
Я хочу иметь некоторый контроль над ситуацией.
Мы не хотим сбрасывать все сразу и молиться над кнопкой отката.
- Минимальная потеря данных при движении.
Мы понимаем, что атомарно перемещаться будет очень сложно, поэтому допускаем некоторую десинхронизацию между данными в обычном и кластерном Redis.
- Графики.
Мы используем Prometheus и Grafana для построения графиков загрузки процессора, использования памяти, количества клиентов, количества операций GET, SET, AUTH и т. д.
- Ээкспертиза.
Представьте, что завтра под вашей ответственностью окажется огромный кластер.
Если он сломается, никто, кроме вас, не сможет его починить.
Если он начнет тормозить, все побегут к вам.
Если вам нужно добавить ресурсы или перераспределить нагрузку, обращайтесь к вам.
Чтобы не поседеть в 25, желательно предусмотреть эти случаи и заранее проверить, как поведет себя техника при тех или иных действиях.
Поговорим об этом подробнее в разделе «экспертиза».
- Мониторинг и оповещения.
Когда кластер выходит из строя, вы хотите узнать об этом первым.
Здесь мы ограничились уведомлением о том, что все узлы возвращают одинаковую информацию о состоянии кластера (да, бывает по-разному).
Другие проблемы можно быстрее обнаружить по оповещениям клиентских служб Redis.
- Прежде всего необходимо подготовить библиотеку для работы с кластером.
За основу Go-версии мы взяли go-redis и немного изменили его под себя.
Мы реализовали Multi-методы через конвейеры, а также немного подправили правила повторения запросов.
С версией PHP было больше проблем, но в итоге мы остановились на php-redis. Недавно они представили поддержку кластеров, и, на наш взгляд, это выглядит хорошо.
- Далее вам необходимо развернуть сам кластер.
Делается это буквально двумя командами на основе файла конфигурации.
Подробнее о настройке мы поговорим ниже.
- Для постепенного перемещения мы используем сухой режим.
Поскольку у нас есть две версии библиотеки с одинаковым интерфейсом (одна для обычной версии, другая для кластера), то ничего не стоит создать обертку, которая будет работать с отдельной версией и параллельно дублировать все запросы к кластеру, сравнивайте ответы и записывайте расхождения в логи (в нашем случае в NewRelic).
Таким образом, даже если версия кластера выйдет из строя во время развертывания, это не повлияет на нашу продукцию.
- Развернув кластер в сухом режиме, мы можем спокойно смотреть на график расхождений ответов.
Если частота ошибок медленно, но верно приближается к какой-то небольшой константе, то все в порядке.
Почему до сих пор существуют расхождения? Потому что запись в отдельную версию происходит немного раньше, чем в кластер, и из-за микролага данные могут расходиться.
Остается только посмотреть логи несоответствий, и если они все объясняются неатомарностью записи, то можно двигаться дальше.
- Теперь вы можете переключить режим сушки в противоположном направлении.
Будем писать и читать из кластера, и дублировать в отдельную версию.
За что? В течение следующей недели хотелось бы понаблюдать за работой кластера.
Если вдруг выяснится, что есть проблемы при пиковой нагрузке, или мы что-то не учли, у нас всегда есть аварийный откат к старому коду и текущим данным благодаря сухому режиму.
- Остается только отключить сухой режим и разобрать отдельную версию.
Прежде всего, Redis — это хранилище ключей-значений.
В качестве ключей используются произвольные строки.
В качестве значений можно использовать числа, строки и целые структуры.
Последних великое множество, но для понимания общей структуры нам это не важно.
Следующий уровень абстракции после ключей — это слоты (SLOTS).
Каждый ключ принадлежит одному из 16 383 слотов.
В каждом слоте может быть любое количество ключей.
Таким образом, все ключи разделены на 16 383 непересекающихся набора.
Далее, в кластере должно быть N главных узлов.
Каждый узел можно рассматривать как отдельный экземпляр Redis, который знает все о других узлах в кластере.
Каждый главный узел содержит несколько слотов.
Каждый слот принадлежит только одному мастер-узлу.
Все слоты необходимо распределить между узлами.
Если некоторые слоты не выделены, то хранящиеся в них ключи будут недоступны.
Имеет смысл запускать каждый главный узел на отдельной логической или физической машине.
Также стоит помнить, что каждый узел работает только на одном ядре, и если вы хотите запустить несколько экземпляров Redis на одной логической машине, убедитесь, что они работают на разных ядрах (мы не пробовали это, но теоретически это должно работать).
.
По сути, главные узлы обеспечивают регулярное сегментирование, а большее количество главных узлов позволяет масштабировать запросы на запись и чтение.
После того, как все ключи распределены по слотам, а слоты разбросаны по мастер-нодам, к каждому мастер-узлу можно добавить произвольное количество подчиненных узлов.
Внутри каждого такого канала master-slave будет работать обычная репликация.
Подчиненные устройства необходимы для масштабирования запросов на чтение и для аварийного переключения в случае сбоя главного устройства.
Теперь поговорим об операциях, которые лучше было бы уметь делать.
Мы будем получать доступ к системе через Redis-CLI. Поскольку Redis не имеет единой точки входа, вы можете выполнять следующие операции на любом из узлов.
В каждом пункте отдельно обращаю внимание на возможность выполнения операции под нагрузкой.
- Первое и самое важное, что нам нужно — это работа узлов кластера.
Он возвращает состояние кластера, показывает список узлов, их роли, распределение слотов и т. д. Дополнительную информацию можно получить, используя информацию о кластере и слоты кластера.
- Было бы неплохо иметь возможность добавлять и удалять узлы.
Для этого существуют операции встречи кластера и операции забывания кластера.
Обратите внимание, что забывание кластера должно применяться к КАЖДОМу узлу, как к мастеру, так и к реплике.
А кластерную встречу нужно вызывать только на одном узле.
Эта разница может сбить с толку, поэтому лучше узнать о ней, прежде чем приступить к работе с кластером.
Добавление узла производится безопасно в бою и никак не влияет на работу кластера (что логично).
Если вы собираетесь удалить узел из кластера, следует убедиться, что на нем не осталось слотов (иначе вы рискуете потерять доступ ко всем ключам на этом узле).
Также не удаляйте мастер, у которого есть слейвы, иначе будет проведено ненужное голосование за нового мастера.
Если у узлов больше нет слотов, то это небольшая проблема, но зачем нам лишний выбор, если мы можем сначала удалить слейвы.
- Если вам нужно принудительно поменять местами позиции ведущего и ведомого, то подойдет команда переключения кластера.
Вызывая его в бою, нужно понимать, что во время операции мастер будет недоступен.
Обычно переключение происходит менее чем за секунду, но не является атомарным.
Вы можете ожидать, что в течение этого времени некоторые запросы к мастеру завершатся неудачно.
- Перед удалением узла из кластера на нем не должно оставаться слотов.
Перераспределить их лучше с помощью команды кластера reshard. Слоты будут перенесены от одного мастера к другому.
Вся операция может занять несколько минут, это зависит от объема передаваемых данных, но процесс передачи безопасен и никак не влияет на работу кластера.
Таким образом, все данные можно передавать с одного узла на другой непосредственно под нагрузкой, не беспокоясь о их доступности.
Однако есть и тонкости.
Во-первых, передача данных связана с определенной нагрузкой на узлы получателя и отправителя.
Если узел-получатель уже сильно загружен процессором, то не следует нагружать его получением новых данных.
Во-вторых, как только на отправляющем мастере не останется ни одного слота, все его слейвы сразу перейдут к мастеру, которому эти слоты были переданы.
И проблема в том, что все эти слейвы захотят синхронизировать данные сразу.
И вам повезет, если это будет частичная, а не полная синхронизация.
Учтите это и объедините операции переноса слотов и отключения/переноса слейвов.
Или надеяться, что у вас достаточный запас прочности.
- Что делать, если во время переноса вы обнаружили, что где-то потеряли свои слоты? Надеюсь, эта проблема вас не коснется, но если коснется, то есть операция по исправлению кластера.
Как минимум она раскидает слоты по узлам в случайном порядке.
Рекомендую проверить его работу, предварительно удалив из кластера узел с распределенными слотами.
Поскольку данные в нераспределенных слотах уже недоступны, волноваться о проблемах с доступностью этих слотов уже поздно.
В свою очередь операция не затронет распределенные слоты.
- Еще одна полезная операция — монитор.
Он позволяет видеть в режиме реального времени весь список запросов, идущих к узлу.
Более того, вы можете его просмотреть и узнать, есть ли необходимый трафик.
Короче говоря, он существует и, на мой взгляд, прекрасно работает. Однако не думайте, что если вы отключите шнур питания на машине с мастер-узлом, Redis тут же переключится и клиенты не заметят потери.
В моей практике переключение происходит за несколько секунд. В течение этого времени часть данных будет недоступна: обнаруживается недоступность мастера, узлы голосуют за нового, переключаются слейвы, данные синхронизируются.
Лучший способ убедиться в работоспособности схемы – провести локальные упражнения.
Поднимите кластер на своем ноутбуке, дайте ему минимальную нагрузку, смоделируйте сбой (например, заблокировав порты) и оцените скорость переключения.
На мой взгляд, только поиграв таким образом день-два, можно быть уверенным в работе техники.
Ну или надеяться, что софт, которым пользуется половина интернета, наверняка работает. Конфигурация Часто настройка — это первое, что вам нужно, чтобы начать работу с инструментом.
А когда все работает, конфиг даже трогать не хочется.
Требуется некоторое усилие, чтобы заставить себя вернуться к настройкам и внимательно их просмотреть.
На моей памяти было как минимум два серьезных сбоя из-за невнимания к конфигурации.
Обратите особое внимание на следующие моменты:
- тайм-аут 0 Время, по истечении которого неактивные соединения закрываются (в секундах).
0 - не закрывать
Не каждая наша библиотека умела правильно закрывать соединения.Отключив эту настройку, мы рискуем достичь лимита на количество клиентов.
С другой стороны, если такая проблема есть, то автоматическое прекращение потерянных соединений ее замаскирует, и мы можем ее не заметить.
Кроме того, не следует включать этот параметр при использовании постоянных подключений.
- Сохранить x y и добавить только да Сохранение снимка RDB. Ниже мы подробно обсудим вопросы RDB/AOF.
- остановка-запись-на-bgsave-ошибка нет и подчиненное-обслуживание-устаревшие-данные да Если этот параметр включен, то в случае повреждения моментального снимка RDB мастер перестанет принимать запросы на изменение.
Если соединение с мастером потеряно, слейв может продолжать отвечать на запросы (да).
Или перестанет отвечать (нет)
Нас не устраивает ситуация, когда Redis превращается в тыкву. - repl-ping-slave-период 5 По истечении этого периода времени мы начнем беспокоиться, что мастер сломался и пора проводить процедуру аварийного переключения.
В нашей практике это 5 секунд.
- repl-backlog-size 1024 МБ и epl-backlog-ttl 0 Именно столько данных мы можем хранить в буфере для вышедшей из строя реплики.
Если буфер закончится, вам придется полностью синхронизироваться.
Существует множество причин, по которым реплика может начать тормозить.
Если лагает, то скорее всего ваш мастер уже с трудом справляется, и полная синхронизация станет последней каплей.
- Максклиенты 10000 Максимальное количество разовых клиентов.
Redis отлично справляется с 10 тысячами подключений.
Просто убедитесь, что в системе достаточно разъемов.
- maxmemory-policy изменчивый-ttl Правило, по которому ключи удаляются при достижении лимита доступной памяти.
Redis можно похвалить за способность нормально работать при достижении предела памяти.
Точнее, три механизма:
- RDB-снимок — полный снимок всех данных.
Устанавливается с помощью конфигурации SAVE X Y и гласит: «Сохранять полный снимок всех данных каждые X секунд, если изменилось хотя бы Y ключей».
- Файл только для добавления — список операций в порядке их выполнения.
Добавляет новые входящие операции в файл каждые X секунд или каждые Y операций.
- RDB и AOF представляют собой комбинацию двух предыдущих.
Во-первых, для сохранения снимка RDB требуется вызов FORK. Если данных много, это может привести к зависанию всего Redis на период от нескольких миллисекунд до секунды.
Кроме того, системе необходимо выделить память для такого снимка, что приводит к необходимости держать двойной запас оперативной памяти на логической машине: если под Redis выделено 8 ГБ, то на виртуальной машине должно быть доступно 16 ГБ с это.
Во-вторых, есть проблемы с частичной синхронизацией.
В режиме AOF при повторном подключении ведомого устройства вместо частичной синхронизации может быть выполнена полная синхронизация.
Почему это происходит, я не мог понять.
Но стоит об этом помнить.
Эти два пункта уже заставляют задуматься о том, действительно ли нам нужны эти данные на диске, если все уже продублировано слейвами.
Данные могут быть потеряны только в случае выхода из строя всех ведомых устройств, а это проблема уровня «пожар в DC».
В качестве компромисса можно предложить сохранять данные только на слейвах, но в этом случае нужно сделать так, чтобы эти слейвы никогда не стали мастерами при аварийном восстановлении (для этого в их конфиге есть настройка приоритета слейвов).
Что касается себя, то в каждом конкретном случае мы задумываемся о том, нужно ли сохранять данные на диск, и чаще всего ответ – «нет».
Заключение В заключение надеюсь, что мне удалось дать общее представление о том, как работает редиск-кластер для тех, кто о нем вообще не слышал, а также обратил внимание на некоторые неочевидные моменты для тех, кто им пользовался.
надолго.
Спасибо за ваше время и, как всегда, комментарии по теме приветствуются.
Теги: #it-инфраструктура #redis #Высокая производительность #highload #citymobil #redis-cluster
-
Создание Блога О Зарабатывании Денег
19 Oct, 24 -
Синий Экран Смерти!
19 Oct, 24 -
Ищу Фотохостинг
19 Oct, 24 -
Вязаные Новости
19 Oct, 24 -
Jsfind. Получение Данных Из Массива Объектов
19 Oct, 24