Привет! Меня зовут Павел Голов, я инженер в юните Communications. Наш юнит развивает функционал взаимодействия пользователей на Авито.
В феврале 2022 года произошло большое событие для нашей команды — мы закрыли все объявления частных пользователей защитными номерами. О том, какой путь мы прошли, я хотел бы рассказать в этой статье.
Что такое защита номера
Сначала быстро разберёмся, что же такое защита номера, как она работает и зачем нужна пользователям.
Защита номера — бесплатная услуга для частных пользователей. Если вы продаёте на Авито, то при создании или редактировании объявления могли наблюдать такое предупреждение:
Когда продавец размещает объявление, мы прикрепляем к нему дополнительный виртуальный номер, который и показываем покупателям, решившим связаться с продавцом. Когда покупатель звонит на этот виртуальный номер, мы переадресуем звонки на реальный номер продавца.
В чём цели защиты номера и зачем она продавцам?
Настоящий номер продавца не попадает в базы злоумышленников. Продавать на площадке становится безопаснее, и можно не беспокоиться, что после закрытия объявления будут названивать спамеры.
Пользователю нельзя написать в сторонний мессенджер или отправить СМС с поддельными ссылками, что делает жизнь злоумышленников труднее. Сообщения на Авито при этом приходят как и раньше.
Мы фильтруем звонки на защитные номера от спама. Система блокирует значительное количество нецелевых вызовов, и продавцы на них не отвлекаются.
Историческая справка
В 2018 году на Авито появился первый прототип защиты номера для частных пользователей.
С точки зрения user-story, защита номера представляла из себя два сценария:
Показ номера при просмотре объявления.
Звонки на защитные номера.
Рассмотрим, как эти сценарии были реализованы изначально.
Показ номера при просмотре объявления. При создании объявления сервис защиты номера асинхронно получал событие из Databus — нашего брокера сообщений, основанного на Kafka. Если продавец включал защиту номера телефона, мы выбирали один из свободных и доступных нам виртуальных номеров и привязывали его к созданному объявлению. Виртуальный номер был привязан к объявлению на протяжении всей его жизни, мы отвязывали виртуальный номер после закрытия или удаления объявления.
Когда покупатель заходил на страницу объявления, он видел кнопку «Показать телефон». При нажатии на эту кнопку отправлялся запрос на бэкенд к сервису защиты номеров. Далее мы проверяли, привязан ли к этому объявлению виртуальный номер: если да — показывали покупателю защитный номер, если нет — показывали настоящий номер продавца.
Звонки на защитные номера. Покупатель видел защитный номер на странице объявления, набирал его на телефоне и звонил. В первую очередь звонок доходил до оператора сотовой связи, владеющего виртуальным номером. Оператор понимал, что этот номер закреплен за Авито и отправлял запрос в наш API.
Запрос приходил в микросервис обработки звонков. На этом этапе мы, используя алгоритмы машинного обучения, определяли, является ли звонок спамом. В случае, если звонок определялся как спам, оператору отправлялась команда сбросить звонок. Если звонок — не спам, мы узнавали, привязан ли виртуальный номер, на который пытаются позвонить, к реальному номеру продавца. Если активная связка была, мы отвечали на запрос оператору номером телефона, на который нужно переадресовать текущий вызов, и звонок доходил до продавца.
На практике схема звонков выглядела немного сложнее, но я оставил самую важную часть, чтобы не перегружать вас лишней информацией.
Масштабирование и трудности
Первый прототип был запущен для частных пользователей категорий «Недвижимость» и «Авто», что покрывало примерно 20% частных пользователей Авито. Прототип хорошо себя зарекомендовал, и мы приняли решение о раскатке защиты номера на всех частных пользователей.
Прототип рабочий, казалось бы, просто масштабируем его на все категории Авито, и дело в шляпе! Но всё немного сложнее: как я описал выше, мы прикрепляли виртуальный номер к каждому объявлению пользователей для сохранения атрибуции вызовов. И эта связка была активна до тех пор, пока было активно само объявление.
Сейчас на Авито больше 90 миллионов активных объявлений, и эта цифра постоянно растёт. Часть объявлений принадлежит профессиональным пользователям, и тем не менее для закрытия всех объявлений частников нам потребовались бы десятки, а в перспективе и сотни миллионов виртуальных номеров. Это выливалось бы в огромные затраты, чего мы хотели избежать.
Решение: динамический защитный номер
Так как виртуальных номеров у нас в десятки раз меньше, чем активных объявлений, пришлось подумать, как закрыть все объявления имеющимся количеством номеров.
Мы провели ряд аналитических исследований, которые показали, что покупатели совершают ~98,2% первичных звонков в течение первых двух часов с момента получения номера при просмотре объявления.
Что касается звонков, когда покупатель перезванивает продавцу по тому же номеру, то ~99,7% звонков совершается в первые 14 дней после первичного звонка.
Опираясь на эти данные, мы построили алгоритм динамической защиты номеров, который стал улучшением прототипа, созданного ранее. Алгоритм основан на следующих тезисах:
Виртуальные номера закрепляются за объявлениями не на весь жизненный цикл объявления, а лишь на определённое время.
В каждом регионе РФ мы выделяем ограниченный пул виртуальных номеров.
Виртуальные номера постоянно ротируются между объявлениями.
User-story в новом алгоритме остаются теми же, что и в прототипе, но реализация отличается. Рассмотрим каждую историю подробнее.
Показ динамического защитного номера
Теперь виртуальные номера закрепляются за объявлениями лишь на определённый срок и постоянно ротируются между ними. Как это работает и как мы определяем, какой виртуальный номер нужно показать при запросе покупателя?
Когда покупатель нажимает кнопку «Показать телефон» на странице объявления, запрос по-прежнему идёт в микросервис защиты номеров. Если к объявлению уже привязан виртуальный номер, то мы просто его и показываем. Если же у объявления нет активной привязки, то мы:
смотрим на пул виртуальных номеров конкретного региона РФ, где зарегистрирован реальный номер продавца;
ищем в пуле номер, который не показывался на сайте дольше всех и при этом показывался более двух часов назад.
После того, как такой виртуальный номер найден, мы отвязываем его от предыдущего объявления, привязываем к текущему и показываем покупателю. Всё происходит за десятки миллисекунд.
Примеры ротации защитных номеров
Рассмотрим на простых примерах, как работает ротация номеров. Пусть у нас есть пул номеров, в котором всего 1 виртуальный номер. Как я говорил, виртуальные номера сгруппированы по регионам РФ. Прямоугольниками на примерах отмечены временные отрезки, в течение которых покупатели могут дозвониться по полученным номерам телефонов:
В первом примере у нас всего 1 продавец, у которого 1 объявление. В момент t1 покупатель получает номер телефона на карточке объявления. С этого момента к реальному номеру продавца прикрепляется виртуальный номер из пула и начинается отсчёт времени, в течение которого покупатель может дозвониться продавцу по полученному виртуальному номеру. Сейчас это 2 часа.
В момент t2, при условии, что никакой другой покупатель не запрашивал номер телефона с этого объявления, виртуальный номер перестаёт переадресовывать звонок на номер продавца. Если же до момента t3 этот виртуальный номер ещё не перешёл никакому другому продавцу, а какой-либо покупатель снова запросил номер телефона на объявлении в момент t3, тот же виртуальный номер снова становится «активным» и переадресует вызовы на реальный номер нашего первого продавца.
Отмечу, что каждый просмотр телефона на объявлении продлевает время, в течение которого мы переадресуем звонки с текущего виртуального номера на реальный номер продавца.
Второй пример сложнее: теперь у нас есть 2 продавца, каждый со своим объявлением. В момент t1 покупатель запрашивает номер телефона на объявлении 1, в результате чего к реальному номеру продавца 1 прикрепляется виртуальный номер из пула. В момент t2 время переадресации заканчивается, и закреплённый номер становится неактивным.
Пусть в момент t3 покупатель запрашивает номер телефона на объявлении 2, которое принадлежит другому продавцу из того же региона РФ, что и у продавца с объявлением 1. Так как регионы совпадают, виртуальные номера для них берутся из одного пула. Единственный виртуальный номер из текущего пула в этот момент закреплен за объявлением 1, но, так как время переадресации для этого номера уже истекло, он переходит на объявление 2. С этого момента виртуальный номер переадресует вызовы на реальный номер продавца 2. В момент t4 время переадресации снова заканчивается, номер становится неактивным и остается закреплённым за вторым продавцом.
Стоит отметить, что если бы во втором примере время переадресации виртуального номера на объявление 1 ещё не истекло, когда произошёл запрос номера на объявлении 2, случилась бы ошибка отсутствия свободных номеров в пуле. Мы постоянно следим за тем, чтобы в пулах всегда было достаточное количество виртуальных номеров для обеспечения работы алгоритма. Для этого в моменты перехода номера от одного продавца к другому мы пишем временную метрику, которая вычисляется как:
Площадка объявлений
Станьте первым!