Как спроектировать систему захвата красного конверта

Микросервисы

предисловие

Привет всем, я Xiao P, в этой статье я расскажу, как спроектировать систему захвата красных конвертов, надеюсь, она будет полезна всем. Он в основном показывает дизайн системы захвата красных конвертов.Алгоритм красных конвертов не находится в центре внимания, поэтому нет такой реализации, как метод двойного среднего. Схема, описанная ниже, была реализована, и код находится вgithub, обсуждение приветствуется.

анализ спроса

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

Поскольку рассматривать красный конверт слишком просто, в этой статье он не обсуждается. Тогда остается только вариант использования системы发、抢два вида.

  1. Отправка красных конвертов: пользователь устанавливает общую сумму и количество красных конвертов
  2. Возьмите красный конверт: пользователь случайным образом получает определенную сумму из суммы, выделенной красным цветом.

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

Хорошо, после анализа переходим непосредственно к рабочему проекту. Так просто есть только два интерфейса:

  1. Красные конверты
  2. возьмите красный конверт

дизайн структуры таблицы

Оператор создания таблицы приведен непосредственно здесь:

Таблица активности красного конверта:

CREATE TABLE `t_redpack_activity`
(
    `id`         bigint(20)     NOT NULL COMMENT '主键',
    `total_amount`     decimal(10, 2) NOT NULL DEFAULT '0.00' COMMENT '总金额',
    `surplus_amount`     decimal(10, 2) NOT NULL DEFAULT '0.00' COMMENT '剩余金额',
    `total` bigint(20)     NOT NULL DEFAULT '0' COMMENT '红包总数',
    `surplus_total` bigint(20)     NOT NULL DEFAULT '0' COMMENT '红包剩余总数',
    `user_id`    bigint(20)     NOT NULL DEFAULT '0' COMMENT '用户编号',
    `version` bigint(20)     NOT NULL DEFAULT '0' COMMENT '版本号',
    PRIMARY KEY (`id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

Таблица красного конверта:

CREATE TABLE `t_redpack`
(
    `id`         bigint(20)     NOT NULL COMMENT '主键',
    `activity_id`         bigint(20)     NOT NULL DEFAULT 0 COMMENT '红包活动ID',
    `amount`     decimal(10, 2) NOT NULL DEFAULT '0.00' COMMENT '金额',
    `status`     TINYINT(4) NOT NULL DEFAULT 0 COMMENT '红包状态 1可用 2不可用',
    `version` bigint(20)     NOT NULL DEFAULT '0' COMMENT '版本号',
    PRIMARY KEY (`id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

список:

CREATE TABLE `t_redpack_detail`
(
    `id`         bigint(20)     NOT NULL COMMENT '主键',
    `amount`     decimal(10, 2) NOT NULL DEFAULT '0.00' COMMENT '金额',
    `user_id`    bigint(20)     NOT NULL DEFAULT '0' COMMENT '用户编号',
    `redpack_id` bigint(20)     NOT NULL DEFAULT '0' COMMENT '红包编号',
    `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    PRIMARY KEY (`id`)
) ENGINE = InnoDB
  DEFAULT CHARSET = utf8;

В таблице активности указано, сколько красных конвертов вы отправили, а оставшуюся сумму нужно сохранить. Подробная таблица — это детали красных конвертов, которые схватил пользователь. Таблица красных конвертов содержит информацию о каждом конкретном красном конверте. Зачем вам три таблицы? На самом деле, если нет таблицы красных конвертов, это тоже возможно. Но наш план预先分配红包Для записи информации о красных конвертах необходимо использовать таблицу, поэтому эта таблица доступна только во время проектирования.

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

Реализация на основе распределенной блокировки

Реализация распределенной блокировки самая простая и грубая, весь хватает красный пакетный интерфейсactivityIdв видеkeyБлокировка выполняется для обеспечения того, чтобы одна и та же партия операций захвата красных конвертов выполнялась последовательно. Распределенные блокировки реализуютсяspring-integration-redisИнженерия обеспечивает, основные классыRedisLockRegistry. блокировать черезRedisизluaРеализация скрипта и реализует блокировку локального повторного входа.

Реализация на основе оптимистической блокировки

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

Реализация на основе пессимистической блокировки

Поскольку увеличение конфликта оптимистичных блокировок в таблице активности красного конверта очень велико, вы можете рассмотреть возможность использования пессимистической блокировки:select * from t_redpack_activity where id = #{id} for update, обратите внимание, что внутри транзакции должны использоваться пессимистические блокировки. В этот момент все действия по захвату красных конвертов стали последовательными. В этом случае эффективность пессимистической блокировки намного выше эффективности оптимистической блокировки.

Предварительное выделение красных конвертов на основе реализации оптимистической блокировки

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

Реализация на основе очереди Redis

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

На основе очереди Redis, асинхронное хранилище

Эта схема не использует базу данных после захвата красного конверта, а сохраняет постоянную информацию вRedis, затем возвращает успех. через другую нитьUserRedpackPersistConsumer, извлекать постоянную информацию для хранения. Следует отметить, что если тяговое действие в это время использует обычныеpopвсе еще появляютсяcrash point, поэтому, учитывая доступность, используйтеRedisизBRPOPLPUSHОперация, извлеките элемент и добавьте его в другую очередь для резервного копирования, чтобы убедиться, что он может быть автоматически восстановлен через очередь резервного копирования после сбоя здесь. поток восстановления после сбояCrashRecoveryThreadРегулярно извлекая информацию о резервной копии, зайдите в БД, чтобы проверить, успешно ли сохраняется сохранение, в случае успеха очистите этот элемент, в противном случае компенсируйте и очистите этот элемент. Если во время работы базы данных произойдет исключение, будет записан журнал ошибокredpack.persist.log, этот журнал использует отдельный файл и формат для легкой компенсации (обычно не запускается).

послесловие

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