Миссия компании Badoo — помочь людям найти новых знакомых по всему миру. Для этого на нашем сайте существует множество инструментов и сервисов, позволяющих пользователю выделиться среди других и повысить свою популярность. Одним из них является сервис Spotlight, в русской версии — “Центр внимания”. Он присутствует почти на всех страницах нашего сайта и представляет собой блок из 12 фотографий. Концепция сервиса такова, что пользователь видит фотографии ближайших к нему географических соседей. Он может отправить заявку, чтобы среди них появилась и его фотография на первом месте слева. Тогда все остальные сдвигаются вправо, а последний выбывает.
Как устроен этот, на первый взгляд, нехитрый сервис, читайте далее...
На сегодняшний день Badoo поддерживает более 30 языков, включая языки с направлением письма справа налево (RTL языки: иврит, арабский и др.). Эта поддержка не ограничивается лишь переводом текстовых материалов, а включает в себя еще и оптимизацию элементов интерфейса. Наши веб-технологи постарались, чтобы Spotlight не стал исключением. В случае с RTL языками он отражен зеркально, а фотографии движутся справа налево.
Для каждой страны определяются центральные города, к которым примыкают все остальные, образуя округа. Центральными городами становятся те, чье население превышает заданный порог, определяемый эмпирическим путем для каждой страны. Округа обычно пересекаются между собой, и пользователь из одного округа может попасть одновременно в несколько других. Согласно алгоритму изначально осуществляется поиск ближайшего округа, вычисляется расстояние до него — D. Затем мы находим все остальные округа, расстояние до которых не более D + X км, что также настраивается индивидуально для каждой страны.
Некоторые центральные города задаются вручную, например на островах. Округа для всех населенных пунктов выбираются исключительно в рамках стран, в которых они расположены. Город на границе не попадет в округ чужой страны, хотя технически нам ничто не мешает делать это в рамках каждого континента. Ниже вы можете увидеть визуализацию округов Франции:
С технической стороны основной частью сервиса Spotlight является программа на С — демон, который принимает заявки, распределяет по округам и осуществляет ротацию пользователей. На наших серверах одновременно работает несколько демонов Spotlight, распределяя между собой нагрузку. Каждый из них отвечает за свой набор стран и группу пользователей определенной сексуальной ориентации. Последнее является еще одним достоинством сервиса, т.к. пользователи видят только тех, кто им интересен, а не всех подряд. В качестве примера ниже приведена таблица:
Молодой человек из Парижа, который хочет познакомиться с девушкой, попадет на сервер №1. При этом в блоке фотографий он будет видеть мужчин и женщин из столичного округа с такими же интересами.
Попасть в Spotlight могут только те, у кого имеется хотя бы одна фотография, одобренная нашими модераторами, но мы постарались сделать этот процесс максимально быстрым и незаметным. Даже если пользователь только что загрузил свою фотографию, она отправится на ускоренную внеочередную модерацию. Пройдет не более минуты как он увидит себя на первом месте среди других фото. Если пользователь удалит фото, это сразу же отразится в сервисе — среди всех его фотографий будет найдена первая подходящая на замену. Для всех текущих заявок постоянно проверяется актуальность фотографий и профиля. Например, если пользователь нарушит правила сайта и будет заблокирован, то его заявка будет удалена.
Изначально Spotlight был основан на Memcache, а в качестве постоянного хранилища заявок использовалась база MySQL. Front-end сервиса на JavaScript за обновлениями обращался напрямую к Memcache через специальный модуль для веб-сервера nginx. За обработку заявок полностью отвечали PHP-скрипты, которые обрабатывали очереди в БД и обновляли данные в Memcache. Тогда пользователи группировались исключительно по странам и сексуальной ориентации, поэтому видели людей сразу со всех городов своей страны. Чтобы сделать сервис более быстрым и гибким, а также расширить функционал, было решено написать специальный демон на С.
Одной из интересных задач, которые нам предстояло решить, была балансировка количества мужчин и женщин в Spotlight. Во многих городах мужчины по ряду причин гораздо активнее пользуются сервисом, чем девушки. Нужно было сбалансировать соотношение девушек и молодых людей так, чтобы количество первых было не менее 25%. Для этого ввели приглашения бесплатно воспользоваться сервисом.
На каждой странице, где есть Spotlight и текущий пользователь подходит под определенные требования, мы вычисляем количество свободных мест, недостающих до 25%. Если есть нужное количество свободных мест, мы показываем приглашение пользователю женского пола. Трудность задачи состоит в том, что количество приглашений ограничено (мы не можем одновременно всему сайту показать приглашения), к тому же пользователь может раздумывать некоторое время и впоследствии отказаться от услуги.
Первое, что приходит в голову — проверять при каждом запросе наличие свободных мест. Если они есть, то показывать приглашение. Предположим, что у нас есть 10 мест и мы начинаем приглашать всех подходящих пользователей, которых может оказаться, допустим, 1000 в один момент времени, и все они согласятся. И тогда в следующую минуту пользователи сайта увидят на странице пулеметную очередь из фотографий. Поэтому необходимо вести учет свободных мест и правильно обрабатывать одновременные запросы. Для этого используется Memcache.
Алгоритм следующий:
- При каждом запросе страницы со Spotlight мы получаем список существующих заявок. Берем статистику по количеству пользователей (МЖ), на основании которой определяем количество возможных бесплатных приглашений.
- Если пользователь подходит под определенные критерии, пробуем сразу же занять место в сервисе. Сохраняем не количество свободных, а количество занятых мест, делая инкремент ключа used_slots_<area_id> в Memcache. Таких ключей получается ровно столько, сколько существует доступных округов. Если значение этого ключа больше количества свободных мест, то уменьшаем значение обратно на единицу и не показываем приглашение. Ключ хранится в течение 30 секунд и отвечает, по сути, за частоту балансировки.
- Если удалось забронировать место, показываем пользователю приглашение и ставим ему соответствующий флаг в сессию. Ждем решения пользователя.
- В случае отказа пользователя делаем декремент.
Вполне возможна ситуация, когда пользователь закроет страницу, не совершив никакого действия. В этом случае у нас останется выданное, но не реализованное приглашение. Это не представляет никакой проблемы, поскольку балансировка происходит достаточно часто — как только истекает ключ в Memcache.
Суть сервиса Spotlight как платной услуги заключается в том, чтобы пользователь получил то внимание, за которое заплатил. Чем крупнее населенный пункт, тем больше находится желающих использовать сервис. Но, с другой стороны, выше конкуренция за время, в течение которого фотография пользователя будет находится в самом центре внимания. Сервис не даст фотографии быстро исчезнуть, но и не будет стоять на месте, если заявок слишком мало. Таким образом достигается баланс между потраченными средствами и количеством пользователей, которые смогут найти друг друга и захотят познакомиться.
Александр Treg Трегер, разработчик Badoo.
Автор: