Каждая компания, принимающая платежи на своем сайте или в магазине, рано или поздно сталкивается с фродом (fraud) и несет убытки. Есть разные методы борьбы с ними. 80% всех задач обычно решаются скриптами, а потом к ним уже докручивается дата-сайнс. Правда не всегда понятно для чего. Но давайте пока не будем останавливаться на этом, а попробуем решить типичные проблемы. Такие, как сбор данных, долгий этап оценки гипотез и снижение нагрузки на внешние системы. Меня зовут Александр Сальков. Я разработчик в Sportmaster Lab. Руковожу направлением дата инженерии и больше 10 лет разрабатываю базы данных и все системы, которые так или иначе с ними связаны. Когда я был молод, написал свой вариант Кафки, который делал то же самое, что делает Кафка, только между инстансами Oracle. Участвовал во всяких разных датасаентистских вещах. В частности, делал систему идентификации людей по венам на ладонях. И много всякого интересного. Sportmaster по факту – группа компаний. У нас больше 500 магазинов с широкой географией. Поэтому если мы говорим про фроды, то их нужно смотреть во всей географии. SM Lab это IT-подразделение группы компаний Sportmaster: порядка 1500 сотрудников, 5 офисов в разных регионах, плюс удаленка по всей России. Давайте пойдем ближе к фроду, но для начала решим, что принято им называть и какие классы задач он решает. В первую очередь, это отслеживание подозрительных пользовательских транзакций и нетипичное поведение пользователей. Также есть классы фродов, которые отслеживают нарушение технологического процесса. Еще очень много разных подклассов-антифродов, но давайте сконцентрируемся на первых двух. Потому что именно на них мы и строили свою систему антифрода. У нас в компании есть человек. Условно назовем его «эксперт». Он хорошо разбирается в типовых операциях, которые происходят в магазине, и их метриках. Знает, как себя ведет пользователь в системах и вообще в нашем информационном пространстве. По ходу статьи будем к нему возвращаться. А пока давайте определимся с какими данными работают системы-антифроды и эксперты. Логично было бы посадить кучу людей, чтобы они отсматривали видео с камер в режиме 24/7 и ловить фроды. Классно и прикольно, но дорого и не работает. Еще вариант слушать разговоры горячей линии техподдержки, обрабатывать аудиопоток и с его помощью делать анализ и выводы. Или прикрутить нейронку, которая все будет делать за нас, а эксперт контролировать. Этот вариант тоже работает так себе. Пока придумывали, поняли, что у нас много внутренних систем, в которых очень много данных. На них и решили посмотреть. Во-первых: это чеки, и все, что с ними связано. Это программа лояльности и система с данными по рационали, движения товаров и мастер-данные. Проблема в географии: все данные либо находятся в ЦОДе, либо распределены по всей стране. А плюс в том, что у нас очень большое IT и почти все системы — это бэк-офис системы. Плюс они в реляционном виде, то есть неструктурированных данных как таковых нет. Объем примерно 30-50 миллионов в сутки. Соответственно, минусы надо превратить в плюсы. У нас есть ЦОД с мастер-данными и нужно информацию из локальных баз данных всех магазинов затянуть к себе. Мы сделали систему, которая собирает их в один центральный Oracle в ЦОДе, добавили репликации, и все заработало. Объем получился не такой уж большой для Oracle — все переваривается. У нас есть еще несколько инстансов в Oracle, которые хранят данные, мастер-данные, данные персонала и так далее. Есть MS SQL, лежащие под 1С, и кафки, через которые общаются и передают информацию на фронт наши бэк-офис системы. Так мы избавились от широкой географии. Когда мы обогатились данными, то решили строить пилот. Взяли самый популярный инструмент в области инженерии, Excel, и затянули все в него. Агрегировали сырые данные и накидали несколько отчетов. Апробировали новый рабочий инструмент и получили следующие выводы: по одному магазину мы считаемся примерно 90 минут; время подготовки одной гипотезы (то что проверяет эксперт на предмет наличия и отсутствия фрода) примерно 1 минута; обработка результатов порядка 15-20 минут. Решение получилось рабочее, но медленное. Чтобы обработать 500 магазинов, нужно примерно 750 часов. Мы такое не любим. Подумали, у нас же есть Data Lake и еще часть данных, и пошли в первую оптимизацию. Выделили на входе, что у нас есть несколько разнородных источников данных: Кафки, MS SQL, Oracle и так далее. Данных много, поэтому мы хотим считать не по магазину, а по всей сети. На выходе мы хотели посчитать на всех сторонах дополнительные атрибуты. Затягивать на стороне Data Lake, обогащать какой-то информацией и отдавать витрину непосредственно пользователям. Сделали! Открылись следующие минусы. Так как данные сильно связаны для фродов, не все из них получается просчитать на стороне систем-источников. Пришлось их затягивать к себе. Из-за этого их, во-первых, задублировали на системах-источниках, а, во-вторых, на Data Lake, и считались на двух плечах. Самым большим минусом этого решения было то, что оперативные системы, в которые мы ходили, больше рассчитаны на OLTP нагрузку, а мы вешали на них OLAP-нагрузку по расчету данных. Но у инструмента были и плюсы. Мы больше не заставляли эксперта анализировать сырые данные. Мы всё считали у себя и предоставляли ему готовые данные. Поэтому ускорили обработку с 750 часов по всей сети до 6 часов. Тогда мы думали, что ушли от Excel, но пользователь привык с ним работать, и отучить его за один шаг было невозможно. Был достигнут промежуточный результат, оптимизация удалась, но не везде. Надо было избавиться от OLTP нагрузки в бэк-офис системах, которые рассчитаны на OLAP-нагрузку. И наоборот – от OLAP-нагрузки в OLTP системах. В изначальном решении мы просто затягивали себе все данные в Data Lake, и уже там их обрабатывали. А чтобы брать гипотезы так, как нам нужно, а не за определенный долгий промежуток времени — надо было делать масштабирование. Начали, как мы подумали, с самого простого. То есть, выделили интеграции — взяли готовые инструменты типа sqoop, flume и прочих. Попытались натравить их на реляционки и через них загрузить всё себе. Получилось так себе. И сделали следующее решение: поделили весь процесс на два плеча. Первое — притворяемся OLTP сессией, когда ходим в реляционную базу данных и загружаем всё в Кафку. Все потоки направили в Кафку, а из нее в параллель с парком начали вычитывать и складывать в ходу. При этом не нужна отказоустойчивая Кафка, у нас была реляционка, из которой мы могли, если что, переподнять. Решение получилось хитрое, но работало довольно быстро, и все потоки оркестрировалось с помощью Airflow. Столкнулись с проблемой, что не все системы готовы отдавать инкременты по данным, и решили не изобретать ничего нового, а взяли лямбда-архитектуру и натянули ее на инкремент. То есть, мы взяли данные за предыдущий день, лог изменения за текущий батч, накатили, определили, какие дни обновились в логе изменений, и прокатили его дополнительно на всю остальную таблицу. У нас получилось, что внутри Data Lake примененный инкремент. Прикольно, но получился вот такой даг. Поэтому когда есть возможность не писать инкремент на стороне Data Lake, не пишите.  Мы сделали интеграции и смогли сформировать слой сырых данных. Получили примерно 30 сущностей, очень близких к четвертой нормальной форме. Партиционировали их по дате, потому что расчеты шли в рамках даты, либо в рамках диапазона дат. У нас получилось всего 10Gb в день в сжатом виде при одной реплике. Это кажется мало, но если анализировать на 3-4-5 месяцев в глубину, то уже не так мало. В интеграциях ускориться не получилось, только реализовать страшный инкремент. Поэтому, чтобы ускориться, пошли анализировать гипотезы, которые нам предоставили эксперты, и выделили общие блоки. Их взяли и вынесли в слой предагрегатов и начали считать отдельно, после того, как мы загрузили данные, но перед тем, как считать гипотезу. Общие блоки — это  атрибуты на чеках, дополнительные активности сотрудников, риски на операциях. Так получилось поранжировать различные аналитические функции, которые строятся на различную глубину. В принципе, весь слой предагрегатов у нас получился такой, что мы считаем агрегационные, аналитические оконные функции на определенную глубину с определенной широтой. И тем самым достигается промежуточный слой, который используется в дальнейших гипотезах. Примерно 80% гипотез, как оказывается, можно покрыть SQL. Это второй по популярности инструмент в области дата инженерии. Гипотеза собирается очень просто. Когда у нас есть вся дополнительная информация внутри Data Lake, мы просто выбираем данные из предагрегатов. Потом обогащаем их данными из справочников. Рассчитываем дополнительные атрибуты специфичные для конкретной гипотезы и по эвристикам помечаем флагами фрода ту или иную строку. После сбора типовой гипотезы — собираем решение. Проверяем по сенсорам, что источники необходимые для предагрегатов, собраны, и можно считать слой непосредственно уже предагрегатов. А дальше считаем гипотезы, которые зависят от тех или иных слоев предагрегата. В итоге от этой оптимизации мы получили: Мы реализовали свои инкременты и батчи, многослойную архитектуру, выделенную в сырые данные, слой предагрегатов и слой гипотез. Получилось, что гипотезы ускорились за счет предагрегатов. Мы ушли от жестких временных границ, больше не завязаны на конкретные тайм-слоты, а используем сенсоры. Появилась возможность смотреть какие были рассчитаны гипотезы, какие были фроды, и на этой основе анализировать и делать выводы. И, наконец, пересадили пользователей с Excel в SAS. Конечно, все зависит, от конкретного потока, но в среднем по ресурсам получилось следующее: Теперь самые интересные примеры. Они направлены на разные области деятельности. Первый пример – это антифрод на кассе, когда кассир возвращает товар, который ранее пробил, проводит товар со своей скидкой, а разницу кладет себе в карман. Есть такие замечательные фродовые операции, которые проверяют гипотезу фрода и получается простая визуализация. У нас есть список магазинов и «светофор». Цветами обозначены возможные фродовые операции. Красные — скорее всего фрод. Если проваливаемся в него, то видим, что у нас есть чек, который был возвращен в 14:20:19 и заново проведен в 14:25:36. При этом цена у него уменьшилась. Это первый фрод, первая гипотеза — это на кассе. Вторая гипотеза касается систем лояльности. В качестве визуализации используем обычную таблицу. Мы можем отфильтровывать, какое количество подозрительных операций нужно проверять. У нас в магазинах операции, не такие частые, как в продуктовых. Поэтому когда одна и та же бонусная карта очень часто применяется либо в одном магазине, либо в магазинах с различной географией за определенный промежуток времени, это подозрительно. То же самое, если один человек покупает 4-5 раз в сутки в течение длительного промежутка времени в одном и том же магазине. Это надо проверять. Ни для кого не секрет, что во многих компаниях есть система KPI для сотрудников. Гипотеза состоит в том, что продавцы подменяя друг друга, оформляют заказы на коллегу, который еще не выполнил свой план продаж. Поэтому, здесь мы уже анализируем источник данных, относящийся к персоналу, проверяем их рабочие часы, чеки и на кого они были оформлены. Получается, что некоторые сотрудники в нерабочее время более продуктивны, чем в рабочее. Ка на примере, 25 операций в рабочее время — против 391 операции в нерабочее время. После обнаружения фрода инициируются дополнительные проверки службы внутренней безопасности, либо проводится внеплановая инвентаризация. Когда фрода касается бонусных карт, мы их блокируем, чтобы предотвратить дальнейшие потери. Применяются различные административные воздействия. Теперь можно подвести итоги. Мы убрали дублирующую нагрузку на внешние системы. OLAP-нагрузки в OLTP системах победили тем, что написали свои инкременты и сделали регулируемую поточность на забор данных. Мы все загрузили внутрь Data Lake и за счет добавления многослойности добились расширяемого решения. Стало можно различные слои менять по требованию, а не единым модулем. За счет слоя предагрегатов сократили время расчета и ускорились с 6 до 2 часов. В среднем на обработку одной гипотезы от момента, когда ее придумал эксперт, до внедрения апробации на фроде у нас проходит от 3 до 5 дней. Добавим немного цифр. В абсолютных, конечно не получится, поэтому поговорим о процентах. Примерно 75-80% фродовых операций, высвечиваются в рамках системы антифрода. Гипотезы, которые придумал эксперт, действительно есть в жизни, и мы их отлавливаем. 15-20% недостач в магазинах действительно подтвердились фродом. Мы выяснили, что программа лояльности, как ни странно, самая атакуемая система. У нас по ней сейчас порядка 30 гипотез. И самое главное – почему без дата-сайнса? Потому что у нас есть те самые эксперты, которые знают поведение людей. Они делают эвристики, помогающие нам в выделении фродов. Поэтому и без дата-сайнса. У нас еще много областей, которые не покрыты фродами. Есть этап, на котором подключаются административные ресурсы, либо проверяющие службы. Есть идея подключить их к антифродам, чтобы был доступ либо к записям, либо к конкретной записи видеокамеры, либо непосредственно к сырым данным, которые необходимы для разбора конкретных ситуаций. Мы активно переезжаем на Clickhouse для визуализации и табло. Просто потому, что это удобно, быстро, и мы любим ускоряться. Там будет сильно быстрее, мы уже попробовали. У нас порядка 40 гипотез в бэк-логе, которые еще предстоит реализовать. И есть авантюрная затея. Так как мы все-таки хотим попробовать дата-сайнс и у нас есть эвристики, хочется сначала генерировать их с помощью дата-сайнса, а уже потом давать экспертам на проверку. Еще больше самых актуальных материалов будет на конференции HighLoad++ 2022 - 24 и 25 ноября в Москве. Посмотреть программу докладов и приобрести билеты можно на официальном сайте конференции.