Некоторое время назад я восхитился от команды Facebook-а, запилившей для целей мониторинга специальную базу — RocksDB. При внимательном рассмотрении оказалось, что оно форк более раннего гугловского проекта, оно архивирует данные налету и оно, будучи «в душе» NoSQL, стыкуется к MySQL как storage engine.
Дальше прилетела новость, что MariaDB включили этот движок в upstream с версии 10.2. Ништяки вроде архивирования на лету и ttl на отдельные строки под капотом так и манили попробовать это на чем-то подходящем…
Подходящим генератором данных в моем хозяйстве оказался zabbix, который к тому же решили перетянуть на новое железо. Но «из коробки» zabbix про rocksdb не в курсе, так что пришлось пошаманить и потестировать. Если интересны результаты и выводы —
Ограничения
Первая проблема, вылезшая при планировании — myrocks не умеет CONSTRAINT FOREIGN KEY
. Не умеет, и всё. И не планируется. NoSQL, однако. Казалось бы, на этом можно свернуть всю затею, но внимательный взгляд на схему данных zabbix-а показывает, что самые горячие таблицы — history_uint, history_text, history_log и history_str — куда, собственно, прилетают данные из всех щелей источников, не содержат внешних ключей. Вероятно, команда zabbix сделала это осознанно, чтобы упростить эти таблицы — но нам это только на руку.
Тут стоит упомянуть, что создатели myrocks не рекомендуют использовать микс из двух storage engine-ов в одном приложении, ссылаясь на то, что транзакции не будут атомарными в этом случае.
Но внимательное разглядывание вывода grep -r 'history_uint' zabbix-3.2.5
приводит к выводу, что хоть zabbix и учиняет транзакции при добавлении значений, внутри этих транзакций он не трогает других таблиц (зачем бы ему, действительно?) — так что пролезаем.
Ещё нужно поменять collation на табличках, которые мы переносим на rocksdb на latin1_bin или utf8_bin. И вообще — от кодировки latin1 лучше избавиться. В итоге получился вот такой perl-скриптик для преобразования дампа:
#!/usr/bin/perl
$tablename='';
$has_constraints=0;
while(<>) {
s/CHARACTER SET latin1//;
if(/CREATE TABLE `(.*)`/) {
$tablename=$1;
$has_constraints=0;
};
if(/CONSTRAINT/) {
$has_constraints=1;
};
if(/ENGINE=InnoDB/ and $has_constraints==0) {
s/ENGINE=InnoDB/ENGINE=ROCKSDB/;
s/CHARSET=([^ ^;]+)/CHARSET=$1 COLLATE=$1_bin/;
};
print $_;
};
Сборка
Я собирал mariadb из исходников до .deb-пакетов и их уже ставил. Выглядит примерно так (ОС — debian 8.8):
apt-get update
apt-get install git g++ cmake libbz2-dev libaio-dev bison zlib1g-dev libsnappy-dev build-essential vim cmake perl bison ncurses-dev libssl-dev libncurses5-dev libgflags-dev libreadline6-dev libncurses5-dev libssl-dev liblz4-dev gdb smartmontools
apt-get install dpkg-dev devscripts chrpath dh-apparmor dh-systemd dpatch libboost-dev libcrack2-dev libjemalloc-dev libreadline-gplv2-dev libsystemd-dev libxml2-dev unixodbc-dev
apt-get install libjudy-dev libkrb5-dev libnuma-dev libpam0g-dev libpcre3-dev pkg-config libreadline-gplv2-dev uuid-dev
git clone https://github.com/MariaDB/server.git mariadb-10.2
cd mariadb-10.2
git checkout 10.2
git submodule init
git submodule update
./debian/autobake-deb.sh
Инсталляция
Не обошлось без дополнительных зависимостей —
wget http://releases.galeracluster.com/debian/pool/main/g/galera-3/galera-3_25.3.20-1jessie_amd64.deb
dpkg -i galera-3*.deb
apt-get install gawk libdbi-perl socat
dpkg -i mysql-common*.deb mariadb-server*.deb mariadb-plugin*.deb mariadb-client*.deb libm*.deb
Сборка net-snmp
По неясным пока причинам, net-snmp из debian приводит к нерабочей сборке zabbix — valgrind ругается на утечки памяти там, где всё должно работать вполне линейно. В итоге заббикс падает.
Спасает — переборка net-snmp из исходников с наложением почти всех debian-овских патчей.
У меня собрался net-snmp-code-368636fd94e484a5f4be5c0fcd205f507463412a.zip
Возможно, более свежие тоже собирутся.
Ещё понадобится debian-овский архивчик с директорией debian.
Дальше как-то так:
version=368636fd94e484a5f4be5c0fcd205f507463412a
debian_version=net-snmp_5.7.2.1+dfsg-1.debian.tar.xz
unzip -q net-snmp-code-${version}.zip
cd net-snmp-code-${version}
tar -xvJf ../$debian_version
for i in 03_makefiles.patch 26_kfreebsd.patch 27_kfreebsd_bug625985.patch fix_spelling_error.patch fix_logging_option.patch fix_man_error.patch after_RFC5378 fix_manpage-has-errors_break_line.patch fix_manpage-has-errors-from-man.patch agentx-crash.patch TrapReceiver.patch ifmib.patch CVE-2014-3565.patch; do
rm debian/patches/$i
touch debian/patches/$i
done
cp ../rules debian/rules
dpkg-buildpackage -d -b
cd ..
dpkg -i *.deb
Фокус с rules-файлом — я в нём выключил --with-mysql (заменил на --without-mysql), чтобы не привязывать net-snmp к mysql — тогда при экспериментах с версиями mariadb не нужно пересобирать net-snmp. Можно и опустить.
Сборка zabbix
Сам zabbix приходится собирать уже после установки mariadb, так как он линкуется к динамическим библиотекам, прилетающим с ней. У меня получилось как-то так:
zabbixversion="3.2.7"
apt-get install libsnmp-dev libcurl4-openssl-dev python-requests
if [ ! -f zabbix-${zabbixversion}.tar.gz ]; then
wget https://downloads.sourceforge.net/project/zabbix/ZABBIX%20Latest%20Stable/${zabbixversion}/zabbix-${zabbixversion}.tar.gz
tar -xvzf zabbix-${zabbixversion}.tar.gz
fi
cd zabbix-${zabbixversion}
groupadd zabbix
useradd -g zabbix zabbix
sed -i 's/mariadbclient/mariadb/' configure
./configure --enable-proxy --enable-server --enable-agent --with-mysql --enable-ipv6 --with-net-snmp --with-libcurl --with-libxml2
make -j5
make install
Профит — удалось уменьшить аппетиты заббикса к месту, отказаться от ротации табличек по схеме «create partition/drop partition» — теперь housekeeper справляется со своей задачей сам (по крайней мере, на ssd-диске, хех. Тут бы проверить на innodb в свежей сборочке, но пока не успелось) и срок хранения данных вновь стал управляемым для каждого элемента данных по отдельности. При массовых проблемах очередь вычищается теперь в разы быстрее.
Что не опробовано (ровно потому, что housekeeper завёлся) — добавить в свойства табличек history* и trends* волшебную штуку COMMENT='ttl_duration=864000;ttl_col=clock;' имеющую, насколько я понял, смысл «хранить не более 864000 секунд, чистить на уровне storage engine».
Да, пока я всё это тестил и прикручивал, заббикс успел выкатить версию 3.4, на ней я всё это не проверял, но что-то мне подсказывает, что должно работать.
Полезные доки, которые пригодились при написании статьи:
Разное другое, что вылезало в гугле на те или иные запросы :)
Спасибо за внимание. Если есть вопросы/замечания — милости прошу в комменты.
Автор: mickvav