Дмитрий Кутейников

Дмитрий Кутейников 

Программист, технарь и самую малость - графоман

55subscribers

180posts

goals1
7 of 100 paid subscribers
Для начала. Возможно, в какой-нибудь параллельной вселенной, я смогу заработать писательством на жизнь, и уж тогда...

Про Rapeed и ClickHouse на диске

При обсуждении Rapeed я регулярно сравниваю его с ClickHouse. Тому есть две причины:
1. ClickHouse - офигительно хорош! Яндекс вложил в него сотни (а то и тысячи) человеко-лет разработки и сделал СУБД мирового уровня, которую можно смело поставить в один ряд с mysql, postrgesql и многими коммерческими. А потом отдал в OpenSource.
2. ClickHouse создавался под задачи, довольно похожие на наши (Яндекс делал его под учёт онлайновых метрик - кто когда куда сколько раз кликнул) и тоже пришёл к столбчатому хранению данных и их шардированию (это называется конвергенция).
Именно по этим же причинам ClickHouse сейчас используется во многих системах бизнес-аналитики как ядро (даже мы его использовали, пока своё ядро не начало работать хоть как-то - чтобы было на чём отлаживать фронт), и сравнение с ним - это, фактически, сравнение с подавляющим большинством наших конкурентов.
При массе сходств между Rapeed и ClickHouse есть принципиальное отличие: ClickHouse - честная СУБД (система управления базами данных) с полноценной поддержкой SQL, а Rapeed - нет. Rapeed - это система бизнес-аналитики, и всем остальным мы сознательно пожертвовали ради скорости и функционала расчётов.
К сожалению, у меня так и не дошли руки как следует разобраться в деталях, как именно ClickHouse хранит данные, и потому про него буду говорить очень поверхностно. Наш шеф категорически настаивает на неразглашении технических деталей (хотя на мой взгляд большинство их абсолютно очевидны, но тут действует старый принцип 90+9+1), так что про Rapeed я тоже расскажу в очень общих словах.
Во-первых, про собственно столбчатое хранение. Кто знает - смело пропускайте абзац, специально выделил курсивом. Таблица в классической реляционной СУБД представляет собой множество (не последовательность!) строк фиксированного набора столбцов разных типов. Классические СУБД хранят эти данные построчно - что создаёт сложности при хранении значений разного типа, но имеет свои плюсы. Столбчатые СУБД, очевидно, хранят данные по столбцам - в каждом столбце данные строго одного типа, что заметно упрощает жизнь, плюс, если какой-то столбец не участвует в запросе - его данные вообще никто не трогает даже длинной палочкой (а классическая СУБД при чтении с диска читает всю строку целиком).
Во-вторых, про сложный философский выбор: диск (в смысле "энергонезависимое хранилище" - сейчас это обычно не шпиндель, а флэш того или иного вида) или оперативная память. Пока что у нас оперативная память при отключении питания сбрасывается и "жить" в ней нельзя (с оговоркой про редкие исключения и перспективные разработки, которым до массовой эксплуатации - как до Луны пешком), поэтому все данные хранятся на диске, откуда загружаются в память при необходимости и куда потом записываются при изменениях. Диски заметно медленнее оперативки (когда-то, во времена шпинделей, разница исчислялась порядками, сейчас сильно сократилась, но всё равно очень существенна) и поэтому очень важно держать в памяти, с одной стороны, как можно больше нужных данных, но с другой - как можно меньше ненужных, отсюда разные сложные системы балансировки между "больше оперативки для расчётов" и "больше данных под рукой, чтобы не читать медленный диск".
ClickHouse использует сжатие данных на диске (и при обменах по сети тоже, но сегодня - про диск), причём так называемые "легковесные алгоритмы" - специально разработанные, чтобы очень-очень быстро снять "энтропические сливки" с данных. За счёт этих алгоритмов нередко оказывается, что "сжать и записать" - быстрее, чем записать не сжимая, и "прочитать и распаковать" - тоже быстрее, чем просто прочитать несжатое, хотя современные накопители на флэше показывают совершенно поразительную скорость работы (но современные процессоры тоже не остаются в долгу). Какие именно алгоритмы используются - увы, не смотрел, и насколько я понимаю, эти же алгоритмы используются и для сжатии данных при пересылке по сети, так что авторам можно только поаплодировать. Минус тоже очевиден: при загрузке данных (если у нас по каким-либо причинам нет возможности обрабатывать их как поток, а такая возможность бывает, увы, нечасто - в лучшем случае их можно обрабатывать блоками) необходима лишняя память: во-первых, целевой буфер под полный размер несжатых данных, во-вторых, отдельный буфер под чтение с диска, желательно достаточно большой, чтобы операционка и сама СУБД не задохнулись под большим количеством операций ввода-вывода.
Мы до сих пор смотрим в сторону сжатия данных - просто для справки, ибо это реально мощная технология, хоть и со своими недостатками. Но не используем, и вряд ли будем использовать для исходных данных - только для каких-то временных объектов и структур. Мы используем отображение файлов в память (когда с точки зрения программы весь файл лежит в оперативной памяти одним длинным блоком, а операционка незаметно читает/записывает данные при обращении). Если предельно кратко, то главных плюсов два: во-первых, операционная система сама решает, когда читать отображаемый файл и сколько физической памяти под него выделить (то есть, при нехватке физической памяти ОС может выгрузить давно не использовавшиеся страницы), во-вторых, сколько бы данных в файле ни было - с точки зрения программы они все лежат одним логическим куском, и можно обратиться в любое место без сложного жонглирования буферами и чтением/записью. Минусы, разумеется, тоже есть, и тоже серьёзные: во-первых, на диске приходится использовать тот же формат, который "живёт" в оперативке ("сырые" данные можно было бы записать компактнее), во-вторых, у программы нет явного контроля над чтением и записью (он косвенный и сложный), также усложняется и контроль за потреблением оперативки. Мы решили, что для наших задач плюсы перевешивают минусы. ClickHouse же - это СУБД и их приоритеты оказались расставлены иначе.
Следующий момент - шардирование данных (от английского shard, осколок). Распределённая система по определению хранит данные несколькими кусками - на каждом сервере свой. Очевидно, что распределённые системы начинались с попытки решить задачу, которая не влезает в один сервер, путём разделения этой задачи на несколько кусков, их независимой обработки и последующего объединения результатов. Столь же очевидно, что далеко не все задачи к такому подходу относятся благосклонно (например, подсчёт количества уникальных значений в столбце по нескольку миллиардов строк на каждом сервере). Однако, в подавляющем большинстве случаев распределённое решение почти не уступает монолитному, а в тех, где уступает, нередко можно так или иначе сжульничать (например, для того самого подсчёта уникальных есть быстрые алгоритмы, которые дают приблизительную оценку с погрешностью до трёх-пяти процентов, в зависимости от данных, и для многих задач этого хватает). Отсюда возникает идея шардирования данных: если обработка по кускам даёт пренебрежимо малые накладные расходы - давайте сделаем ещё больше кусков (а сами куски поменьше) и будем обрабатывать их параллельно на десятках ядер серверных процессоров. Если опустить длинные рассуждения, то в сухом остатке мы получаем некий оптимальный размер шарда, который, с одной стороны, достаточно быстро и эффективно обрабатывается, а с другой - самих этих шардов (и результатов их обработки, что важенее) - достаточно мало, чтобы агрегация не стала отдельной самостоятельной головной болью.
Самый сложный вопрос - как именно разбивать данные. ClickHouse делает это по дате. Я не знаю, что получится, если в таблице не будет ни одной даты или наоборот, будет много разных дат - вероятно, будет использована дата записи строки (вспоминаем, что исходно ClickHouse создавался для учёта онлайновых метрик, и "когда кликнули" - информация архиважная). ClickHouse нарезает данные по месяцам, насколько я помню (полагаю, там есть адаптивный механизм, позволяющий адаптировать гранулярность под плотность реальных данных - это было бы логично) и раскидывает более-менее равномерно между серверами кластера. В плюсе: если у нас запрос ограничен по дате (онлайновые метрики!) - мы сразу знаем, какие шарды нам нужны, и остальные просто не трогаем. Если запрос по дате не ограничен, но хотя бы сгруппирован (какой-нибудь ежеквартальный отчёт) - шардирование тоже помогает (каждый шард строит свой кусочек общего списка). Если запрос с датой не связан никак - мы ничего не выигрываем от шардирования по дате. Rapeed данные шардирует в порядке поступления: читаем из СУБД батчами, раскидываем по разным серверам кластера, где они складываются в шарды, а как только шард достиг оптимального размера - он закрывается и следующая пориция данных идёт в новый шард. Причина очень простая: мы не знаем, как именно пользователь будет группировать данные при обработке, а потому и не пытаемся угадать, зато адаптируем все алгоритмы к сценарию "шардирование неудачное". Очевидный недостаток - на каждый запрос мы всегда обрабатываем все шарды, столь же очевидный плюс - мы не тратим ресурсы на выбор нужных шардов, все алгоритмы изначально оптимизированы именно под этот вариант и запрос любой формы обрабатывается примерно с одной и той же скоростью вне зависимости от выбранной пользователем структуры. Фактически, мы отказались от большого выигрыша на очень узком множестве сценариев ради маленького выигрыша на всех сценариях.
Отдельно стоило бы поговорить про логическую структуру хранения данных - всякие деревья, хэш-таблицы и вот это всё, но ClickHouse я знаю очень поверхностно, а про Rapeed рассказывать нельзя. Зато я могу рассказать о принципиальной разнице подходов. ClickHouse - это СУБД, настоящая, взрослая, полноценная - хвалите его больше, это реально отличная СУБД, особенно под свои задачи. У них есть масса классных оптимизаций и запросы выполняются очень быстро (мы потратили примерно месяц, жестоко перетряхивая всё наше ядро, чтобы сократить отставание с трёх раз до двадцати процентов при подсчёте уникальных в некотором очень тяжёлом сценарии, и потом ещё месяц - чтобы сократить до единиц процентов в худших для нас случаях, а в некоторых востребованных сценариях - и заметно обогнать). Но у нас есть кэш, который заточен именно под задачи бизнес-аналитики. Возможно, в ClickHouse тоже есть какой-то кэш - не интересовался, так как повторные запросы в ClickHouse выполняются примерно то же время, что и самый первый, а у нас ответ из кэша занимает доли секунды, даже если первый запрос считался несколько минут.
Собственно, вот к этой разнице (десятки секунд каждый раз против долей секунды на повторных запросах) и сводится различие между "настоящей честной СУБД" и нашей системой бизнес-аналитики. Как ClickHouse проектировали, зная, что будут хранить в нём онлайн-метрики, так и Rapeed проектировали, зная, что будут считать в нём бизнес-аналитику. К слову, в целеполагании тоже видно разницу: "хранить" и "считать". Впрочем, это мы уже выходим за рамки обсуждения именно дисковой стороны.
Subscription levels3

Поддержать голодного программиста!

$0.4 per month
Спасибо за моральную поддержку! Она для меня ОЧЕНЬ важна!

Поддержите молодого (нет) графомана

$1.31 per month
ВСЁ И СРАЗУ!
Ничего ждать не придётся, весь платный контент будет выкладываться именно на этом уровне и через неделю падать ниже.

Две шавермы

$5.3 per month
Всё ровно то же самое, что и на предыдущем уровне, ибо я так и не смог придумать, что бы такое осмысленное добавить.
Специально для тех, кто хочет поддержать более решительно.
Go up