Ускоряем базу данных. Bcache

    Для работы мы используем postgresql + postgis базу данных с данными для всей планеты от osm.org. На диске она занимает около 350 Gb и работает не быстро, да и хранится на обычном винчестере 2Tb 7200rpm, без RAID-a. Т.к. нагрузка на базу данных постепенно растет, было решено ускорить дисковую подсистему, потратив при этом минимум денег. Вариантов было не много:
    • купить еще один такой же винчестер и объединить их в raid-0.
    • купить небольшой SSD и организовать на нем быстрый кэш:
      • dm-cache. Был добавлен в ядро 3.9, ставится просто.
      • bcache. Судя по обзорам самый быстрый. Основной минус — надо форматировать диски перед началом использования. Официально добавлен в ядро 3.10, распространяется как пропатченое ядро 3.9.
      • EnhanceIO. В обзорах я встретил упоминание его, как самого медленного, но простого в использовании.

    Взвесив плюсы и минусы, а так же спросив отзывы знакомых, я решил остановиться на bcache. О нем и расскажу подробнее.

    Сборка ядра bcache


    Чтобы попробовать bcache — надо собрать пропатченое ядро 3.9. Проект активно развивается и его исходники даже не распространяются как tar.bz2. Хочешь скачать — качай репозиторий (700Мб где-то).
    # устанавливаем все необходимое для сборки ядра
    sudo apt-get install kernel-package fakeroot build-essential ncurses-dev bc
    # забираем последние исходники bcache
    git clone http://evilpiepirate.org/git/linux-bcache.git
    cd linux-bcache
    # за основу конфига ядра с bcache используем конфиг текущего ядра
    cat /boot/config-`uname -r`>.config
    make oldconfig
    

    После этого шага надо будет выбрать какие опции использовать для добавившихся параметров ядра. Я оставил все по умолчанию, только bcache собрал как модуль ядра. Debug ключи bcache оставил в выключенном состоянии.
    make-kpkg clean
    # С ключом -j можно задать число параллельных процессов сборки.
    sudo time fakeroot make-kpkg -j8 --initrd kernel_image kernel_headers
    # Через 24 минуты ядро было готово. Можно устанавливать.
    sudo dpkg -i ../linux-image-3.9.0+_3.9.0+-10.00.Custom_amd64.deb ../linux-headers-3.9.0+_3.9.0+-10.00.Custom_amd64.deb
    
    # следом установим и bcache-tools
    cd ..
    git clone http://evilpiepirate.org/git/bcache-tools.git
    cd bcache-tools
    make
    sudo make install
    

    Если это ядро самое свежее по версии — оно загрузится автоматически, если у вас установлено что-то более новое — ядро с bcache можно будет выбрать при загрузке в grub2 в меню Advanced boot options.

    Настраиваем bcache


    Для работы с bcache диски надо предварительно отформатировать. (не забудьте забэкапить данные)
    sudo -i
    umount /dev/sdb4
    # форматируем раздел HDD
    make-bcache -B /dev/sdb4
    # форматируем SSD для кэша
    make-bcache -С /dev/sda
    

    Далее диски надо зарегистрировать в ядре.
    echo /dev/sdb4 > /sys/fs/bcache/register
    echo /dev/sda > /sys/fs/bcache/register
    

    После регистрации диск появится как /dev/bcache0, а кэш как /sys/fs/bcache/<UDID>. Форматируем диск в файловую систему по выбору и монтируем его.
    mkfs.ext4 /dev/bcache0
    mount /dev/bcache0 /mnt
    

    Что бы диск знал с которым кэшем ему работать, кэш надо подключить. Пока кэш-сет, это один диск, но в будущем планируют добавить работу с несколькими кэш устройствами в кэш-сете. Один кэш-сет можно добавить к нескольким дискам, что очень удобно для систем с несколькими медленными дисками. Для подключения кэша нам понадобится его UDID.
    echo <UUID> > /sys/block/bcache0/bcache/attach
    

    Ну вот и все. У вас в системе есть диск, с подключенным к нему writetrough кэшем. Если основная нагрузка на базу — это выборки, без модификации данных — такого режима кэширования будет достаточно и SSD проживет дольше. Writeback можно включить коммандой:
    echo writeback > /sys/block/bcache0/cache_mode
    

    Впечатления от bcache


    После заполнения кэша база стала работать в разы шустрее. Привести какие-то цифры мне тяжело, т.к. до перехода на bcache я не делал референсных запросов. Но приблизительное отношение скоростей я показать смогу. Так сферический запрос с пустым кэшем выполняется за 171 секунду. Повторно он же выполняется за 3.2 секунды. Чтобы время исключить влияние кэшей базы данных на скорость обработки, я перезапустил БД, после чего запрос выполнился за 4 секунды. С таким приростом скорости обработка данных всей планеты не кажется невыполнимой задачей на нашем относительно слабом железе.

    Приятным дополнением к bcache является его статистика, которую он бережно собирает. Можно посмотреть на статистику работы кэша, сколько miss, сколько hits, сколько процентов приходится на hits, сколько кэша заполнено, сколько информации было записано в кэш и т.д. Вот что он показывает у меня в настоящий момент:
    $ cd /sys/block/bcache0/bcache/stats_hour
    $ cat cache_hit_ratio 
    90
    $ cat cache_hits
    836233
    $ cat cache_misses 
    91086
    $ cd cache/cache0
    $ cat btree_written 
    92.3M
    $ cat metadata_written 
    481M
    $ cat written 
    41.3G
    

    Спасибо за внимание. О опечатках и неточностях сообщайте в личку, на вопросы постараюсь ответить в комментариях.
    p.s. Документация к bcache очень подробная и хорошо написана, рекомендую к прочтению.
    Метки:
    Поделиться публикацией
    Похожие публикации
    Комментарии 28
    • +1
      Как оно относится к жесткой остановке работы, когда на SSD остаётся масса dirty-блоков?
      • +1
        Bcache не различает жесткую остановку и обычную. Dirty блоки останутся целы и невредимы и работа с кэшем продолжится из последнего состояния. Из документации:
        Bcache goes to great lengths to protect your data — it reliably handles unclean shutdown. (It doesn't even have a notion of a clean shutdown; bcache simply doesn't return writes as completed until they're on stable storage).
        • 0
          Это для writethrough и так вроде все делают в этом режиме.
          WriteBack, скорее всего, уничтожит базу. Вот есть блочное устройство с кешем, есть файлуха. На кэше блоки свои, у файлухи свои. Вырубается питание. Все, что было в памяти и не успело упасть в кэш на ssd — пропало. Так? Как теперь кэш, который ничего не знает про файловую систему и ее состояние, поймет, какие блоки где dirty? Надо все делать dirty, либо какойто журнал вести, что опять сильно снижает эффективность такого кэша.
          • 0
            А зачем использовать writethrough? Есть pagecache, который работает вполне себе сам. Память стоит не слишком дорого.
            Лично я вижу смысл применения только в режиме writeback, потому и интересуюсь.
            ToSHiC однажды высказывал мысль, что можно хранить карту dirty-блоков на самом SSD, тогда будет большой write amplification, но безопасное резкое отключение питания.
          • 0
            Кэш с dirty данными работает как база данных. Для каждого блока сохраняются его метаданные и он сам. После этого запись считается выполненной. Так что при выключении питания информация о том какой блок dirty, а какой нет — останется. Так же останется информация какие блоки, каким данным на диске соответствуют.
            • 0
              Я про writeback.

              Осталось понять, как эти метаданные кэша связаны с файлухой и уже ее журналом. Вот свет появился, акей, эти блоки надо записать, а эти уже dirty. А на файлухе другая картина уже и она хочет совсем другого, чем ей дает записать кэш. Каша будет, я это наблюдал не раз. Нет батарейки — прощайте данные. Это наверное работает, но под нормальной нагрузкой под тысячу рпс на бекенд, пишущий в базу постгреса, у меня в 10 случаях из 10 данные превращались в кашу. Это выглядит, как, напрмер, кусок сислога посреди файла с таблицей. Или кусок таблицы в другой таблице. Все, куда была интенсивная запись, все перемешано.
              • 0
                В том случае, в котором был бы фэйл на обычном HDD — будет фэйл и у bcache. Как я понимаю, дополнительной угрозы данным bcache не вносит. Файловая система не видит отдельных секторов диска, для нее диск — это bcache. А bcache делает работу записи такой же надежной как и запись на голый HDD, потому как операции записи возвращаются, когда данные и их метаданные уже сохранены на SSD.
    • 0
      читал, что толку от SSD ZIL в ZFS намного меньше по сравнению с добавлением оперативки
      хотелось бы повысить скорость random write, для read то поди и линукс ядро нормально справится, да и ZFS ARC вроде нормальный

      а имеет ли смысл для увеличения random write IOPs прикрутить bcache к ZFS ZVol (кусочек пула в качестве блочного устройства), не ухудшится ли надежность при выдергивании SSD или 220В?
    • 0
      Меня вот вопрос интересует а без bcache устройства доступ получить ко всему этому можно?
      • 0
        bcache — это просто устройство через которое мы работаем с HDD. Он появляется когда подключенный кэш инициализировался, если кэш не был подключен, как в начальном этапе настройки — bcache появится сразу. Если с SSD диском случилось что-то плохое и bcache не появился — можно вручную заставить bcache стартовать (все dirty данные из кэша, ясное дело, будут утеряны):

        echo 1 > /sys/block/sdb/bcache/running
        

        Или я неправильно понял вопрос? :)
        • 0
          Правильно. А то вот в этой схеме по сравнению с flashcache меня сильно смущал момент, что надо форматировать отдельно.
          • 0
            Один раз забэкапить, отформатировать и развернуть обратно можно. Время конечно занимает, но не критично.
        • 0
          т.е. если поверх bcache смонтировать ext4 с опциями journal_checksum,data=journal (хотя, наверно, достаточно журналировать метаданные)
          начать записывать много мелких файлов и и дернуть SSD или питание,
          то файловая система не порушится и все, что было записано до подключения SSD и bcache останется (если специально не стирать)?
          • 0
            На практике я не проверял. Но документация к bcache уверяет нас что все будет хорошо.
    • 0
      А чем Bcache отличается от Flashcache, разработанный Facebook? Насколько мне известно, только Flashcache сейчас готов к продакшну.
      • 0
        тоже очень любопытно, хотя ни один пока не использовал
      • 0
        Тесты показывают, что Flashcache проигрывает bcache в скорости.
      • 0
        Около года используем FlashCache в продакшене под postgresql базами, отзывы только положительные. Отличия:
        Flashcache основан на devoce-mapper поэтому перед тем как начать его использовать, нужно «слепить» гибридный dm-том из имеющегося тома и SSD-тома/раздела/диска. И потом это гибридное устройство монтировать и использовать.
        Bcache (как и EnhanceIO) это отдельный блочный драйвер, не использующий device-mapper слой.
        Оба отличаются подходом в создании томов (в flashcache мне как-то показалось проще это устроено, bcache показался непривычным flashcache… а enhanceio вобще показался сказкой, но он медленный это правда + пару раз ловил kernel panic).
    • 0
      Откуда информация о включении EnhanceIO в 3.10? В LKML появились патчи с запросом о включении, но мейнтейнеры затребовали обоснование и конкретные результаты тестов, после чего процесс включения пока заглох.
      • 0
        Хм. Мне кажется я встречал информацию о том, что EnhanceIO хотят включить в ядро так же, как и bcache. Значит ошибся — уберу упоминание из поста.
        • 0
          Хотят — да, но не включили. Разработчик пишут на github'е, что скоро опубликуют результаты тестов в LKML, но пока их нет, патч рассматривать не будут.
    • 0
      вы ускоряете в основном запись или чтение?
      насколько запись и чтение рандомные?
      какое соотношение размеров SSD и HDD?
      какие прогнозы выжиываемости при внезапной смерти SSD?

      Я о том, насколько оно лучше, чем просто заменить старый винчестер на SSD.
      • 0
        В основном я ускоряю чтение, данные редко меняются.
        Настолько на сколько рандомно чтение при работе с большой базой данных.
        HDD, как я писал, 2Tb и SSD 120Gb
        Если не использовать writeback кэширования — никаких проблем быть не должно. Если умрет кэш с dirty данными, будет конечно хуже. Я посматриваю на smart показатели SSD диска, чтобы смерть не стала неожиданной. Опять таки работать с важными данными и не делать бэкап было бы глупо. HDD тоже умирают время от времени.

        SSD на 512Gb стоит несколько дороже, чем такое вот решение. Да и время жизни SSD с базой, мне кажется, будет меньше чем у SSD c writetrough кэшем той же базы.
    • +1
      А BTIER не пробовали?

      www.opennet.ru/opennews/art.shtml?num=37023
      • 0
        Нет, не пробовал. Даже не встречал его упоминания как-то. Буду рад почитать, если кто-нибудь напишет о нем свои впечатления.
    • 0
      Возьму ваш опыт на заметку. От себя добавлю, что неплохой прирост производительности можно получить, если все же докупить несколько хардов и раскидать на них таблицы, логи и индексы (каждому — свой хард).
    • +3
      > Хочешь скачать — качай репозиторий (700Мб где-то).

      На заметку:
      git clone --depth 1
      
      Создаёт shallow-копию (только последняя ревизия).

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.