Как Redis устанавливает отдельные сроки действия для элементов List/Set/Hash?
Как Redis устанавливает отдельные сроки действия для элементов List/Set/Hash?

Привет всем, я Сяо ❤, 985-ненаучный программист, который много лет скитается по миру. Я работал в сфере backend-разработки государственных предприятий, интернет-гигантов и стартап-компаний.

1. Введение

1.1 Очередь потребления

В этот день, когда маленький ❤ покупал билеты на поезд, он обнаружил, что при наличии неоплаченного заказа он уже не сможет приобрести билеты. Если заказы, подлежащие оплате, помещены в очередь, длина очереди может быть только 1.

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

Диаграмма статуса бизнеса выглядит следующим образом:

Кроме того, необходимо обеспечить контролируемую длину очереди. Например, мы разрешаем пользователям иметь только 3 неоплаченных заказа.

1.2 Реализация Redis

Redis, как высокопроизводительная база данных кэша и хранения данных, всегда была мощным помощником для серверных разработчиков.

Если используется Redis В качестве очереди потребления мы можем использовать следующие структуры данных: List, Hash. и Набор. В приведенном выше бизнес-сценарии, поскольку нам нужно сосредоточиться только на orderId(Заказ ID), поэтому доступны все три структуры данных.

Например, используйте hash При хранении мы можем хранить key установлен на UnpaidOrder-{userId},каждый field Это все приказ.

но,Теперь мы столкнулись с проблемой: время выживания каждого Заказа разное.,Оно разделено на ручное потребление, обычное удаление и логическое.

  • После того, как заказ 1 оплачен вручную, orderId1 необходимо удалить из списка.
  • Срок действия заказа 2 автоматически истечет, если он не будет оплачен в течение получаса. Пользователь может продолжить перевод заказа в неоплаченный статус.

Поэтому в структуре List, Set или Hash для каждого поля необходимо установить отдельный срок действия.

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

2. Общие решения

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

Для приведенного выше сценария нам необходимо посчитать количество неоплаченных заказов пользователей, но срок действия каждого заказа разный.

В этом случае нам необходимо вручную удалить поля с истекшим сроком действия в бизнесе или позволить им автоматически истечь.

2.1 Установить срок действия для отдельных полей?

Мы знаем, что в настоящее время в Redis нет интерфейса для установки времени истечения срока действия индивидуально для полей List, Set или Hash. Время истечения срока действия можно установить только для всего списка, набора или Hash.

так,когда List/Set/Hash Когда он истечет, все field Срок действия всех элементов истек

Но это не отвечает потребностям.

Маленькая ❤ попыталась найти в Интернете несколько известных решений, одно из которых Stack Overflow из проблемного поста, с которым я столкнулся, очень похоже:

Источник рисунка: StackOverflow, как установить срок действия дочернего ключа (поля) HSET в Redis?

Затем я случайно увидел ответ автора Redis в ответе под постом:

Китайский перевод выглядит следующим образом:

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

Срок годности сохраняется, а затем программа определяет, истек ли он.

Это действительно огонь в мешке, очень жгучий!

2.2. Установите общий срок действия.

теперь это Redis Так сказали основатели Redis невозможно быть одному field Чтобы установить время истечения срока действия, первое, что мы рассматриваем, это дать всю List/Set/Hash Установите срок годности.

Этот подход прост и груб, но с ним сложно удовлетворить необходимость устанавливать срок действия индивидуально для каждого поля.

затем,Я думаю об этом,теперь это Срок годности каждого Заказа разный,Так можем ли мы создавать разные изоляторы в зависимости от времени?,Поместите из Заказ, срок действия которого истекает в то же время, в ту же сборку:

Затем,соответственно разныеизсобиратьнастраивать TTL, когда срок действия заказа истекает без оплаты, заказ будет удален в течение той же минуты, когда истечет срок сбора.

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

Более того, может возникнуть проблема при создании коллекции за считанные минуты: срок действия заказа пользователя изначально истекал в 01 секунде, но был удален через 59 секунд.

Если вы создаете коллекции за секунды, 1800 коллекций необходимо создать за 30 минут, что сложнее в управлении, поэтому установка общего срока действия коллекций невозможна.

Есть ли более элегантный способ реализовать это?

2.3 Реализация zset в сочетании со счетом

Конечно, есть!

Помимо часто используемых структур List/Set/Hash, Redis также имеет структуру данных, специально используемую для сортировки, zset (т. е. Sorted Set, отсортированный набор).

Основываясь на структуре Zset Redis, время истечения срока действия может быть представлено в виде Score, и мы можем легко реализовать отдельный срок действия каждого поля.

Конкретная реализация:

  1. При каждом добавлении нового платежа предыдущее время будет меняться. Unix timestamp плюс срок годности 30min как score установить этот элемент,так,sorted set Элементы будут отсортированы и сохранены на основе этой отметки времени истечения срока действия;
  2. После оплаты Заказа необходимо оплатить Заказ по userId и orderId удалить отсортированный набор;
  3. в то же время,Добавьте запланированную задачу в программу,Каждую секунду удаляю, когда время истекло из Заказ.

2.4 Низкоуровневая реализация

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

С другой стороны, операция zset в Redis очень эффективна и не оказывает существенного давления на производительность системы.

Это связано с zset Базовая структура данных Zset Базовая реализация использует ZipList (Почтовый список) и SkipList (список пропуска)Два видавыполнить Способ,когдаудовлетворить:

  • Zset середина сохраняет количество элементов меньше, чем 128 (можно изменить zset-max-ziplist-entries конфигурацию для изменения)
  • Zset середина сохраняет все элементы, длина которых меньше 64 байта (путем изменения zset-max-ziplist-values конфигурацию для изменения)

При наличии двух условий Zset использовать Реализация ZipList; в противном случае,использовать Реализация списка пропуска。

Реализация ZipList

ZipList это массив формы,Время хранения данныхЧасть заголовка списка и часть данных,Заголовок списка имеет 3 элемента:

  • zlbytes: представляет общую длину списка элементов хранилища до того, как
  • zllen: представляет количество элементов, сохраненных в списке до того, как
  • zltail:выражатькогдавперед list изHead node из адреса, передано zltail Просто могу восстановить list из Траверс

Часть данных организована в виде пар ключ-значение, и ключ хранит фактическое значение. member,хранение ценностейизда member переписыватьсяиз Очки(score)。

Реализация списка пропуска

SkipList разделен на две части:

  1. dict Частично получено из словаря калибровки (который на самом деле HashMap, содержащий элементы score из МАП);
  2. zset Частично выполнить сбор таблицы переходов makeuse (сохранены все элементы, решено) HashMap середина key расстройство из проблемы).

Как видно из рисунка, dict и zset Все данные магазина.

Но на самом деле dict и zset Последние используемые указатели указывают на одни и те же данные элемента, то есть данные являются общими для двух частей. Для удобства выражения одни и те же данные отображаются в двух местах.

2.5 Реализация кода

Когда мы вставляем срок действия в zset Когда, Редис Он автоматически отсортирует его для нас.,Нам нужно только добавить запланированное задание в программу середина,Например: выполнять задачу удаления каждую секунду.,Удалить временную метку из 0 к текущей временной метке score Просто цените

Псевдокод выглядит следующим образом:

Язык кода:javascript
копировать
# 1. При создании нового Заказа к оплате запросите количество zsets.
count = zcard UnpaidOrder-{userId}

# 2. Определить количество неоплаченного Заказа
if count >= 3:
        return

# 3. Добавлен заказ
zadd UnpaidOrder-{userId} redis.Z{Score: {timestamp1}, Member: {order1}}

# 4.1 Заказ После оплаты от set середина Удалить неоплаченный заказ
zrem UnpaidOrder-{userId} order1

# 4.2 Срок годности истек, от set середина Удалить неоплаченный заказ
zremrange UnpaidOrder-{userId} 0 {current_timestamp}

3. Заключение

Благодаря разумному выбору структуры данных и умному применению мы успешно решили проблему списков, наборов и хешей. поля в поездке.

Это решение было проверено на реальных проектах и ​​дало замечательные результаты. Сравните с другими очередями задержки или etcd из field Срок действия плана истек,Redis извыполнить относительно удобнее.,Это также проще понять.

Я надеюсь, что это решение можно использовать в вашем проекте.,Повышение эффективности разработки,Лучше реагировать на реальные потребности. Если у вас есть дополнительные вопросы об использовании Redisuseiz,Также вы можете общаться и обсуждать в комментариях.

Redis становится все более комфортным в этом мире и добивается новых прорывов в технологиях.

Я маленькая ❤, увидимся в следующий раз!

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose