Почему система подарков в мобильной игре ломается на пиках
Пик наступает не в момент запуска, а когда система подарков мобильной игры получает лавину одновременных отправок: ивент, крупная рассылка, открытие сезона. Клиент шлёт запрос, сервер не успевает подтвердить операцию в срок, клиент повторяет — и вместо одного подарка начисляются два.
Типовые точки разрыва — повторная отправка без ключа операции (дубли начислений), списание у отправителя без начисления получателю (потерянный подарок, который игрок уже видит в истории) и зависшая операция: откатить её автоматически нельзя, завершить тоже.
Отдельный источник дублей — подтверждение покупки в Google Play: платёж проведён, а сервер запрашивает проверку повторно и начисляет подарок второй раз. Ни один из этих сбоев не виден на графиках доступности — падает не сервис, а корректность учёта подарков.
Цена считается в часах поддержки: каждое расхождение — ручной разбор, запрос скриншотов, компенсация и правка баланса в базе. Пока такие случаи единичны, их закрывают руками; на пике счёт идёт на сотни обращений, и очередь разборов растёт быстрее, чем команда успевает её разгребать.
Корни обычно одни и те же: лимиты проверяются на клиенте, а не на сервере, повторы идут без дедупликации, баланс пишется синхронно с выдачей, а сверки начисленного и списанного нет вовсе. Дальше разбираем, как это закрывается — от идемпотентной выдачи до очередей и push-уведомлений, которые не добавляют нагрузки в пик.
Эффект от управляемой выдачи: что меняется в цифрах
Доля успешных отправок перестаёт зависеть от качества связи у игрока. На каждом шаге выдачи есть подтверждение и повтор с тем же ключом операции: подарок либо доставлен, либо будет доставлен, третьего состояния нет. Конверсия отправок растёт без правок в самих правилах игры.
Время восстановления после сбоя считается минутами, а не волной обращений. Очередь подарков переживает перезапуск процесса, лимиты снимаются автоматически, а деградация идёт по отдельным каналам — выдача может замедлиться, но не отключается целиком. Инженер видит, какой шаг отстал, и возвращает его точечно.
Объём ручных обращений в поддержку падает, потому что игрок видит статус подарка, а не «что-то пошло не так». Типовые ситуации — не дошло, пришло дважды, лимит на сегодня — закрываются автоматически, и человеку остаются только настоящие спорные случаи.
Дубли начислений уходят как класс отказов: повторная доставка не создаёт второй подарок, а сверка балансов ловит расхождение раньше, чем его заметит игрок. Раньше такое разбирали вручную по логам, теперь расхождений просто нет.
Все четыре показателя — успешные отправки, время восстановления, ручные обращения и дубли — снимаем до и после изменений по одной методике. Так видно, что дал каждый шаг: где выросла конверсия отправок, а где сократилось время возврата в норму.
Варианты выдачи: набор, прямой перевод, обмен
Режим выдачи определяет, как предмет покидает каталог предметов и оказывается в инвентаре получателя. От него зависят суточные лимиты, учёт в истории операций и то, насколько просто откатить ошибочную или дублирующую выдачу. Переиграть это после запуска почти нельзя: уже выданные предметы придётся мигрировать, а баланс экономики — пересчитывать заново.
Режимы ниже не взаимоисключающие — подарочный набор часто соседствует с прямым переводом между игроками, а обмен подарков живёт отдельным контуром. Выбирать стоит под задачу события и под то, кто инициирует выдачу: система по правилу, один игрок или двое по взаимной договорённости.
| Режим выдачи | Когда подходит | Ограничения |
|---|---|---|
| Подарочный набор | Праздничные события, компенсации, стартовые бонусы: состав жёстко описан каталогом | Нет адресности — набор уходит всем по правилу, персональный выбор получателя недоступен |
| Прямой перевод между игроками | Внутриигровая валюта, расходники, подарки друзьям из списка | Суточные лимиты обязательны, иначе ресурсы перекачиваются между аккаунтами одной группы |
| Обмен подарков | Когда предметы должны возвращаться в оборот, а не оседать на складах у получателей | Двусторонняя сделка: откат сложнее, нужен журнал по обеим сторонам и проверка на встречные передачи |
Режим выдачи фиксируется до того, как выдан первый предмет: правила лимитов, журнал операций и логика отката описываются в одном месте и не дублируются на клиенте. Тогда добавление нового режима — расширение правил, а не переделка экономики.
Этапы внедрения: от аудита до передачи в поддержку
Этапы выстроены так, чтобы каждый следующий шаг опирался на проверенный предыдущий: пока не описан текущий учёт, проектировать схему рано, а лимиты нельзя настраивать до закрытия повторов. Ниже — путь от первого дня до момента, когда система живёт без нас.
- Аудит учёта. Смотрим, где хранится баланс отправителя, как фиксируется вручение и что происходит при обрыве связи между игровым сервером и платежным контуром. На выходе — карта узких мест и список сбоев, которые уже случаются.
- Схема данных. Проектируем таблицы подарков, статусов и журнала операций с индексами под реальные запросы: «что уже получил игрок», «сколько отправил за сутки». Ни одна выборка не читает историю целиком.
- Защита от повторов. Каждой отправке присваиваем уникальный ключ операции — повторный запрос возвращает результат первого, а не создаёт второй подарок. Списание и начисление идут в одной транзакции.
- Лимиты. Задаём границы на отправителя, получателя и пару между ними с суточными и недельными окнами. Отдельно описываем поведение при превышении: отказ, очередь или перенос.
- Нагрузочная проверка. Прогоняем пиковые сценарии — праздничные события и массовые рассылки. Смотрим, держат ли лимиты, не растёт ли время отклика и остаётся ли журнал полным.
- Обучение поддержки. Передаём регламенты по типовым обращениям: подарок не пришёл, пришёл дважды, лимит сработал раньше срока. Показываем, как по журналу восстановить путь подарка без правки баланса руками.
- Передача. Закрываем доступы, настраиваем оповещения об аномалиях и договариваемся о реакции на инциденты. Дальше правила и лимиты меняются штатным порядком, без разбора системы заново.
Что передаём на руки: конфигурации, схемы, регламенты
В приложении игрок видит витрину, а сам подарок живёт в правилах, лимитах и учётных записях на серверной стороне. Поэтому на приёмке передаём не только сборки, но и описания, по которым ваша команда меняет условия акций, разбирает спорные начисления и отвечает игрокам без нас.
- Правила начисления — таблица «событие → что и сколько начисляется → что списывается» с оговорёнными исключениями: отмена подарка, возврат, повторная доставка, недоставленное пуш-уведомление.
- Схема учёта — путь каждого подарка от отправителя к получателю: статусы, ключ идемпотентности операции, журнал изменений и источник (игра, промо, поддержка).
- Таблица лимитов — суточные и недельные потолки на игрока, пару, уровень и тип подарка, поведение на границе и порядок ручного повышения.
- Документация интеграции — контракты игровых сервисов и админ-панели: какие события приходят, какой ответ считается успешным, что делать при отсутствии ответа.
- Регламент поддержки — пошаговые сценарии: найти операцию по идентификатору, отличить начисление от дубля, откатить ошибочный подарок, сформулировать ответ игроку.
- Регламент разбора спорных операций — уровни эскалации, сроки ответа, состав доказательств (снимок баланса, журнал статусов) и порядок компенсации.
- Инструкции по эксплуатации — метрики доставки подарков, пороги оповещений, включение «стоп-крана» на начисления и передача дежурства.
Проверка простая: инженер, не участвовавший в разработке, по этим документам воспроизводит начисление и закрывает обращение. Что такую проверку не проходит — доводим до передачи.
Кейс: рост отправок без роста нагрузки на серверы
До переработки подарок уходил в очередь асинхронно, и результат отправки нигде не фиксировался отдельным состоянием. В пиковые часы — массовые события, вечерние окна — доля неуспешных отправок доходила до нескольких процентов, а пользователь видел либо «подарок не отправлен», либо, что хуже, отправлял повторно. Поддержка получала сотни обращений в месяц, и каждое разбиралось вручную: по логам приложения и записям в базе нужно было понять, списался ли предмет и дошёл ли он до получателя. На разбор одной спорной операции уходило больше получаса.
Ключевое изменение — модель состояния операции. На каждую отправку формируется ключ, по которому повторный запрос не создаёт вторую запись, а лишь возвращает текущий статус: создан, зарезервирован, доставлен, возвращён. Списание и начисление идут в одной транзакции по обеим сторонам, поэтому «подарок ушёл, а предмет не списался» перестало быть возможным классом отказа. Отдельно добавили лимиты на отправителя и получателя и очередь с нарастающей паузой между повторами — сервер перестал получать шквал одинаковых запросов в момент пика.
Что показали метрики
| Показатель | До | После |
|---|---|---|
| Доля неуспешных отправок | несколько процентов в пиковые часы | доли процента, остаток — с автоматическим возвратом |
| Обращения в поддержку по подаркам | сотни в месяц | в разы меньше, спорные случаи закрываются без оператора |
| Разбор спорной операции | более 30 минут вручную | 1-2 минуты по журналу операций |
| Пиковая нагрузка | деградация при трёхкратном росте | четырёхкратный рост без добавления узлов |
Устойчивость на пиках обеспечивается не запасом железа, а тем, что очередь разбирается пачками и приоритет отдаётся операциям с уже зарезервированным предметом. Метрики снимали в Grafana по панелям на долю ошибок, глубину очереди и время ответа — тот же набор дашбордов передали команде заказчика, чтобы отклонения ловились до обращений пользователей.
Для игрока разница сводится к одному: подарок либо доходит, либо предмет остаётся у него. Для команды — к предсказуемому разбору инцидентов вместо ручных сверок в дни крупных событий.
Чем подарок отличается от внутриигровой валюты?
Внутриигровая валюта и подарок по-разному устроены в учёте. Валюта — это число на балансе: сервер меняет его одной операцией, а история остаётся в журнале для сверки. Подарок — не число, а факт передачи конкретного предмета конкретному игроку, поэтому учёт подарка строится как запись с уникальным идентификатором, отправителем, получателем и временем выдачи.
Отсюда разная обратимость операции. Ошибочное начисление валюты закрывается компенсирующей проводкой: баланс возвращается к прежнему значению, запись в журнале остаётся. Подарок после выдачи так не откатить — предмет уже у получателя. Платёжные правила App Store требуют восстанавливать купленную валюту при сбое, а подарок восстановлению не подлежит: его либо выдали, либо нет. Поэтому правило возврата задают заранее — до выдачи подарок возвращается отправителю, после выдачи нет.
Правила лимитов тоже решают разные задачи. Для валюты ограничивают эмиссию и скорость начисления на аккаунт — так сдерживают инфляцию и мошеннические начисления. Для подарков лимиты считают по парам отправитель-получатель, по частоте и по ценности предмета, иначе ценность гоняют по кругу между связанными аккаунтами.
Экономика предметов зависит от этого напрямую. Начисление валюты увеличивает общую массу и обесценивает накопления, а подарок лишь перераспределяет уже существующий тираж — но при неограниченной передаче предметы концентрируются у перекупщиков. Поэтому для подарков задают потолок ценности и запрет на вторичную передачу.
Технические сомнения: лимиты, задержки, защита от накрутки
Сомнения по подаркам обычно одни и те же: дубли при повторной отправке, задержки на плохой сети, суточные лимиты, свежие аккаунты и уведомления. Ниже — как эти места закрыты в архитектуре.
Игрок нажал «отправить» дважды — подарок уйдёт дважды?
Нет. Каждая отправка получает уникальный ключ операции, и повтор с тем же ключом сервер отбрасывает. Списание с баланса проходит один раз, даже если запросы пришли одновременно с двух устройств.
Подарок потеряется, если связь оборвётся?
Нет: подарок фиксируется на сервере до ответа клиенту, а начисление идёт через очередь повторов. Игрок видит статус «в обработке», и после восстановления связи операция доводится до конца.
Как считаются суточные лимиты на отправку?
Сервер ведёт счётчики по скользящему окну, а не по календарным суткам: отдельно на число подарков одному получателю, на общий объём за день и на новые аккаунты. При достижении лимита игрок видит причину и время до сброса.
Как закрыта накрутка с новых аккаунтов?
Свежие аккаунты работают в ограниченном режиме, пока не наберут историю: подарки доступны после привязки, а цепочки обмена между связанными аккаунтами уходят на ручную проверку по журналу событий.
Что с уведомлениями и спорными операциями?
Уведомление уходит после подтверждения зачисления, а не в момент отправки, поэтому ложных пушей нет. Если подарок не доставлен, срабатывает возврат по таймауту, а спор разбирается по журналу: видно инициатора, ключ операции и все повторы.
Обсудим задачу: что прислать и что получите в ответ
Обсуждение задачи по системе подарков не должно растягиваться на недели переписки: достаточно прислать набор вводных по проекту — по ним мы сразу видим узкие места и не переспрашиваем очевидное. Чем конкретнее данные, тем точнее оценка этапов и меньше допущений в плане работ.
- Как устроен подарок в текущей модели: запись в инвентаре, отдельная сущность со сроком жизни или ссылка на каталог, и что считается «доставленным».
- Где считаются лимиты — на клиенте, на игровом сервере или в отдельном сервисе подарков, и что происходит при попытке превысить суточный или общий предел.
- Схема начислений и списаний: атомарность парных операций, идемпотентность повторных запросов, поведение при обрыве связи на середине обмена.
- Как устроены уведомления о подарке: кто инициирует отправку, есть ли группировка при веере событий, что видит игрок, вернувшийся в игру спустя сутки.
- Текущие метрики: доля доставленных подарков, повторные попытки, обращения в поддержку с формулировкой «подарок не пришёл».
- Ограничения площадок и правил магазинов к внутриигровым покупкам, зависимость от платёжного провайдера и его лимитов.
- Кто со стороны заказчика принимает решения по игровому балансу и держит тестовые аккаунты для проверки сценариев.
В ответ вы получите схему решения с границами сервисов, план работ по этапам, порядок ввода в бой и перечень рисков с тем, как каждый из них закрывается.







