Открытый исходный код | Как разработать высокопроизводительный прокси кластера Redis?

Redis
Открытый исходный код | Как разработать высокопроизводительный прокси кластера Redis?

задний план

Введение в кластер Redis

Кластер Redis — это официальное кластерное решение, предоставляемое Redis. В дизайне используется децентрализованная архитектура. Узлы обмениваются статусами друг друга через протокол сплетен. Кластер Redis использует сегментирование данных для построения кластера. Кластер имеет 16384 встроенных хэша. слотов.Каждый ключ принадлежит одному из этих 16384 хеш-слотов.Хэш-значение вычисляется по алгоритму crc16, а остаток можно получить для получения хеш-слота, к которому принадлежит каждый ключ.кластер redis поддерживает динамическое добавление новых узлов, динамическое миграция слотов, автоматический переход на другой ресурс и т. д.
Архитектура кластера Redis требует, чтобы клиент напрямую устанавливал соединение с каждым узлом в кластере Redis, а при возникновении таких событий, как добавление новых узлов, отключение узла во время отказа, миграция слотов и т. д., клиент должен иметь возможность для обновления локального через протокол кластера Redis Таблица сопоставления слотов и может обрабатывать семантику ASK/MOVE, поэтому мы обычно называем клиента, который реализует протокол кластера Redis, умным клиентом Redis.
Cluster Redis может построить кластер с более чем 100 главными узлами. ), один кластер может не соответствовать емкости около 1т.

вопрос

Кластер Redis имеет много преимуществ (например, возможность создавать кластеры большой емкости, хорошую производительность и гибкое расширение и сжатие), но когда в некоторых проектах ожидается переход с кластера Redis на кластер Redis, клиент сталкивается с большим объемом работ по обновлению. , и в то же время с What приходит потребность в большой работе по тестированию и введении новых рисков, что, несомненно, огромно для некоторых стабильных онлайн-проектов.

нужно

Для более удобного переноса бизнеса на кластер Redis больше всего ожидается, что API клиентского SDK будет полностью совместим с redis/redis-cluster.RedisTemplate, предоставленный Spring, является хорошей реализацией, но для проектов, которые не используйте SpringRedisTemplate, многие клиенты реализуют Redis и API-интерфейсы доступа к кластеру redis несовместимы (например, популярный Jedis в Java), что незаметно увеличивает рабочую нагрузку и сложность работы по миграции В настоящее время хорошим выбором является прокси-сервер кластера redis. , С прокси-сервером вы можете работать с кластером Redis как с одним экземпляром Redis, клиентской программе не нужно вносить какие-либо изменения.
Конечно, добавление прокси-слоя неизбежно приведет к определенной степени снижения производительности, но, как сервис без сохранения состояния, прокси-сервер теоретически может расширяться по горизонтали, а поскольку наличие прокси-слоя уменьшает количество подключений к серверной части сервер redis, в некоторых случаях В крайних случаях это может даже улучшить общую пропускную способность кластера Redis. Кроме того, на основе прокси мы можем делать много дополнительных вещей:
  • Например, логика сегментирования может быть выполнена на уровне прокси, так что, когда кластер Redis одного кластера не соответствует требованиям (память/QPS), уровень прокси можно использовать для прозрачного доступа к нескольким кластерам Redis одновременно. .
  • В качестве другого примера, вы можете выполнить логику двойной записи на прокси-уровне, чтобы при миграции или разделении кэш-типа Redis вам не нужно было использовать такие инструменты, как redis-migrate-tool для полной миграции, а нужно только дублировать -запись по требованию Завершите миграцию.
  • Кроме того, поскольку прокси-сервер реализует протокол Redis, другие носители данных могут использоваться для реализации команд, связанных с Redis, на уровне прокси, чтобы его можно было имитировать как внешнюю службу Redis. Типичным сценарием является разделение горячего и холодного хранения.

Функция

