Некоторое время назад я восхитился от команды 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, на ней я всё это не проверял, но что-то мне подсказывает, что должно работать.

Полезные доки, которые пригодились при написании статьи:


Разное другое, что вылезало в гугле на те или иные запросы :)
Спасибо за внимание. Если есть вопросы/замечания — милости прошу в комменты.

Комментарии (18)


  1. looofi
    18.09.2017 13:38

    Сколько сейчас NVPS?


    1. mickvav Автор
      18.09.2017 13:38

      Немного, 374.55


    1. mickvav Автор
      18.09.2017 13:42

      При всяких чудесах на сети — подскакивает до полутора — двух тысяч. Перемалывает без проблем.


  1. 0x12ee705
    18.09.2017 15:00

    а где первые впечатления?


    1. mickvav Автор
      18.09.2017 15:15

      Ну, если чуть длиннее, чем в статье — видно, что rocksdb время от времени жмёт свои файлики, так что в норме жизни график свободного места представляет собой пилу.
      Весь стандартный функционал заббикса — работает, как ни в чем не бывало.
      Производительность выросла, но тут я не могу отделить вклад rocksdb от вклада перехода с hdd на ssd.
      Сборка всей кухни из исходников доставила хлопот (хотя бы потому, что из всех веток в git mariadb надо было выбрать рабочую).


  1. 0x12ee705
    18.09.2017 15:27
    +1

    ну хотя бы бенчмарк привели бы — до и после)))и почему Вы из исходников все собираете?


    1. mickvav Автор
      18.09.2017 15:48

      Из исходников — вынужденная мера — заббикс из коробки линкуется с libmysql, который приходится перекомпилировать, чтобы rocksdb был рабочий. Если не пересобирать net-snmp (про это есть в статье) — zabbix на snmp-ных элементах данных валится. Но не сразу, а через какое-то время.
      Бенчмарк — тема, осталось собрать нормальный стендик под это, независимый от продакшена. Нет ли у вас на примете достаточно разлапистой конфигурации для zabbix-а и генератора данных под неё, чтобы сравнить «при прочих равных». С меня — оплатить ноды на amazon-е и прогнать тесты в конфигурации с innodb (c housekeeper-ом и без и с partition-ing-ом) и с rocksdb (соответственно, с housekeeper-ом и с Comment=ttl_...) — мне тоже интересно увидеть, сколько можно выжать того же NVPS.


  1. looofi
    18.09.2017 15:59

    Репликация настроена?


    1. mickvav Автор
      18.09.2017 16:02

      Нет.


      1. looofi
        18.09.2017 16:06

        А зачем тогда galera?


        1. mickvav Автор
          18.09.2017 16:59

          Ну прописана она в зависимостях у mariadb-ных пакетов. Содержательно тут она не нужна, да.
          Да, можно и тут подпилить rules-файл (или где оно там), но зачем?


  1. 0x12ee705
    18.09.2017 16:09

    что Вы подразумеваете под «разлапистой конфигурации»?
    и если под генерацией данных Вы имеете это: www.zabbix.org/wiki/Docs/protocols/zabbix_sender/3.4
    www.zabbix.org/wiki/Docs/protocols/zabbix_agent/3.4
    давайте я Вам помогу


    1. mickvav Автор
      18.09.2017 17:13

      Чтобы было осмысленно сравнивать, imho, нужно иметь конфигурацию из хотя бы сотни узлов с хотя бы десятком элементов данных в каждом. И «нечто», что по zabbix-овому протоколу будет кормить заббикс данными. Смысл — забить кэши, какие ни есть.
      А лучше — нечто, что будет отвечать на запросы к агентам какими-то разумно шумящими циферками.
      Проблема в том, что у меня под руками такого стенда нету.


  1. Softer
    18.09.2017 16:59

    А конфиги машины? Статистка Zabbix, графики нагрузки на железо и его параметры? Можно? :)


    1. mickvav Автор
      18.09.2017 17:08

      Можно, а какие именно вам интересны?
      Машина — (24 ядра по cpuinfo) CPU — Intel® Xeon® CPU E5-2640 0 @ 2.50GHz
      16 GB RAM, SSD — Kingston_SHPM2280P2_480G
      С графиками и статистикой — опять же можно, но завтра и прицельно — что интересно.


      1. Softer
        18.09.2017 17:13

        Интересно сколько хостов суммарно и потребление памяти/cpu/hdd на сервере до/после. Субъективно — быстрее ли отрабатывают разделы интерфейса с данными из history_*? Если таблица крашнется — как у этого аддона дела с восстановлением?


        1. mickvav Автор
          19.09.2017 14:41

          Количество узлов сети (активированных/деактивированных/шаблонов) 844 615 / 104 / 125
          Количество элементов данных (активированных/деактивированных/неподдерживаемых) 91652 71854 / 407 / 19391
          Количество триггеров (активированных/деактивированных [проблема/ок]) 69283 68416 / 867 [57 / 68359]
          Количество пользователей (в сети) 17 4
          Требуемое быстродействие сервера, новые значения в секунду 374.55

          Субьективно — быстрее. График с ~35 линиями с данными за сутки (с разрешением ~3 точки в минуту) рисуется ~5 секунд. На старой машине — в разы дольше, но точную цифру не скажу.
          Даже если поднять там данные — не будет честного сравнения — на ней диск медленнее, а процессор быстрее.

          Таблицы специально не крешил.
          Когда по ошибке прервал операцию «alter table… add column» над history_uint с поднятыми данными, отправив sigkill серверному процессу, случился казус — оно оставило временный файл в директории, записала себе в мозг, что создало его, а при следующем пуске сперва потёрло времянку, а потом удивлённо упало с комментарием вида «ой, тут у меня табличко пропало» — пришлось лезть грязными руками в исходники.
          Детали тут: github.com/mickvav/mysql-5.6/pull/1
          и тут: github.com/facebook/mysql-5.6/issues/669


        1. mickvav Автор
          19.09.2017 14:53

          С памятью и потреблением диска — попробую сделать контрольный замер (при «прочих равных») — но это займёт время, не сегодня уже.