Практические задания по libslave
libslave
представляет собой библиотеку C++ для считывания изменений данных, внесенных с помощью MySQL, а также – опционально – для записи их в базу данных Tarantool. Она выступает в качестве ведомого в схеме репликации. Сервер MySQL записывает информацию об изменении данных в бинарный журнал и передает ее на любой клиент, который запрашивает: «Хочу увидеть всю информацию, начиная с этого файла и этой записи, безостановочно». Таким образом, библиотека libslave
, прежде всего, используется для создания реплик базы данных Tarantool (намного быстрее, чем используя традиционный ведомый сервер MySQL) и для отслеживания изменений данных, чтобы они были пригодны для поиска.
Здесь мы не будем подробно рассматривать библиотеку – информация есть в документации по API. Мы лишь дадим упражнение: минимальная программа с использованием библиотеки.
Примечание
Используйте тестовый сервер. Не используйте боевой сервер.
ШАГ 1: Убедитесь в наличии следующего:
последняя версия Linux (например, Ubuntu версии 14.04 не подойдет),
сервер MySQL версии 5.6 или 5.7 (MariaDB не подойдет),
пакет программ для разработки клиента MySQL. Например, на Ubuntu можно загрузить его с помощью следующей команды:
$ sudo apt-get install mysql-client-core-5.7
ШАГ 2: Установите libslave
.
Рекомендуется источник по ссылке https://github.com/tarantool/libslave/. Загрузки включают в себя только исходный код.
$ sudo apt-get install libboost-all-dev
$ cd ~
$ git clone https://github.com/tarantool/libslave.git tarantool-libslave
$ cd tarantool-libslave
$ git submodule init
$ git submodule update
$ cmake .
$ make
Если система выдаст сообщение с ошибкой со словом «vector», отредактируйте field.h
, добавив следующую строку:
#include <vector>
ШАГ 3: Запустите сервер MySQL. В командной строке добавьте соответствующие коммутаторы для выполнения репликации. Например:
$ mysqld --log-bin=mysql-bin --server-id=1
ШАГ 4: Для целей данного упражнения, предполагаем, что у вас есть:
- пользователь «root» с паролем «root» с правами,
- тестовая база данных «test» с тестовой таблицей под названием «test»,
- бинарный журнал под названием «mysql-bin»,
- сервер с идентификатором 1.
Значения заданы в программе, хотя программу, конечно, можно изменить – посмотреть настройки несложно.
ШАГ 5: Обратите внимание на программу:
#include <unistd.h>
#include <iostream>
#include <sstream>
#include "Slave.h"
#include "DefaultExtState.h"
slave::Slave* sl = NULL;
void callback(const slave::RecordSet& event) {
slave::Position sBinlogPos = sl->getLastBinlogPos();
switch (event.type_event) {
case slave::RecordSet::Update: std::cout << "UPDATE" << "\n"; break;
case slave::RecordSet::Delete: std::cout << "DELETE" << "\n"; break;
case slave::RecordSet::Write: std::cout << "INSERT" << "\n"; break;
default: break;
}
}
bool isStopping()
{
return 0;
}
int main(int argc, char** argv)
{
slave::MasterInfo masterinfo;
slave::Position position("mysql-bin", 0);
masterinfo.conn_options.mysql_host = "127.0.0.1";
masterinfo.conn_options.mysql_port = 3306;
masterinfo.conn_options.mysql_user = "root";
masterinfo.conn_options.mysql_pass = "root";
bool error = false;
try {
slave::DefaultExtState sDefExtState;
slave::Slave slave(masterinfo, sDefExtState);
sl = &slave;
sDefExtState.setMasterPosition(position);
slave.setCallback("test", "test", callback);
slave.init();
slave.createDatabaseStructure();
try {
slave.get_remote_binlog(isStopping);
} catch (std::exception& ex) {
std::cout << "Error reading: " << ex.what() << std::endl;
error = true;
}
} catch (std::exception& ex) {
std::cout << "Error initializing: " << ex.what() << std::endl;
error = true;
}
return 0;
}
Всё лишнее почистили, чтобы можно было ясно увидеть, как это работает. В начале функции main()
есть некоторые настройки, используемые для установки соединения – хост, порт, пользователь, пароль. Затем есть вызов инициализации с именем файла бинарного журнала = «mysql-bin». Обратите особое внимание на оператор setCallback
, который передает имя базы данных = «test», имя таблицы = «test» и адрес функции обратного вызова = callback. Программа войдет в цикл и будет вызывать эту функцию обратного вызова. Посмотрите, как на ранних этапах программы функция обратного вызова выводит «UPDATE», «DELETE» или «INSERT» в зависимости от переданных данных.
ШАГ 5: Поместите программу в директорию tarantool-libslave
и назовите ее example.cpp
.
ШАГ 6: Выполните компиляцию и сборку:
$ g++ -I/tarantool-libslave/include example.cpp -o example libslave_a.a -ldl -lpthread
Примечание
Замените tarantool-libslave/include
на полное имя директории.
Обратите внимание, что имя статической библиотеки – libslave_a.a
, а не libslave.a
.
ШАГ 7: Выполните:
$ ./example
Результат нет – программа в цикле ожидает, пока сервер MySQL запишет данные в бинарный журнал репликации.
ШАГ 8: Запустите клиентскую программу MySQL – подойдет любая клиентская программа. Введите следующие операторы:
USE test
INSERT INTO test VALUES ('A');
INSERT INTO test VALUES ('B');
DELETE FROM test;
Проверьте, что происходит в выводе программы example.cpp
– отображается следующее:
INSERT
INSERT
DELETE
DELETE
Репликация является построчной, поэтому видим DELETE два раза – потому что есть две строки.
В результате выполнения упражнения видим:
- можно собрать библиотеку, а
- программы, которые используют библиотеку, могут получить доступ ко всему, что сохраняет сервер MySQL.
Более подробную информацию и примеры использования см. ниже:
- Загрузить нашу версию
libslave
можно по ссылке: - Ответвление сделано из версии по ссылке (с другим файлом README):
Статья How to speed up your MySQL with replication to in-memory database (на английском)