Чжан Вэйфань (техническая группа NetEase Yanxuan)
RedisTemplate — один из наиболее часто используемых классов инструментов доступа к данным Redis, инкапсулированный Spring, с мощными функциями и лаконичным использованием. Но под, казалось бы, простым API RedisTemplate также скрываются подводные течения, и за этим скрывается много загадок. Эта статья начинается с проблемы производительности в сети, шаг за шагом исследует RedisTemplate и выкапывает яму, в которой RedisTemplate выполняет команды psetex.
1. Предпосылки
В предыдущем процессе стресс-тестирования RT страницы сведений о бизнесе оставалось высоким, и был обнаружен аномальный сигнал тревоги кластера Redis yx_malltech_user.Поначалу, когда бизнес не включал чтение разгрузки, подчиненный узел кластера Redis имел большое количество подключений, которые занимали много ресурсов ЦП., и приводили к ненормальному поведению, такому как отключение ведущего и ведомого устройств Redis.
После анализа dba видно, что из платформы мониторинга базы данных в реальном времени генерируется большое количество кластерных команд, и этот запрос существовал всегда, но трафик измерения давления слишком велик, что приводит к усилению проблемы. запрос одной команды кластера составляет более 30 миллисекунд. Все они попали в случайный узел NODE, в результате чего процессор этого узла взлетел.
Затем администратор базы данных запускает соответствующую обработку, включающую, но не ограничивающуюся изоляцией аномальных узлов на независимые машины, оптимизацией параметров конфигурации и т. д. Принципиально проблема не решается. Можно определить, что это не проблема на стороне сервера Redis, а проблема на стороне бизнес-кода.Вам необходимо проверить метод использования из бизнес-использования, чтобы увидеть, как запускается большое количество команд кластера.
6.9 Проблема все еще существует, когда детали единого поставщика давления. Начинаем наше расследование.
2. Служебная информация
- Задействованные сервисы: yanxuan-app
- Используемые сценарии: бизнес-детали
- весенняя версия: 4.0.8
- версия spring-data-redis: 1.8.4.RELEASE
- версия джедая: 2.9.0
3. Процесс анализа
1. Мониторинговое наблюдение
Так как аномальных команд кластера слишком много, давайте посмотрим на данные мониторинга. Во второй половине дня 6.9, единственная пресса для деловых подробностей
Видно, что команды cluster действительно слишком много и выполняется долго. Это влияет на другие обычные операции получения и установки.
Мы внимательно наблюдали и обнаружили, что аномальный запрос — это не только кластер, но и psetex. Обычно мы работаем с кешем и не используем команду psetex напрямую. Наблюдайте за двумя по отдельности.
На следующих двух рисунках показаны диаграммы трендов команды psetex и команды cluster, которые признаны согласованными. По сути, можно определить, что psetex и кластер сильно связаны.
pset выглядит следующим образомкластер выглядит следующим образом
И кластер только бьет10.130.68.239:16379на этой машине.
2. Анализ кода
Судя по приведенному выше наблюдению, команда psetex и команда cluster в основном находятся в одинаковом соотношении, а объем запросов команды psetex довольно велик. В нашей разработке мы на самом деле не используем pset, мы все redisTemplate.opsForValue().set()
Это странно, так что давайте перейдем к коду.
Это инкапсулирует логику кэширования.Нижний уровень — это метод redisTemplate.opsForValue().set().Затем мы переходим к исходному коду redisTemplate, чтобы посмотреть, что он делает тайно.В этом коде мы понимаем, откуда берется psetex. Если единицей времени, которую вы используете для тайм-аута, является мс, будет использоваться psetex, а в противном случае будет использоваться команда setex. Такое ощущение, что мы делаем шаг вперед. Но почему команды psetex и cluster находятся в одинаковой пропорции? Читать дальше.Здесь узел, в котором находится соответствующий слот, будет вычисляться по ключу. Давайте перейдем к методу топологии и посмотрим.Глядя на этот код, истина видна. Получается, что кеш для получения информации о топологии кластера есть, а время истечения — 100мс (здесь Spring фактически записал время истечения кеша на смерть). Кэш становится недействительным, а затем узлы циклически выбираются из узлов кластера для отправки команды узлов кластера для обновления информации о топологии. Это доказывает корреляцию между командой cluster и командой psetex. Время истечения кэша составляет 100 мс, что неизбежно приведет к частым командам узлов кластера. После подтверждения с помощью dba Dafeng в процессе измерения напряжения действительно присутствует большое количество команд кластера, а именно команда узлов кластера. подтвердил предположение.
4. Решение и проверка
1. Решение
Решение простое: измените весь код в кеше, который использует миллисекунды в качестве времени истечения срока действия, чтобы установить кеш в секундах.
Пока он изменен на второй уровень, то есть с использованием setex, setex не будет запускать команду кластера. Избегайте использования команды psetex, которая вызывает команду частых узлов кластера.
2. Проверка
После завершения модификации наблюдайте за мониторингом. Установлено, что в онлайн-процессе наблюдается четкая тенденция к снижению.В пиковый период производительность упала до очень низкого уровня.Окончательная проверка стресс-теста:Судя по результатам испытаний под давлением, производительность также очень хорошая. Задача решена.
В стресс-тесте основного канала MRT общего согласования также снизился с предыдущих 100 мс+ до 66 мс.
5. Резюме и размышления
1. Резюме
Этот вопрос более интересен, виновником на самом деле является единица времени. Тот факт, что используются 1000 мс и 1 с, теоретически должен быть одинаковым, и большинству людей все равно. Однако нижний слой пружины в процессе эксплуатации оставил такую ямку, что привело к возникновению проблем при опрессовке под высоким давлением. Небольшая разница имеет огромное значение.
И нам не нужно быть точным до уровня миллисекунд для времени истечения кэша, поэтому мы можем напрямую изменить его на второй уровень.
2. Думай
Между PSETEX и SETEX нет существенной разницы, кроме точности времени экспирации.
Таким образом, spring обеспечивает использование setex и psetex в соответствии с единицей времени, а интерфейс не показывает отражение. Я лично считаю, что это неразумное место для весеннего дизайна интерфейса. Хотя это сделано для удобства разработчиков, чтобы скрыть детали, основная логика не совсем такая же (не только отправка разных команд). Вместо этого есть командная логика, такая как получение узлов кластера, которые представляют собой два набора логики. Это также тревожный звонок для интерфейсов и методов, представленных в нашей разработке и дизайне. Интерфейс и методы должны обеспечивать простоту понимания пользователя и отсутствие двусмысленности. В противном случае придется разделить несколько интерфейсов, чтобы пользователи могли выбирать, не оставляя для них дыр.
Последующие меры по оптимизации:
- Отсортируйте лучшие практики для версии, а затем стандартизируйте используемую версию фреймворка. Например, версия spring-data-redis 1.x единообразно использует 1.8.4, а затем имеются соответствующие рекомендации; версия 2.x единообразно использует 2.2.4, и имеются соответствующие рекомендации. Таким образом, вы можете не наступать на повторяющиеся ямы, и вы можете стоять на плечах гигантов и видеть дальше.
- Установите стандартный механизм CodeReview. Благодаря обзору кода нескольких людей и опыту разных людей можно обнаружить некоторые скрытые подводные камни. Избегайте проблем после выхода в эфир.
6. Дополнительная история
1. Почему команда кластера всегда попадает на определенный узел?
Как мы упоминали ранее, есть еще одна проблема: команда cluster всегда попадает на определенный узел, что приводит к резкому увеличению загрузки процессора этого узла.
Причина все же в следующем коде Spring-data-redis:
Цикл for проходит по всем узлам, отправляет команду узлов из первого и возвращает результат напрямую, если он возвращается. И наша информация об узле вообще неизменна. Поэтому порядок entrySet не изменится, и команда Cluster Nodes всегда будет отправляться на один и тот же узел.
Согласно информации в сети, эта ошибка была официально исправлена.Поскольку ah.spring.IO/browse/data…
2. Почему команда Cluster nodes работает так медленно?
Ну, это прямая выдержка из интернет-информации.
Ответ на рисунке ниже, константа CLUSTER_SLOTS равна 16384, поэтому каждый раз Redis выполняет множество циклов, чтобы собрать информацию о слоте каждого узла. ЦП должен зациклиться не менее 16384 раз N раз, где N — количество мастеров кластера Redis.Поэтому по мере расширения масштаба кластера redis и увеличения количества клиентских узлов проблема загрузки ЦП командой NODES будет становиться все более и более серьезной.
Проблема с производительностью системной команды redis NODES была передана официальному лицу redis в 2018 году:GitHub.com/Антиэнтузиазм/Горячие…
3. Каковы сценарии использования команды PSETEX?
PSETEX works exactly like SETEX with the sole difference that the expire time is specified in milliseconds instead of seconds.
Между PSETEX и SETEX нет существенной разницы, кроме точности времени экспирации. Так что я лично понимаю, что psetex следует использовать в сценариях, требующих высокой точности времени истечения.
За позиционирование и устранение этой проблемы я хотел бы поблагодарить dba за большую оптимизацию на стороне сервера и за предоставление очень хорошего направления анализа, чтобы мы могли быстро и четко проверить из бизнес-кода. В процессе расследования бизнес-кода Вэнь Юань неразлучен. Большое спасибо! ! !
Команда NetEase Technology Lovers продолжает набор соратников! Netease проходит строгий отбор из-за любви. Мы с нетерпением ждем ваших единомышленников, которые присоединятся к нам. Ваше резюме Java-разработчика можно отправить на почтовый ящик:lizhuo01@corp.netease.com