Изменения

Перейти к: навигация, поиск

Производительность Ceph

42 байта добавлено, 12:22, 8 августа 2020
Нет описания правки
Кто задолбался со спилловерами? Все задолбались со спилловерами! :)
Спилловер — Спилловер — это когда вы собрали Bluestore на SSD+HDD, выделив SSD под базу (block.db), но при этом эта самая база постоянно частично утекает на HDD. При этом она, вроде бы, даже влезает в SSD с запасом — запасом — но всё равно утекает. Начиная, кажется, с Ceph 14 Nautilus, о спилловерах предупреждает <tt>ceph -s</tt>, а с Ceph 15 Octopus авторы попытались победить spillover-ы через дополнительные «allocation hint»-ы RocksDB, но, в целом, легче от всего этого не стало.
Когда случается спилловер в SSD+HDD конфигурациях, работа кластера замедляется — замедляется — в большей или меньшей степени, в зависимости от размеров RocksDB и паттерна нагрузки, так как когда метаданных не очень много, они влезают в кэш OSD — OSD — либо onode cache, либо rocksdb cache, либо, если включено bluefs buffered io — io — то ещё и в системный page cache. Если кэш-промахов достаточно много, могут даже появляться slow ops-ы.
Так в чём же дело и как это победить? А дело в том, что с выбором раздела для очередного файла БД (RocksDB организована в виде набора файлов) «есть небольшой нюанс», точнее, даже два.
Нюанс № 1№ 1: RocksDB кладёт файл на быстрый диск только когда считает, что на быстром диске хватит места под все файлы этого же уровня (для тех, кто ещё не в курсе — курсе — RocksDB это [https://github.com/facebook/rocksdb/wiki/Leveled-Compaction LSM база]).
Дефолтные настройки цефа:
* соответственно, L1 = 256 Мб
* L2 = 2560 Мб
* L3 = 25600 Мб и ти т. д д.
…Соответственно!
Rocksdb положит L2 на block.db, только если раздел имеет размер хотя бы 2560+256+1000 Мб — Мб — округлим вверх до '''4 ГБ'''. А L3 она положит на block.db, только если block.db размером хотя бы 25600+2560+256+1000 МБ = около '''30 ГБ'''. А L4, соответственно, если ещё +256 ГБ, то есть итого '''286 ГБ'''.
Иными словами, имеют смысл только размеры раздела block.db 4 ГБ, 30 ГБ, 286 ГБ. Все промежуточные значения бессмысленны — бессмысленны — место сверх предыдущего граничного значения использоваться не будет. Например, если БД занимает 10 ГБ, а раздел SSD — SSD — 20 ГБ, то фактически на SSD ляжет только WAL (1 ГБ), L1 и L2 (256 МБ + 2.56 ГБ). L3, составляющий бОльшую часть базы, уедет на HDD и будет тормозить работу.
При этом 4 ГБ — ГБ — слишком мало, 286 ГБ — ГБ — слишком много. Так что, по сути, правильно делать block.db размером хотя бы 30 ГБ для всех OSD.
Нюанс № 2№ 2: В момент compaction-а RocksDB часто требуется целиком переписать уровень целиком. Если при этом на SSD нет запаса места в размере этого уровня, то он, опять-таки, утечёт на HDD и так там и останется, ибо перемещать после compaction-а его обратно она не умеет. При этом одновременно могут компактиться как минимум первый и последний уровни.
Из этого следует, что, по идее, на разделе БД нужен ещё и запас в размере первого + последнего уровня БД. То есть примерно 30 ГБ превращаются в примерно 60.
Но что делать, если сами базы у вас размером, скажем, 30 ГБ? Выделять на SSD раздел 550 ГБ как-то уж очень жирно, но и спилловеров иметь не хочется. В этом случае можно поменять базовый размер уровня RocksDB (max_bytes_for_level_base). multiplier менять не будем, оставим по умолчанию 10 - 10 — его значение влияет на итоговое количество уровней RocksDB, а это уже более тонкая материя. Теоретически, меньшее число уровней снижает read и space amplification, но замедляет compaction и из-за этого может сильно повысить итоговый write amplification. Также есть тема с уменьшением размера отдельных memtable и кратным увеличением общего их числа, т.е.то есть, например, установки 32*32 МБ вместо дефолтных 4*256 МБ и min_write_buffer_to_merge=8, но эффект от этого тоже не совсем понятен (возможно, немного экономится CPU при compaction-е), так что это тоже пока лучше не трогать.
Итак, помня про необходимость запаса под первый и последний уровни выводим, что общий размер раздела БД должен быть равен k*X, где X - X — размер первого уровня, а k - k — коэффициенты из ряда: 2 (1 уровень), 22 (2 уровня), 212 (под 3 уровня), 2112 (под 4 уровня) и ти т.п п.
Соответственно, берём целевой максимальный размер нашей БД: 30 ГБ. Это будет размер последнего уровня. Делим его на 10 до тех пор, пока значение не приблизится где-то к гигабайту и принимаем это за размер первого уровня. Компактится база по 256 МБ за раз, так что меньше 256 МБ размер первого уровня ставить точно смысла нет. После этого число делений+1 принимаем за число уровней, домножаем размер первого уровня на соответствующий коэффициент, накидываем +1 ГБ для WAL, округляем чуть вверх и получаем необходимый размер раздела SSD. В случае с 30 ГБ - ГБ — размер первого уровня будет 300 МБ, число уровней 3 и требуемый размер SSD раздела - раздела — около 65 ГБ. Прописываем это в конфигурацию (bluestore_rocksdb_options = ...,max_bytes_for_level_base=300MB), деплоим OSD и радуемся жизни. Ну, почти радуемся, так как 5050 % этого раздела у нас используется только в момент компакшена, а остальное время простаивает...простаивает…
== Снапшоты ==

Навигация