Хабрахабр

Как мы делали клубную программу Спортмастера

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

Тогда

На дворе стоял 2004-й год. Что было — клубная программа у Спортмастера и доллар по 27 рублей. Чего не было — нормального интернета на местах и стабильных каналов связи у магазинов.

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

То есть для базы это выглядело просто, грубо говоря, одна карта — одна циферка. Работали сами карточки довольно просто — на каждой карте просто накапливалось определенное число бонусов, которые её владелец мог радостно и с чувством потратить. Это когда ты купил велик, а через полгода захотел подтянуть цепь, проверить тормоза, звонок стал не так греть душу и отпугивать прохожих и прочее (или поточить коньки к новому сезону и поправить сноуборд, например). С золотыми картами было немного сложнее — там кроме циферки с бонусами были ещё и сервисные баллы.

И да, если этот человек вдруг решил чуток поболеть или что ещё — некоторые покупатели могли остаться без бонусов в эти нелёгкие дни. При этом начисление бонусов проводилось мощностями решения на базе естественного интеллекта — у нас был специальный сотрудник, который писал селекты и делал выборки, потом начислял в специальной табличке бонусы, а система подтягивала эту табличку.

Само собой, для бизнеса такая ситуация была довольно затратна, да и вообще — опасна и непредсказуема, и бизнес хотел перевести систему на нормальные (автоматические) рельсы.

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

И в один прекрасный день эта база просто перестала пролезать через имеющиеся каналы связи. Второй проблемой было ещё и то, что с ростом клиентской базы и количества магазинов сложилась ситуация, когда всё более и более здоровенную базу надо было пересылать во всё большее и большее количество магазинов. Обсчитывалась по всем магазинам в короткий промежуток времени она тоже с большим скрипом.

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

Собрал от бизнеса ряд требований к этой системе с их стороны и прописал новые возможности. И тогда Александр Афанасьев (ныне IT-директор другой компании) придумал, как всё это можно сделать самим, не покупая сторонний софт. Можно давать человеку бонусы на день рождения, можно отдельно дать бонус только на лыжи и связанные с ними товарные позиции, можно предложить бонусы только на товары бренда Columbia и в определенные периоды времени — и всё это комбинировать, комбинировать, комбинировать. Сначала просто в виде приятных фич — к примеру, теперь бонусы это не просто одна цифра, а целая сложная система.

То есть схема работы стала такой — есть магазин со стабильным сетевым каналом, он по сети обращается в базу за остатком (а в базе теперь всё самое свежее и вкусное), забирает остаток бонусов из базы и работает уже с ним. К счастью, развитие сети достигло того момента, когда интернет таки уже появился почти везде, и можно было вывести решение в онлайн. И все это, пока покупатель радостно общается с приветливым продавцом.

У нас же как — ты можешь весь год задорно копить баллы, но 1 марта они всегда вероломно сгорают, если ты не успел их потратить. Третьей проблемой было проведение операций по сгоранию бонусов.

Ведь сжигание бонусов — это полноценный проход по всей базе с изменениями. Первая версия системы (под названием CARDS) могла их нормально учитывать, но вот когда она переходила в режим бонусосжигательного завода, начинались проблемы. Причем в процессе она жутко тормозила и тупила, из-за чего иногда сжигание бонусов прерывали, и получалось, что в каком-то магазине у камрада Петрова, зашедшего за новыми шариками для пинг-понга, бонусы ещё есть, а у Сидорова, зашедшего за новым великом, уже, к сожалению, нет. Учитывая размер базы, это могло занять дня 3-4.

Новая версия системы

Мы сделали прототип где-то за 3-4 дня, потом пару дней потестили его на живых чеках. Оказалось, что система вполне себе работоспособна, и можно использовать её для генерации разных условий бонусов и формирования текстов коммуникаций.

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

Взаимодействие с ними проходило примерно так:

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

Так вот, о прототипе. В принципе всю систему было решено сильно отреинженирить, потому что изначально она была заточена только под учёт бонусов, а не под работу онлайн, поэтому она ожидаемо перестала справляться с отдачей. Причём падала она, само собой, в моменты высокой нагрузки. То есть в самое вкусное для магазина время — Новый год, 8 марта, 23 февраля и прочие приятные даты.

Падает система —> падает настроение у бизнеса —> падает настроение у всех.

Вдвоем с коллегой мы переписали систему по следующему принципу.

Компонент 1. Препроцессинг, максимально оперативно отдающий магазинам ответ.
Компонент 2. Процессинг, тот самый магический ящик, сложно и хитро начисляющий бонусы на товарные чеки.
Компонент 3. Маркетинг, собирающий всё это воедино и формирующий тексты коммуникаций.

Новая система просто их не сжигала. Плюс ко всему мы решили проблему сгорания бонусов. Ведь если ты не заставляешь систему сжигать бонусы — у тебя нет проблем со сжиганием бонусов.

То есть теперь бонусы есть всегда, но каждый — со своим периодом активности. В новой версии система просто хранит бонусы каждого клиента в базе, но в какой-то момент времени перестаёт считать их активными. Что, кстати, позволило вводить более точные и более срочные акции и кампании.

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

Дополнительной фичей новой системы стали так называемые товарные бонусы, это работает вот так:

  • у каждого товара есть атрибуты (наименование, товарная категория, размер, цвет, вид спорта, прочее, прочее, прочее).
  • система комбинирует эти атрибуты, формируя логическое условие для начисления бонусов.
  • при прилетании чека такое условие всегда проверяется.

Мы показали этот прототип в работе бизнесу. Бизнес дал добро.

На самом деле, плановой датой поставки было 1 сентября, но не успевал главный контрагент системы — розничные магазины. Писать систему мы начали 1 марта, внедрили в работу 27 октября 2013 года (писали вдвоём, да). Поэтому отложили, дождались их, и запустились 27 октября. Магазины не успевали по ряду своих причин, плюс не у всех обновили кассовое ПО (а обновлять кассовое ПО в масштабах довольно крупной сети — это та ещё боль).

Идеология системы

Заложили главную идею — ни магазин, ни кассовое ПО больше не работают с логикой бонусов. Магазин теперь просто отправляет корзину покупателя в Центр, Центр всё это дело обрабатывает, отдаёт магазину расчёт по бонусам.

Сейчас бонусы размазываются так:

  • Прежде всего, бонусы размазываются по всему чеку равномерно, на все товарные позиции. Это и полезно для аналитики, и помогает в случае возврата товара.
  • Ввели понятие приоритета бонусов. Бонусы есть товарные, есть бонусы на дни рождения, у которых срок действия короткий, есть регулярные (самые живучие). Поэтому мы сначала списываем именно специфичные бонусы. То есть пришёл человек за лыжами — мы спишем прежде всего бонусы, которые у него есть именно на лыжи. А то получится, что пришёл он за лыжами, мы списали регулярные бонусы. Через неделю придёт за курткой, а мы ему — Мужик, у тебя только бонусы на лыжи есть. Хочешь лыжи? То же самое с покупками в периоды дня рождения, сначала списываем их, а потом — регулярные.
  • Разносим бэкофисные операции и фронт. Теперь магазины, приходящие с запросами, никак не влияют на работу и производительность сервиса, начисляющего бонусы, и наоборот

В общем, удалось забороть все старые проблемы, а вместо новых проблем добавить новых возможностей.

Вместо бэклога у нас была вот такая тетрадь Александра.

Запуск новой версии системы

Так как новая система отличалась от старой не только технически, но и идеологически, мы не могли накатывать её как-то частично, на половину магазинов или как-то ещё. Мы должны были просто отключить старую и включить вместо неё новую.

Звучит неплохо, но на деле упирается в пару ограничений.