В связи с вышеуказанными причинами и требованиями мы разработали промежуточное программное обеспечение, такое как camellia-redis-proxy, на основе netty, которое поддерживает следующие функции:
  • Поддержка установки пароля
  • Поддержка прокси-сервера для общего Redis, а также поддержка прокси-сервера для кластера Redis.
  • Поддерживает настройку пользовательской логики сегментирования (может проксировать на несколько кластеров redis/redis-cluster)
  • Поддерживает настройку пользовательской логики двойной записи (сервер распознает атрибут чтения-записи команды, и после настройки двойной записи команда записи будет отправлена ​​на несколько бэкэндов одновременно)
  • Поддержка внешних подключаемых модулей, чтобы можно было повторно использовать модуль разбора протокола (в настоящее время предоставляется подключаемый модуль camellia-redis-proxy-hbase, реализующий холодное и горячее разделение хранения команды zset)
  • Поддержка онлайн-изменения конфигурации (необходимо ввести камелию-приборную панель)
  • Поддержка нескольких бизнес-логик для совместного использования набора прокси-кластеров, таких как: Бизнес A настраивает правило переадресации 1, Бизнес B настраивает правило переадресации 2 (вам необходимо установить бизнес-тип с помощью команды клиента при установке соединения Redis).
  • Spring-boot-starter предоставляется извне, а прокси-кластер можно быстро построить с помощью 3 строк кода.

Как улучшить производительность

Клиент инициирует запрос к camellia-redis-proxy и в процессе получения обратного пакета запроса проходит по очереди следующие процессы
  • Анализ восходящего протокола (чтение и запись ввода-вывода)
  • Сопоставление правил переадресации протокола (вычисления в памяти)
  • Переадресация запроса (чтение и запись ввода-вывода)
  • Backend redis обратная упаковка и распаковка (чтение и запись ввода-вывода)
  • Back-end Redis возвращает пакеты клиенту (чтение и запись ввода-вывода)
Видно, что в качестве прокси много работы в сетевых операциях ввода-вывода.Для повышения производительности прокси проделана следующая работа:

Многопоточность

Мы знаем, что сам Redis является однопоточной резьбой, но в качестве прокси, Multi-Threading может использоваться для полного использования производительности многоядерных процессоров, но слишком много потоков вызывают ненужное переключение контекста, что приведет к деградации производительности. Camellia-Redis-Proxy использует многопоточную модель реактора Netty, чтобы обеспечить производительность обработки сервера. По умолчанию количество рабочих потоков ядер CPU будет включено. Кроме того, если сервер поддерживает мульти-очередь сетевой карты, что позволяет избежать дисбаланса нагрузки между различными процессорами; если нет, свяжите бизнес-процесс к другим ядрам, отличным от CPU0, так что CPU0 может сосредоточиться на прерываниях обработки сетевой карты Пострадавших от слишком многих бизнес-процессов.

Асинхронный неблокирующий

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

сборочная линия

Мы знаем, что протокол Redis поддерживает конвейеры, а использование конвейеров может эффективно снизить нагрузку на сеть. Camellia-redis-proxy также в полной мере использует такие функции, в основном включая два аспекта:
  • При анализе вышестоящих протоколов старайтесь анализировать несколько команд одновременно, чтобы правила можно было пересылать пакетами.
  • При пересылке на внутренний узел Redis отправляйте как можно больше пакетов.В дополнение к агрегированию команд из одного и того же клиентского соединения вы также можете подключать команды от разных клиентов, но когда цель пересылки Redis одинакова, агрегация команд также может быть выполнено.
Конечно, все эти пакетные и агрегационные операции требуют однозначного соответствия между запросами и ответами.

Пакетирование TCP и обработка больших пакетов

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

Обработка исключений и объединение журналов исключений

Если различные исключения не обрабатываются эффективно, производительность сервера будет быстро снижаться при возникновении исключений. Представьте себе сценарий, в котором мы настраиваем 90% трафика для пересылки в кластер A и 10% трафика для пересылки в кластер B. Если кластер B выйдет из строя, мы ожидаем, что 90% запросов от клиентов будут выполняться нормально, и 10% трафика должны выполняться нормально.Запросы терпят неудачу, но на самом деле гораздо более 10% запросов не выполняются по разным причинам:
  • Внезапный сбой на уровне серверной операционной системы. Уровень прокси может не узнать об этом сразу (пакеты TCP fin не получены), что приводит к большому количеству запросов, ожидающих ответных пакетов.Хотя уровень прокси не блокируется, клиент показывает, что время запроса истекло.
  • Когда прокси-сервер пытается перенаправить запрос в кластер B, запрос на переподключение для кластера B может замедлить весь процесс.
  • Большое количество журналов исключений, вызванных простоем, может привести к снижению производительности сервера (это легко игнорировать)
  • Из запросов, отправленных конвейером, 99 запросов направляются в кластер A и 1 запрос направляется в кластер B. Однако из-за недоступности кластера B запросы, направленные в кластер B, задерживаются в возвращаемых пакетах или ненормальном ответе. слишком медленно Конечная производительность клиента составляет 100 запросов, все неудачные
Camellia-redis-proxy использует следующие стратегии при решении вышеуказанных проблем:
  • Установите стратегию быстрого отказа для аварийных серверных узлов, чтобы избежать замедления работы всей службы.
  • Журналы исключений управляются единообразно, а выходные данные объединяются, чтобы уменьшить влияние журналов исключений на производительность сервера без потери информации об исключениях.
  • Увеличьте время обнаружения серверного Redis, чтобы избежать долгосрочных отклонений в бизнесе, вызванных сбоем простоя и невозможностью немедленно его обнаружить.

Архитектура развертывания

Поскольку служба без сохранения состояния, прокси-сервер можно масштабировать по горизонтали. Для обеспечения высокой доступности службы необходимо развернуть как минимум два или более прокси-узла. может использовать прокси Служба прокси LVS устанавливается перед уровнем.В настоящее время схема архитектуры развертывания выглядит следующим образом:
Конечно, есть и другое решение: прокси-узел может быть зарегистрирован в центре регистрации, например zk/Eureka/Consul, клиент может тянуть и мониторить список прокси, а затем обращаться к каждому прокси, как к одноузловому редису. Взяв в качестве примера Jedis, вам нужно всего лишь заменить JedisPool на RedisProxyJedisPool, который инкапсулирует логику обнаружения регистрации, и вы можете использовать прокси, как обычный Redis, В настоящее время схема архитектуры развертывания выглядит следующим образом:

Сценарии применения

  • Нужно мигрировать с redis на redis-cluster, но клиентский код неудобно модифицировать
  • Клиент напрямую подключается к redis-кластеру, что приводит к слишком большому количеству подключений к серверу кластера, что приводит к снижению производительности сервера.
  • Если емкость/количество запросов в секунду одного кластера redis/redis-cluster не соответствует бизнес-требованиям, используйте функцию сегментирования Camellia-redis-proxy.
  • Разделение и миграция кластера класса кэша redis/redis-cluster с использованием функции двойной записи Camellia-redis-proxy
  • Используйте функцию двойной записи для аварийного восстановления redis/redis-cluster.
  • Некоторые бизнес-сценарии, в которых шардинг и двойная запись смешиваются
  • Основываясь на функции плагина Camellia-Redis-Proxy, разрабатывайте собственные плагины.

Эпилог

Кластер Redis является официально рекомендуемым кластерным решением. Все больше и больше проектов переходят или переходят на кластер Redis. Camellia-redis-proxy родился в этом контексте; особенно если вы являетесь разработчиком Java, Camellia Он также предоставляет такие решения, как CamelliaRedisTemplate CamelliaRedisTemplate имеет тот же API, что и обычные Jedis, предоставляет функции, не поддерживаемые родным JedisCluster, такие как mget/mset/pipeline, и обеспечивает сегментирование/двойную запись, которая согласуется с функциями Camellia-redis-proxy.
Чтобы отблагодарить сообщество, исходный код камелии официально открыт. Если вы хотите узнать больше о проекте камелии, перейдите на github по следующему адресу:GitHub.com/netease-IM/…
Если у вас есть хорошие идеи или предложения, или у вас есть какие-либо вопросы, пожалуйста, отправьте вопрос, чтобы связаться с нами!

Об авторе
Цао Цзяцзюнь. Старший инженер-разработчик серверов Netease Smart Enterprise. После окончания Китайской академии наук он присоединился к NetEase и отвечал за разработку серверов обмена мгновенными сообщениями в NetEase Yunxin.