Upload
badoo-development
View
1.126
Download
8
Embed Size (px)
DESCRIPTION
Каждый день на badoo.com пользователи просматривают порядка 100 миллионов профилей других юзеров. Мы храним счетчики и полную историю посещений за последние 90 дней, с некоторой агрегацией - это около 5 миллиардов ивентов. Система обрабатывающая этот поток данных создана давно и пережила несколько инкарнаций, становясь все ближе к базе данных. В какой-то момент мы решили перестать изобретать велосипед, отказались от демонов на C+sqlite, не стали делать на mysql-ях, редисах и мемкешах, а взяли и запилили на Tarantool. Рассказываем почему Tarantool, как шардим, реплицируем (все просто) и как плавно это дело внедрили на живой системе без downtime.
Citation preview
Tarantool в BadooХранение истории посещений
~60k php req/sec + 200k media req/sec
Badoo
215M пользователей в 200 странах
переводы на ~50 языков
~500k req/sec к внутренним сервисам
~3000 серверов
2.5 датацентра
На сайте
Профиль
Переходят !- из поиска - из чатика - из писем и т.д.
На сайте
Посетители
счетчики с фильтрацией
новый хит
список хитов
На сайте
считаем популярность
Как устроен хит
to from
timestamp
is_visible
source
is_new
поиск, чатик, encounters, письмо, etc. (bitmask)
юзер спрятал хит из списка?
юзер уже видел этот хит?
Задача
Цифры
день
всего 5000M100M
Данные (хиты) - храним историю за 90 дней
чтение
запись 35%65%
Запросы - ~7k rps на площадку
Задача
Начало - 2003
> придумали и сделали основные фичи
> храним историю за 30 дней
одна площадка
“патчик” в мемкеш, пишет текстовые снапшоты
!
История
hitd - 2008
> появилась еще одна площадка
> нужно экспортировать данные в базу
! медленно загружаемся из текстового снапшота
пишем логи - для репликации и экспорта
сделали снапшоты бинарными
История
hitd - 2009
> количество пользователей выросло в 7 раз
> хотим историю за 90 дней вместо 30
расшардили, сделали по три машины на площадку
! кончилась память
История
hitd - 2010
> нужно добавить поля в структуру хита
хотим простую эволюцию схемы данных!
решили попробовать sqlite
История
hitd - 2010+
С ростом базы - sqlite перестает справляться
hitd
апдейты
aggregator
основная база replace/insert/update
syncer на другую площадку
История
hitd - 2013
держим апдейты и базу на разных дисках
! рестарт требует “прогрева базы” cat /path/to/db > /dev/null
! не успеваем доклеивать апдейты в базу растет WAL, рекорд - 27gb
копируем базу на ramdisk и делаем repair :(
История
Что хотим (2014)
История
> решить проблемы с нехваткой iops
> упростить сетап и обслуживание
> простоту программирования
> возможность влезть и “пропатчить” если нужно
“достаточно” performance (latency ~1ms / 10k rps)!
Tarantool
Инструменты
MySQL
Инструменты
+ переносим логику в php, данные - в mysql
+ данные пользователей уже расшардены
выжмем достаточно скорости
+ готовые админские инструменты
~ нужны транзакции, никакого handlersocket
- непредсказуемое время ответа–
?
Redis
Инструменты
+ быстро, ибо in memory
+ можно сделать lua api ( слегка неудобно)
~ неудобно делать удаление старых данных
~ сохранение на диск можно сделать лучше
+ хорошая документация и community
Tarantool
Инструменты
+ быстро, ибо in memory
+ lua - только на сервере, обновление кода на лету
+ есть документация и дружественные девелоперы
+ отличная сохранялка на диск
~ напряженка с php коннектором
здесь должна быть фотка
Кости Осипова
Мега фичи
Инструменты
обновление lua кода без рестарта
фоновые “процессы” - удаляем старые данные
произвольное количество полей в tuple
не только key-value, индексы по нескольким полям
Данные и запросы
uid_to uid_from timestamp sourceis_visible is_new
Реализация
add - добавить или обновить в радиусе 30 мин
× del - удалить по uid_to или uid_from
+
… list - постраничный список хитов с фильтрацией
✂ cleanup - зачистить хиты старше 90 дней
∑ counters - сколько новых хитов? за последний час?
Попытка #1
uid_to uid_from timestamp sourceis_visible is_new
unique
index index
Реализация
index
+50% служебные данные для каждого tuple
+200% копии данных в индексах + служебные данные
- нужно 300 гигов памяти… опять:(
120gb исходные данные
Попытка #2
uid_to 0 1 42 3 ∞
uid_from timestamp sourceis_visible is_new
Реализация
X записей -> одна, со списком из X элементов
всего один индекс, из одного поля
~ нужно бегать по списку для поиска нужных хитов
~ поддерживаем уникальность ручками
Нюансы
uid_to 0 1 42 3 ∞
uid_from timestamp sourceis_visible is_new
Реализация
tuple[n] - честно бежит по списку, т.е. O(n)
нужно кешировать результаты запроса count
~ если хитов очень много - разбиваем список на части
Репликация
Реализация
> нужна полная копия данных на каждой площадке
> нужен умный merge хитов на приеме
делаем свою на php + lua stored procedures
! встроенная репликация не подходит
(кроссплощадка)
tnt
Прага
tnt
Майами
x3 x4
php Берем по-многу за разЗаливаем по одной
~8500км ~140ms latency
Реализация
lua процедуры repl_load, repl_list, repl_count
php карта + транспорт
! экономим latency, скачивая пачками на практике latency ~1500ms при ~1000 записей/сек
Шардинг
сервера
3x
ноды
x24
Реализация
! хотим использовать все процессоры
делаем мелкие ноды, удобно в обслуживании
! датасет не влезает на одну машину
но не слишком мелкие, т.к. больше random io
Dark launch
импортируем часть данных в tarantool
включаем постепенно для части пользователей
пользователи ничего не заметят, а мы потестируем
Выкладка
измеряем, оптимизируем - повторяем
hitd
апдейты
aggregator
основная база replace/insert/update
syncer на другую площадку
Старая система выглядит так
Выкладка
php
hitd
апдейты копятся
aggregator
основная база
syncer на другую площадку
Этап #0
Выкладка
php
hitd
основная база вливаем в tarantool
Этап #1
aggregator
syncer на другую площадку
Несколько часов
Выкладка
php
tarantool
накопленные апдейты
включаем репликацию на другую площадку
~25 минут
Выкладка
Этап #2
заливаем
tarantool
Выкладка
Этап #3
продолжаем заливать
phpвключаем запись
hitd
чтение и запись
tarantool
Выкладка
Этап #4
продолжаем заливать
php включаем чтение и запись
?