Привет! Сегодня поделюсь с вами статьёй, написанной по мотивам моего доклада на Tarantool Meetup. Маленькая история, почему в компании Мамба стали использовать Tarantool. Почему мы занялись репликацией из MySQL в Tarantool? Первая причина в том, что в какой-то момент нужно было начинать переходить на MySQL 5.7, но в нём отсутствует handler socket, который активно используется на наших серверах в MySQL 5.6. Мы даже связались с командой Percona, и они подтвердили, что 5.6 — это последняя версия c handler socket.
Вторая причина — мы начали пробное использование Tarantool, и скорость работы нам понравилась: мы просто сравнили memcache и Tarantool как key/value-хранилище, получив прирост производительности — с 0,6 до 0,3 мс на одинаковом железе. В относительном выражении Tarantool в два раза быстрее, в абсолютном выражении это не так круто, но всё же. И третья причина — желание полностью сохранить текущую структуру: есть MySQL Server Master и его Slave’ы, ничего переписывать не хотелось, хотелось оставить максимально близко к той архитектуре, что есть сейчас. Как бы нам сделать так, чтобы вместо Slave’ов MySQL 5.6, на которых используется handler socket, применить что-то другое и полностью не переписывать всю огромную архитектуру?
Мы узнали, что у команды Mail.Ru Group есть репликатор, который они написали для своих целей. Это была изначально их идея — реплицировать данные из MySQL в Tarantool. Мы попросили у них код, который нам пришлось переделать, потому что он работал с MySQL 5.1 и Tarantool 1.5, а не 1.7. Репликатор использует libslave, opensource-разработку для чтения событий с сервера MySQL Master. Репликатор, полностью собирается статически и не использует системных mysql lib.
Ограничения данной репликации
Во-первых, bin log’и на Master’е должны быть только Row-based. Ни Statement, ни Mixed не подойдёт, только Row-based. Во-вторых, репликатор — это не некий модуль в Tarantool, а отдельный Daemon. То есть этот инструмент в принципе никак не связан ни с Tarantool, ни с MySQL. В-третьих, если вам нужно, допустим, чтобы у одного Master’а было 10 Slave'ов, то придётся запускать 10 Daemon’ов. Один репликатор может реплицировать только в один Tarantool. И в-четвёртых, репликатор не станет работать с MariaDB. Мы его попробовали и на 5.6, и на 5.7, но это будет либо сборка от Oracle, либо сборка Percona, мы исторически используем версию Percona. У MariaDB протокол репликации изменён.
Как работает репликация
Ни MySQL не знает о Tarantool, ни Tarantool не знает о MySQL. Репликатор вычитывает bin log’и с MySQL Master, и всё это записывается в Tarantool.
Что умеет делать репликатор?
При запуске репликатор полностью забирает данные с Master’а, основываясь на конфиге, в котором указано, какие базы/таблицы нужно реплицировать, т. е. для запуска достаточно просто взять тарантул с пустыми спейсами, что очень удобно.
Вы как системный администратор должны понимать, работает ли вообще репликация, какой bin log сейчас читает репликатор, какую его позицию, всё это, конечно же, есть. Есть отдельный Space, в котором всего три значения: имя bin log’а и считываемая в данный момент позиция, т. е. существует маленький аналог привычного всем Show slave status.
10.5.2.17:5000> box.space.ReplicationLog:select() [0, 'db-bin.024218', 916925355]
После внедрения репликатора мы развернули семь экземпляров Tarantool, которые работают только на двух серверах, потому что один инстанс Tarantool не может утилизировать все ядра машины. Немножко напомню архитектуру тарантула, один инстанс умеет потреблять от трёх ядер: одно ядро и более — сеть, строго одно ядро — транзакционная часть, строго одно ядро — работа с wal-файлами.
Нагрузка
Запустили репликатор, и нагрузка на MySQL Slave’ах, на которых работал handler socket, резко провалилась — практически в ноль.
После этого я попробовал вместо текущих восьми MySQL slave серверов оставить только один, уже один сервер полностью держал нагрузку. Мы не отказались полностью от MySQL slave серверов, мы оставили на них те запросы, которые работают без handler socket, а значит, можно полностью перейти на 5.7. В результате мы сэкономили минимум семь серверов, накопители Enterprise SSD, которые работают в них, место в стойке, электричество, деньги.
Что можно сказать интересного про время ответа? В компании Мамба есть свой opensource-продукт BTP, вот его графики.
У handler socket очень необычный API. Надо сначала вызвать метод Connect, потом метод Open Index, потом метод Execute. Суммарное время всех трёх методов представлено на иллюстрации: длительность выполнения запроса на handler socket могла достигать 1 секунды.
А теперь всё то же самое, но уже с Tarantool’овскими серверами, куда реплицируется с Master та же самая база:
Причина очень проста: Tarantool — это In-Memory база данных, а MySQL работал на SSD, под buffer pool size было выделено памяти меньше, чем размер базы данных. Здесь же у нас полный In-Memory, причём даже во всех instance, выключены wal-файлы, т. е. нет работы с диском, только память, есть отдельные инстансы, на которые не идут боевые запросы, там wal-файлы включены и с них делаются snapshot’ы.
Не велосипед ли?
Если бы обо всём этом рассказывал кто-то другой, я бы сам задал вопрос: «А не изобрели ли вы велосипед? Вы из MySQL что-то реплицируете в Tarantool. Да, вы думаете отказаться от handler socket, потому что хотите перейти на 5.7. Но для чего это нужно? Если не потянет без handler socket, то просто поставьте чуть больше серверов. Если вам обязательно нужна In-Memory база данных — можно либо сделать Heap’овские таблицы, либо перенести БД-файлы в TMPFS, сделать симлинки, и все таблицы опять окажутся в памяти, всё будет прекрасно работать»
Но это не так.
Главная особенность репликатора вот в чём. Допустим, в той базе данных, которую мы реплицируем и которая лежит на Master’е, находится порядка сотни таблиц, но на Slave все таблицы ни к чему, нужно ограниченное количество таблиц, всего семь. Соответственно, не хочется тратить ресурсы на репликацию лишних данных. В MySQL можно указать, что мы реплицируем эти семь таблиц. Но предположим, что в семи таблицах 120 полей, а для запросов, которые используются только на Slave’ах, нужно лишь 21 из 120 полей. В MySQL я всё равно буду реплицировать все семь таблиц, которые в нашем случае занимают в памяти порядка 80 Гб. А в репликаторе можно указать только набор полей этих таблиц, т. е. вместо 120 полей из семи таблиц реплицируется 21 поле, и в Tarantool они занимают 20 Гб.
Ещё одна особенность репликатора: на самом деле все поля из этих семи таблиц сливаются в один Space, т. е. их можно выбирать одним запросом, без join.
Что на выходе?
Tarantool реально быстрый. Я показал графики, где он демонстрировал преимущество перед MySQL — вплоть до троекратного.
Репликация в Tarantool, которая у нас получилась, работает быстрее, чем в MySQL, и вот почему. Когда мы её запустили, первый вопрос, который сразу возник, — консистентна ли наша репликация. Мы написали очень простой PHP-скрипт, который берёт активную аудиторию за месяц и делает сверку на MySQL master и Tarantool slave. Иногда получалось так, что этот скрипт выгрузки активной аудитории брал пользователя, который зарегистрировался меньше секунды назад. На MySQL Slave его ещё не было, а в Tarantool он уже был, хотя на MySQL’овском Slave в Show slave status отставание всегда нулевое, там у нас никогда не бывает, чтобы Slave отставал. Но при этом в Tarantool информация попадает гораздо быстрее. Опять же, потому что Tarantool — полностью In-Memory база.
Преимущества Tarantool
Что будет, если вытащить из сервера MySQL кабель питания, а потом запустить сервер опять? При старте начнётся процесс InnoDB Recovery, и в итоге база восстановится. Но у нас пару раз случалось, что в какой-то момент контроллер переставал писать на диск адекватную информацию, сервер падал в kernel panic по причине сбоя контроллера, процесс innodb recovery после ребута заканчивался Core Dump. В Tarantool настолько удачно продуман механизм write-ahead-log, что даже если по каким-то причинам контроллер записал в wal-файл какую-то ерунду, из-за чего Tarantool не поднимается, то вы просто сносите wal-файл. Или открываете файл и убиваете из него данные записи построчно до тех пор, пока Tarantool не запустится. Причём вы можете указывать желаемое количество транзакций, которые будут записываться в wal-файле, хоть по одной транзакции. Подчеркну, что пример с MySQL, который я привел выше, — это именно последствия аппаратного сбоя сервера, при нормальных условиях innodb recovery отработает как часы.
Также понравилось, что Tarantool очень простой. Там всё хорошо понятно, что и как делать. Допустим, выходит какая-то новая версия MySQL, мы обновились, а он не запускается. Лезешь в Error Log и понимаешь: «Ого! Какие-то настройки my.cnf уже deprecated». Открываешь документацию и видишь, что вместо этого появилась ещё куча настроек, теперь тебе надо разобраться, как написать новый my.cnf для повышения производительности. В Tarantool ничего этого нет. Здесь всё просто и понятно, минимум настроек.
Следующее, что всем нам понравилось при работе с Tarantool, — это классное сообщество. В Telegram есть чатик, куда можно получить приглашение от Дениса Аникина, где отвечают на твои вопросы и оперативно делают bug fix.
Snapshot’ы в Tarantool сделаны здорово. Этот механизм работает с безумной скоростью — 800 Мбит в секунду, может быть, даже 1 Гбит. Пишется последовательно в один файл. Тут не нужны какие-то супердиски, всё работает очень быстро и грамотно даже на самых дешёвых SATA. Поднятие snapshot’а 20-гигабайтной базы занимает не более пяти минут. Я проверял, и в MySQL у меня получалось гораздо медленнее.
Недостатки
Первый, самый большой недостаток — в Tarantool индексы case sensitive, это очень неудобно, особенно когда начинаешь использовать Tarantool после MySQL.
Второй недостаток — это консоль. Как в MySQL, например, понять, что репликация работает? Вы набрали два раза Show slave status и увидели, что циферки бегут. При этом в консоли MySQL Show slave status заполнится не два раза, а один. Если вы даже сто раз подряд заполните Show slave status, то всё равно в History MySQL консоли запомнится, будто вы сделали это только один раз. Но в Tarantool можно попробовать сто раз Enter ввести, и у вас в консоли будет сто Enter, вы замучаетесь вверх нажимать, чтобы прокрутить до того, что было до многократного нажатия.
Вывод
Tarantool действительно хороший продукт, который можно применять. Да, в нём есть свои минусы, но продукт развивается. Надеемся, что после того, как в нём появилась репликация из MySQL, он будет развиваться ещё быстрее. Самое главное достоинство Tarantool, конечно же, его скорость. Продолжение следует.
Автор: Mail.Ru Group