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

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

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

В сообщении в блоге 2019 года на веб-сайте IBM Алан Чатт, менеджер по предложениям IBM Event Streams & Kafka, сказал: «Простой способ думать об этом - это то, что потоковая передача событий позволяет компаниям анализировать данные, относящиеся к событию, и реагировать на это событие. в реальном времени." «Событием» может быть нажатие кнопки, отправка формы, транзакция, что угодно. Вы можете видеть, насколько это важно для чего-то вроде цифровой лотереи, потому что информация о записях должна быть точной и постоянно обновляться.

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

Самый популярный сервис для потоковой передачи событий - Apache Kafka. Kafka или аналогичный сервис потоковой обработки может обрабатывать очередь запросов билетов. Пользователь может отправить запрос API на участие в лотерее. Это представление должно содержать рекламный идентификатор, относящийся к шоу, дате и времени, а также идентификатор транзакции, в идеале универсальный уникальный идентификатор (UUID), специфичный для пользователя. Ответ JSON может быть таким же простым, как логическое значение, независимо от того, является ли билет «выигрышным» или «проигрышным», или целочисленным ответом, то есть 0 для выигрыша, 1 для отсутствия выигрыша, 2 для лотереи закрыто. Что касается безопасности, эти запросы также должны содержать уникальные идентификаторы сеанса и I.P. журналы адресов, чтобы ограничить количество запросов, исходящих от одного или небольшого числа пользователей.

Вышеизложенное необходимо учитывать для всей системы, но что касается метода выбора «победителей», существует множество вариантов. Обсуждение алгоритмов сортировки и того, как они могут быть реализованы, слишком обширно для обсуждения здесь. Поэтому вместо того, чтобы анализировать их все, я выбрал алгоритм, который мне интересен. Это не обязательно будет самый быстрый способ, но он будет справедливым. Алгоритм Fisher-Yates Shuffle, который работает как перетасовка колоды карт, гарантирует беспристрастную перестановку и надежную справедливость для всех, кто участвует в розыгрыше, поскольку их положение в массиве держателей билетов будет перемешано и, следовательно, может быть выбрано случайно.

Вот алгоритм, продемонстрированный на JavaScript:

В этом коде цикл настроен на уменьшение currentIndex, пока не достигнет нулевой позиции. Переменная randNum генерирует новое случайное значение от 0 до currentIndex при каждом проходе цикла. Временная переменная сначала представляет значение случайной позиции индекса. Затем вы берете массив со случайным индексом и меняете его на значение в позиции индекса цикла.

Затем индексная позиция прохождения цикла - currentIndex - выбирается и заменяется на временное значение.

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