Пока один магазин в полночь в одном часовом поясе закрывается, в другом совсем иное время, а тут ещё и плюс круглосуточные магазины. Во-первых, из-за большого количества магазинов (1200+) мы должны были успеть всё сделать за 3 часа. В общем, чтобы сконвертировать все данные из старой системы, скормить новой, запуститься на трёх серверах сразу — 3 часа.

Подводные камни были вот такие:

  • Система врубалась сразу на всей сети. Если всё везде хорошо — всё работает по всей сети. Если что-то падает — да, падает по всей сети.
  • Новая система при включении должна содержать в себе все данные, которые были в старой системе на момент закрытия магазинов и выдачи самого свежего бонуса. Мы запускались на 4 страны разом. БД была более терабайта и хранила сотни миллиардов записей.
  • В 23.00 мы должны были выключить систему. Сконвертировать всё. Залить в новую систему. Включить всё. При этом всё должно работать.

Мы долго тренировались, увешались скриптами по самое небалуйся. После долгих тестов и попыток сделать всё максимально быстро мы достигли лучшего результата в 9 часов.

Что немного отличалось от задуманной цифры в 3 часа.

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

Но всё равно, такой объём данных на стандартных машинах в установленный срок сделать не получалось.

Ребята из Oracle сделали специальную железку, которая прекрасно работает с её же БД, да ещё и на флеш-дисках. И тут надо отметить Oracle Exadata. С её помощью на тестах мы осилили сделать всё нужное за 2 часа вместо 9 и поняли — надо брать. В общем, было принято волевое решение использовать Exadata.

Например, был один занятный баг — из-за ошибки во внутренней обработке запроса Oracle стал усиленно потреблять TEMP. Так как мы ребята дотошные, в процессе настройки и работы мы выгребли кучу багов и завалили саппорт Оракла с запасом. Но поскольку железяка оказалась очень толковой и знающей свое дело, она с чувством употребила 3 Тб TEMP за 10 минут, поняла, что больше нет, и ушла на покой. Мы это вовремя заметили, и накинули ему еще TEMP’овых файликов, было очень интересно, когда же он нажрется. Пришлось придумывать обходы.

С другой стороны, во всём процессе чистой конвертации 2 часа, а мы планировали ещё и: С одной стороны, было круто, что всё в плане конвертации у нас сделалось за 2 часа.

  • перезалить все данные с серверов старой системы на exadata, потому что она дико быстро всё считает.
  • сконвертировать данные из старых структур в новые.
  • залить всё это сконвертированное добро на три разных сервера.

В каждой БД при этом находилась куча полезной служебной инфы типа тех же индексов, которые могли помочь при перестройке, но мы забили на это и решили перестроить всё заново уже на боевых серверах.

Подготовка

Мы готовились вовсю. Мы спали на работе. Мы увешались не только скриптами, но и множеством метрик.

00 каждый день мы запускали процесс и следили за метриками. В 23. Вносили нужные правки, в итоге настроили всё так, что вообще ничего не могло пойти не так.

Ясное дело, именно в день запуска что-то пошло не так.

Где-то тупо моргнула сеть. К нашей чести, косяк был не на нашей стороне. То есть сидишь себе такой, настраиваешь всё, чтобы комар не только носа не подточил, но даже не успел подумать об этом — и кто-то где-то просто дёргает не тот кабель.

Общим дедлайном было 5 утра, к этому времени все серваки должны быть бодры и веселы, потому что первые магазины на Дальнем Востоке открываются в 10 по их времени. Всё равно первый сервак мы успели запустить вовремя.

Но так как мы строили систему таким образом, что всё было изолировано, всё заработало нормально. Итого последний сервак запустился в 11 утра.

Сейчас

Сейчас над клубной системой работают 14 разработчиков и 8 аналитиков. Учитывая все плюшки, которыми мы её обвешали, это уже давно не просто карточка, которая даёт вам определённое число бонусов, доступных к трате в магазинах.

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

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

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

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

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

А в одном из будущих постов мы расскажем вам историю создания сайта Спортмастера. Но и с этим мы тоже разберемся.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть