Реализация задачи задержки на базе REDIS

Redis
Реализация задачи задержки на базе REDIS

Фоновое введение

В последнее время возникла потребность в бизнесе, а предыстория такова: Есть племенная дичь, которая улучшается кормлением питомцев.После одного кормления питомцы едят 4 часа. Теперь появилось новое требование: вы можете использовать карты предметов, чтобы обогатить игровой процесс. Существует два типа карт предметов: одна — карта ускорения, а другая — карта автоматической подачи. Карта-ускоритель сократит время приема пищи на два часа, а карта автоматического кормления может помочь питомцу автоматически кормить один раз после того, как питомец съел текущий корм для собак.

Автоматическое питание в бизнес-требованиях является типичная задержка задачи. Задержка задач - это те, которые необходимо автоматически вызвать в указанной точке в будущем. Подобные сценарии включают в себя:

  • Push-сообщения пользователям за 2 часа до окончания мероприятия;
  • Отправить сообщение пользователю за 2 часа до истечения срока действия купона;
  • Во время мгновенного убийства заказ будет автоматически отменен, если оплата не будет произведена в течение 10 минут после оформления заказа;

Отраслевые решения

Таблица развертки

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

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

Самая большая проблема со сканированием таблиц заключается в том, что будет задержка, и оно не может быть запущено в указанное время.Для сценариев с высокой своевременностью это решение не может удовлетворить потребности.

Очередь задержанных сообщений

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

опрос временного интервала

Циклическая очередь используется для создания временных срезов, и связанный список поддерживается в каждой сетке циклической очереди. В каждый момент текущий указатель указывает на определенную сетку циклической очереди, и каждый раз, когда таймер истечет, текущий указатель указывает на следующую сетку нижней циклической очереди. Затем обработайте задачи в связанном списке, сохраненном в этой сетке. Если поддерживать ее только таким образом, если необходимо достичь гранулярности секунд и продолжительности времени до одного дня, то круговая очередь будет очень большой. Поэтому кто-то его усовершенствовал.При попадании задачи в очередь продолжительность времени делится на длину круговой очереди, которая записывается как количество кругов. Таким образом, каждый раз при обходе элемента количество кругов уменьшается на 1. Если уменьшить на 1, то будет выполняться задача изменения, иначе не будет выполняться.

Внутренняя реализация отложенного сообщения Kafka реализована путем опроса временных интервалов.

Для сценария с очень большим промежутком времени, если использовать этот метод, в связанном списке будет много элементов, и накладные расходы на обход связанного списка не маленькие, даже за один квант времени. Следовательно, есть еще одно усовершенствование, позволяющее разделить временные срезы на разные степени детализации. Например, колесо времени с точностью до часов, колесо времени с точностью до минут и колесо времени с точностью до секунд. Когда колесо времени в часах достигает состояния запуска, оно будет помещено в колесо времени минут, а колесо времени в минутах будет помещено в колесо времени секунд, когда оно достигнет состояния запуска. (Картинка взята из интернета, захвачена и удалена)

Временной срез этой схемы хранится в памяти, поэтому эффективность опроса очень высока, и временной срез также можно регулировать в соответствии с различной степенью детализации, поэтому он также очень гибкий. Однако это решение требует собственной реализации сохраняемости и высокой доступности, а также управления хранением.Если нет готового колеса, разработка займет много времени.

Реализация ZSET для Redis

Redis реализует задачи задержки через свою структуру данных ZSET. ZSET будет хранить оценку и значение, и значение может быть отсортировано в соответствии с оценкой, в то время как SET неупорядочен.

Реализация задачи задержки делится на следующие этапы:

(1) Возьмите время выполнения задачи как оценку, а данные задачи, которые должны быть выполнены, как значение, которое хранится в zset; (2) Используйте процесс для регулярного запроса элемента с наименьшей оценкой zset, что может быть достигнуто с помощью команды ZRANGEBYSCORE -inf +inf limit 0 1 withscores; (3) Если минимальная оценка меньше или равна текущей метке времени, задача вынимается и выполняется, в противном случае она будет запрошена после сна в течение определенного периода времени.

ZSET в redis реализован таблицей переходов, сложность O(logN), N — количество элементов, хранящихся в ZSET. Использование Redis для достижения сохраняемости может полагаться на сохраняемость самого Redis для обеспечения сохраняемости и кластера Redis для поддержки высокого параллелизма и высокой доступности. Поэтому стоимость разработки очень мала, и ее можно сделать в режиме реального времени.

Выполнение

Задержка метода подметания таблицы слишком велика, чтобы соответствовать требованиям реального времени.Очередь сообщений, используемая в настоящее время командой, не поддерживает очередь сообщений с задержкой.Метод колеса времени требует много времени для разработки, поэтому Наконец, для его реализации был выбран Redis.

Принцип Redis, реализующий отложенные задачи, был введен ранее, и для достижения более высокой параллелизма необходимо проектировать на основе этого принципа. Конкретная реализация будет подробно описана далее. Схема архитектурного проекта выглядит следующим образом:

инструкция:

  • Чтобы предотвратить сохранение ключа при увеличении объема данных, скорость запроса будет замедлена, во-первых, потому что его временная сложность равна O(logN), а во-вторых, если в один и тот же момент времени выполняется несколько задач, ключ не будет распространяться, вызвать перегрузку. Поэтому мы разрабатываем его как несколько ключей для хранения и направляем хэш на соответствующий ключ через uuid.Если количество задач увеличивается, мы можем быстро увеличить количество ключей Redis, чтобы противостоять увеличению;
  • Установить такое же количество процессов или потоков, как несколько ключей, каждый процесс имеет номер, соответствующий ключу, и постоянно опрашивать соответствующий ключ;
  • Процесс опроса ключа называется процессом события, процесс события только запрашивает задачу, но не обрабатывает дело, а записывает задачу в очередь сообщений. Кроме того, есть работа по извлечению сообщений из очереди сообщений и последующему выполнению дела. Таким образом, работу можно развернуть распределенным образом, и нужно только распределить событие, так что параллелизм может быть очень высоким, и даже если одновременно выполняется большое количество задач, задачи могут выполняться с небольшой задержкой;
  • Чтобы избежать процесса развертывания среднего развертывания событий после простоя машины, что приводит к не принимает сообщения, сохраненные данные Redis будут выполнены. Наш процесс события развертывания нескольких машин и использует первичные выборы Zookeeker, процесс был единственным лидером, чтобы взять сообщение из хоста Redis. После того, как лидерный хост снижается, Zookeeker автоматически выберет новый лидер;
  • В реальном деле, также на данных записи DB. Задача задачи состоит в том, чтобы изменить сгенерированную БД, затем снова Redis запись данных, то там обновление БД успешно, затем Redis пишет сбой сценариев, это первый раз, чтобы уменьшить вероятность сбоя по редис написать повторение, повторить попытку, если кажется, не может Будьте успешными, он отправляет сообщение в процесс демона асинхронной компенсации;

На основании задержки на задачу есть спрос на эту услугу, задача состоит в том, чтобы отложить время выполнения прибытия, если это не так, то время задержки задачи может быть изменена. Для достижения этого спроса мы в дополнение к каждому пользователю поддерживать ZSET, это ZSET хранится в пользовательской задержке задачи всех. Для простоты описания мы назвали это zset Zset-user. Если вам нужно изменить задачу задержки, если нет способа найти эту задачу от задания ZSET в целом задержки, но даже если мы сможем найти, может только перейти за ZSet, этот подход явно слишком медленный, тоже ресурс. Наш подход вывезен из ZSet-user в пользовательской задержке задачи, а затем измените счет, и, наконец, Re-zadd задержать задачу ZSET и ZSET-пользователя, ZADD перезапишет оригинальную задачу, а обновления начисления происходят Отказ Похоже, что это требование может быть достигнуто только через Redis.

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