Переизобретаем сжатие в распределенной базе данных
Источник: Хабр "Переизобретаем сжатие в распределенной базе данных"
Меня зовут Антон Виноградов, я Java developer в СберТехе, работаю в команде Platform V DataGrid — распределенной базы данных, основанной на Apache Ignite. Я реализовал альтернативный «ванильному» вариант сжатия данных в нашем продукте и хочу рассказать, какие особенности позволили превзойти оригинал.
В начале 2020 года мои коллеги уже рассказывали, как и зачем было организовано сжатие данных в Apache Ignite.
Сжатие данных в Apache Ignite
Кратко напомню, как мы сжимали данные раньше:
Cжатие данных производилось только на диске.
Специально увеличенные в размере страницы, занимающие несколько блоков файловой системы, например, размером в 16 Кб (4 x 4 Кб), при записи в хранилище сжимались до меньшего числа блоков файловой системы, например, до 12 Кб, 8 Кб или даже 4 Кб. Это происходило за счет использования файловых систем с разреженными файлами. При этом постраничная индексация прекрасно продолжала работать за счет того, что с точки зрения приложения страницы не изменяли свой размер.
Помимо этого, страницы сжимались и при записи в WAL, но уже без соблюдения кратности по отношению к блоку файловой системы, например, с 16 Кб до 5 Кб.
Однаĸо в WAL по-прежнему записывались:
- несжатые дельты страниц (Δ), которые записываются вместо полной страницы при повторной записи в одну и ту же страницу в рамках одного чекпоинта;
- несжатые логические записи (op), требующиеся для восстановления консистентности распределенной базы данных.
В итоге у нас появлялась возможность хранить больше данных на диске, но никаких других бонусов при этом мы не получали. И это подтолкнуло нас к реализации альтернативного подхода к сжатию данных, где решались бы и другие значимые для нас проблемы.
Альтернатива
В противоположность описанному варианту мы придумали сжимать отдельные записи в памяти:
В результате на страницах помещается больше данных:
Записываем на диск меньшее число страниц:
В итоге и в памяти, и на диске храним больше данных, а в WAL пишем заметно меньше:
- Страницы в WAL продолжают сжиматься, как и в первом описанном варианте, но сжимаются не с 16 Кб до 5Кб, а с 4 Кб до 2 КБ; записать 2 Кб — значительно быстрее, чем 5 Кб.
- Логические записи в WAL (op), как и дельты страниц (Δ), теперь меньше благодаря тому, что значения уже сжаты при первоначальной записи в память.
Как следствие, в WAL пишем меньше, чем в любом другом варианте со сжатием и без.
Данные на диске не так хорошо сжимаются, как в первом варианте, но зато сжимаются в памяти. А чем больше данных вмещается в память, тем позже наступает Page Replacement — механизм, который при переполнении памяти подгружает нужную страницу с диска, заменяя ею менее востребованную. Уже начавшийся Page Replacement приводит к значительной дергадации быстродействия, поэтому минимизация этого риска — очень важный бонус.
Чего мы добились в итоге
Мы сравнили оба варианта сжатия — «ванильный» сценарий сжатия страниц на дисĸе и наш новый сценарий сжатия значений в памяти.
- Мы добавляли данные в пропорции 1:4 к их чтению.
- Использовали алгогитм сжатия SNAPPY.
- Комбинировали размер страницы (4 Кб, 8 Кб и 16 Кб) и различные подходы к сжатию (None — без сжатия, Value — сжатие значений, Page — страниц, WAL — журнала изменений).
- Использовали данные в формате: Ключ — Integer, Значение — String (размером в 1 Кб, сжимаемая до ~380 байт).
И получили следующие результаты:
1) При использовании нового подхода к сжатию уменьшается потребление памяти, что и было первоначальной целью. Это увеличивает зазор до Page Replacement.
2) Неплохое сжатие данных на диске — очень приятный бонус к первоначальной цели.
3) Невероятное уменьшение размеров WAL — неожиданный бонус, проявившийся именно на бенчмарках и кратно повышающий итоговую ценность решения.
4) Ускорение операций — следствие третьего пункта. Меньше пишем — быстрее работаем.
Даже на крутых SSD есть выигрыш по latency по отношению к любым другим вариантам:
На дисках похуже отрыв будет больше: