Real-Time Backend

Design: Live Auction

USD 69 млн долларов за JPG-файл - и вся сумма определилась за последние 20 минут торгов. Christie's онлайн аукцион Beeple в 2021 году: система обрабатывала ставки в режиме реального времени при наблюдении миллионов людей. Один баг в bidding engine - и крупнейшая сделка в истории цифрового искусства могла стать скандалом.

  • eBay: 1.4 млрд активных листингов, proxy bidding работает с 1995 года - механизм не изменился за 30 лет, только масштаб
  • Christie's онлайн аукцион 2021: NFT-работа Beeple продана за USD 69 млн долларов, последние 20 минут - лавина ставок, soft close продлевал таймер многократно
  • Sotheby's BidNow: платформа с anti-sniping (продление на 2 мин при ставке в последние 2 мин), обслуживает физические и онлайн торги одновременно
  • Дефицитный товар за USD 0.01: когда Amazon или Sony проводят flash-sale, race conditions в naive системе могут привести к тому, что тысячи покупателей 'победят' одновременно

Архитектура аукционной платформы

eBay обслуживает 1.4 млрд активных листингов одновременно. За каждым аукционом стоит система, где задержка в 200 мс может стоить победы - и репутации платформы. Задача архитектора: обеспечить консистентность ставок при пиковых нагрузках без блокировок на горячих лотах.

Ключевые компоненты

Auction State в Redis - это hot spot системы. Все операции со ставками проходят через него. Для исключения race conditions используется Lua-скрипт: атомарная операция compare-and-set (CAS) гарантирует, что ставка принимается только если она выше текущей.

WebSocket - стандарт для live-аукционов. Sotheby's BidNow и Christie's используют постоянные соединения: клиент получает обновления цены мгновенно, без polling. При 50 000 одновременных зрителей одного лота - это критично.

КомпонентТехнологияПочему
Состояние аукционаRedis clusterSub-ms latency, атомарные Lua-скрипты
Соединения клиентовWebSocket + sticky sessionsPersistent duplex, fan-out уведомлений
Аудит ставокPostgreSQL (append-only)ACID, история для споров
Fan-out уведомленийRedis Pub/Sub или KafkaМасштабируемая рассылка всем зрителям

Почему операция принятия ставки выполняется через Lua-скрипт на Redis, а не через стандартные GET + SET команды?

Bidding Engine: обработка ставок

Proxy bidding - механизм, которым eBay пользуется с 1995 года и который до сих пор формирует доверие к платформе. Участник указывает максимальную сумму, система автоматически перебивает конкурентов минимальным шагом - и раскрывает реальный максимум только если его превысили.

Proxy Bidding: алгоритм

Как работает proxy bidding на практике

Лот начинается с USD 100. Участник A устанавливает максимум USD 500. Система ставит USD 100 от его имени. Участник B ставит USD 200 - система автоматически ставит USD 210 (шаг USD 10) от A. Участник C ставит USD 550 - побеждает, система раскрыла, что максимум A был USD 500. Итог: A проиграл на USD 550, хотя его реальный максимум был USD 500.

Шаг ставки: динамическая сетка

Диапазон ценыМинимальный шаг
USD 0 - USD 99USD 1
USD 100 - USD 999USD 5
USD 1 000 - USD 9 999USD 25
USD 10 000 - USD 99 999USD 100
USD 100 000+USD 500

Christie's онлайн аукцион NFT-работы Beeple установил рекорд: USD 69 млн долларов. Система обрабатывала ставки с интервалом в секунды при одновременном наблюдении миллионов зрителей. Bidding engine должен гарантировать порядок ставок даже при сетевых сбоях - через sequence numbers и idempotency keys.

Idempotency key - защита от двойных ставок при retry. Клиент генерирует UUID для каждой ставки. Если сеть оборвалась и запрос повторился - сервер распознает дубликат по ключу и возвращает результат первоначального запроса.

Участник установил proxy bid USD 300 при текущей цене USD 100. Конкурент ставит USD 250. Какую цену выставит система?

Anti-sniping: защита от последней секунды

Sniping - ставка в последние 2-5 секунд аукциона, когда конкуренты не успевают ответить. Это не баг, это фича системы с жестким дедлайном - и одновременно фундаментальная проблема честности. eBay долгое время не боролся с sniping, считая это частью игры. Сейчас большинство платформ реализуют soft close.

Soft Close: продление таймера

Sotheby's BidNow продлевает аукцион на 2 минуты при каждой ставке в последние 2 минуты, до максимума 10 продлений. Это превращает жесткий дедлайн в скользящее окно - аукцион завершается только когда никто не делает ставок 2 минуты подряд.

Детекция sniping: серверное время

Критичный момент: все временные метки должны генерироваться на сервере. Если клиент может манипулировать timestamp ставки - система сломана. Ставка считается принятой в момент получения на сервере, а не в момент отправки клиентом.

  1. Клиент отправляет ставку с client-timestamp (только для диагностики сети)
  2. Сервер фиксирует server-received-at при получении
  3. Сравнение с auction.endsAt происходит по server-received-at
  4. Ставки, полученные после endsAt, отклоняются с кодом AUCTION_ENDED
  5. Граничный случай: ставка in-flight в момент окончания - принимается, если received-at <= endsAt

Аукцион настроен с soft close: продление на 5 минут при ставке в последние 3 минуты, максимум 10 продлений. Участник делает ставку за 90 секунд до конца. Через 4 минуты другой участник делает ставку. Что происходит?

Fairness: честность и консистентность

Fairness в аукционах - не просто этика. Это survival requirement: платформа, где участники чувствуют нечестность, теряет доверие быстрее, чем успевает вырасти. Две главные угрозы: технические (race conditions, clock skew) и поведенческие (bid shielding, shill bidding).

Технические проблемы честности

  • Clock Skew — Серверы в кластере имеют разное системное время (±100 мс типично). Ставки с разных узлов могут получить одинаковый timestamp. Решение: Lamport timestamps или централизованный sequence generator - монотонно возрастающий счетчик, не зависящий от реального времени.
  • Network Latency Inequality — Участник с low-latency соединением имеет преимущество перед участником с high-latency. Платформы из разных регионов получают ставки с разной задержкой. Частичное решение: geo-distributed узлы приема ставок, но полное равенство недостижимо.
  • Last-write-wins конфликты — При одновременных ставках на одну цену побеждает та, что пришла первой на master-node. Алтернатива: tie-breaking правило (меньший userId выигрывает при равной цене и одном timestamp). Это детерминировано и аудируемо.

Bid shielding и shill bidding

Аудит и разрешение споров

  • Каждая ставка записывается в append-only лог с server-timestamp и Lamport clock
  • История ставок неизменяема: ни администратор, ни система не могут модифицировать запись
  • Участник может запросить полный лог ставок по любому лоту (transparency)
  • Победная ставка подтверждается криптографической подписью финального состояния
  • SLA на разрешение споров: Christie's и Sotheby's гарантируют ответ в течение 24 часов

Immutable audit log - это не только честность, это юридическая защита. В случае судебного спора о результате аукциона (особенно актуально для лотов на USD 1 млн+) платформа должна предоставить полную хронологию ставок с верифицируемыми timestamps.

Fairness в аукционе достигается простым правилом 'первая ставка побеждает' - кто успел, тот и выиграл

При распределенной системе 'первая ставка' неопределима без causal ordering. Clock skew в 100 мс делает физическое времяненадежным критерием. Нужны Lamport timestamps или centralized sequence numbers.

В системах с несколькими узлами нет единого понятия 'одновременно'. Ставки, кажущиеся одновременными для разных клиентов, могут прийти на разные узлы кластера с разным порядком. Без causal ordering честность недостижима технически.

Два участника делают ставку USD 1000 одновременно (разница 50 мс по сети). Какой механизм гарантирует детерминированный и аудируемый выбор победителя?

Итоги

  • Атомарность - фундамент: compare-and-set через Redis Lua-скрипты исключает race conditions на hot spots аукциона
  • Proxy bidding скрывает реальный максимум участника, автоматически перебивая конкурентов минимальным шагом
  • Anti-sniping через soft close превращает жесткий дедлайн в скользящее окно - аукцион завершается только при паузе в активности
  • Fairness требует causal ordering (Lamport timestamps) и immutable audit log - честность технически недостижима без них

Связанные темы

Live auction platform строится на фундаментальных паттернах distributed systems:

  • Distributed Consensus — Lamport timestamps и causal ordering - прямое применение теории распределенных часов для разрешения конфликтов ставок
  • WebSocket и реальное время — Fan-out уведомлений о новых ставках всем зрителям - классический use case persistent duplex соединений
  • Redis и атомарные операции — Lua-скрипты в Redis как механизм compare-and-set для hot state аукциона - основа correctness системы
  • Rate Limiting — Velocity check для детекции fraud и защиты от DDoS через фиктивные ставки - стандартный слой защиты

Вопросы для размышления

  • Аукционная платформа вводит ограничение: не более 5 продлений anti-snipe. Какие trade-offs между честностью и UX это создает? Как изменится поведение участников?
  • Proxy bidding скрывает максимум участника - но что если платформа технически имеет доступ к этим данным? Какие архитектурные механизмы не позволяют сотрудникам платформы злоупотреблять этим?
  • При разработке Christie's онлайн аукциона: как тестировать anti-sniping логику и fairness механизмы без возможности воспроизвести реальный трафик USD 69 млн долларов лота?

Связанные уроки

  • sd-01-intro
Design: Live Auction

0

1

Войти