Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Алексей Миловидов работал инженером в Яндекс.Метрике, и перед ним стояла непростая задача.
Яндекс.Метрика работала с петабайтами данных — это был третий по популярности сервис веб-аналитики в мире. Для него нужна была база данных, которая может обрабатывать огромное количество данных в реальном времени, очень быстро, при этом не сжигая миллиарды денег.
Долгое время такая СУБД разрабатывалась только для внутренних нужд — но в 2016 вышла в опенсорс под названием ClickHouse, и сообщество встречает инструмент по-разному.
Мы поговорили с Алексеем о том, как он стал разработчиком, почему ClickHouse намного быстрее всех аналогов и как так получилось, какова цена производительности, почему ClickHouse стал опенсорсным и куда вообще движется индустрия.
— Расскажи про себя, про учебу, и про первый опыт в разработке.
— Наверное, надо начинать очень издалека. В семье было еще два брата, я самый младший. Году в 90-м родители купили старшему брату бытовой компьютер БК-0010. Это была реально классная машина. Интересные игры, встроенные языки программирования: Бейсик Вильнюс 86 и Фокал (Focal, акроним от англ. formula calculator).
Мои братья играли в эти игры, я в основном смотрел, мне было года 3-4. Отец с работы приносил стопки ксерокопий. На них можно было рисовать. Я рисовал компьютерные игры, лабиринты. И все время пытался заставить старшего брата все это запрограммировать. И я его так достал, что он взял и выполнил мою просьбу. Оказывается, я стал менеджером гораздо раньше, чем программистом.
Ради смеха братья посадили меня за компьютер, показали бейсик. Научили набирать команды. Типа нарисовать на экране круг, и компьютер покорно его рисовал. Вроде ничего особенного, но я воспринимал это как чудо. Как будто у меня в руках появилась волшебная палочка.
Брат рассказал про цикл и дал мне в руки толстую книгу под названием «Язык программирования Бейсик». Уже позже папа принес домой IBM 286, и я стал что-то ковырять на нем. Мое первое достижение — я написал игру и смог уговорить поиграть в нее маму. Мне было чуть меньше 10 лет.
В школе преподавали Паскаль. Писал на Паскале, потом на Делфи. Потом решил изучить С. С++ всегда был мощным, таким он и остался — так было написано на диске старшего брата. Тем более я где-то услышал, что если писать игры — то только на С++, другого варианта нет.
Это история была общей для всех программистов. Все учили С++, чтобы делать игры, а в итоге делают КликХаус.
— Почему КликХаус настолько быстрее аналогов?
— Тому есть две причины. Одна причина — это просто более-менее подходящие технические решения. А вторая — внимание к деталям. КликХаус был создан для обработки данных веб-аналитики в Яндекс.Метрике. Я решал задачи производительности. Что-нибудь подкрутить, как-нибудь схитрить, чтобы КликХаус работал хотя бы в 2 раза быстрее. Как только ты сделал его в 2 раза быстрее, сразу думаешь: а как еще в полтора раза быстрее сделать? А еще бы на 30%, и вообще было бы идеально! Приходится много ковыряться в деталях.
В других системах есть один алгоритм, подходящий для общего случая. Допустим, для разных типов данных — один алгоритм, а в КликХаусе — есть специализации. Для разных видов данных он может использовать разные алгоритмы.
— В такой работе должен быть инженерный кайф.
— Да, он определенно присутствует. Представь, что ты наконец-то сделал решение, (может быть, впервые в жизни!), про которое ты можешь сказать: да, это лучшее решение в мире.
Я иронизирую, но, допустим, на работе ты делаешь круды. Или другие мемы индустрии: клепаешь формочки, перекладываешь джейсоны. Однажды ты настолько хорошо переложил джейсоны, что понял: ты сделал лучший в мире Перекладыватель Джейсонов! Он тратит мало оперативки, его можно быстро прикрутить. И главное, прийти в другую компанию, сказать, что с помощью этого классного инструмента я вам сейчас переложу все джейсоны из одного места в другое.
— Но компаниям на самом деле наплевать, как ты перекладываешь джейсоны. Жрет оно в 5 раз больше оперативы, и бог с ним!
— Не нужно постоянно искать лучшее решение в любом коде. Я постоянно пишу код, на который мне наплевать, как он будет работать. Но это в основном всякие временные скрипты, которые я называю треш-скрипты. Я даже могу сказать, что есть языки программирования, к которым я отношусь без уважения. Я пишу программу на питоне, мне пофиг, насколько это идеальная программа, мне просто главное, чтобы она решала задачу.
— В самом начале работы над кликхаусом ты был человеком, который хорошо разбирался в оптимизации производительности?
— Совершенно нет. Пробовал, экспериментировал. Я точно могу сказать, что год назад я был тупой, два года назад — очень тупой! Сейчас не знаю, посмотрю через год.
— Работа над кодом, главная черта которого — производительность, накладывает большие требования на тестирование этой производительности?
— Во-первых, если пишешь такой код, у тебя получается просто больше строк из-за того, что в этом коде больше разных путей, больше пространства, которое нужно тестировать. Протестировать такой код стоит больших усилий.
Во-вторых, на большинстве проектов или нет регрессивного тестирования производительности, или есть, но ему уделяют не так много внимания, как просто другим функциональным тестам. Это непростая задача. При тестировании производительности требуется использовать статистические критерии.
Например, изменения производительности могут быть связаны с тем, что в бинарном файле куски машинного кода расположились немного по-разному. Думаешь, ну случайно. Но у тебя есть результаты тестирования, которые представляют собой выборку тестов. Десять раз один, десять раз другой. Ты используешь статистический критерий и проверяешь, есть ли статистическая значимость между разницей времени выполнения. И тебе показывают, что она вроде как есть. И ты думаешь, ну не может же такое быть, я вообще код в другом месте менял. Запускаешь сто раз, запускаешь тысячу, а все равно разница сохраняется. Смотришь, какой код выполняется, а выполняется абсолютно одинаковый код, который работает в одном случае быстрее, а в другом — медленнее. И ты думаешь, как такое может быть, что одинаковый машинный код выполняется по-разному? И начинаешь смотреть уже счетчики производительности, которые встроены в железо, в процессор.
Процессор говорит, в одной программе чуть-чуть больше промахов кеша инструкций. На каждое процессорное ядро есть 32 килобайта L1 кеша инструкций и почему-то туда стало хуже все помещаться. Может быть, проблема возникла из-за структуры устройства кеша. Из-за его ассоциативности. Какие-то куски кода попали на адреса, которые отличаются на энное число байт, кратное двум. Внутри процессора есть как бы такая маленькая хеш-таблица, и в этой таблице происходит вытеснение.
— И как такие проблемы решаются? Ты их один решаешь, или у вас там консилиум собирается? Бывают ли тупики?
— А теперь раскрою секрет, вот такие проблемы мы не решаем! Мы еще до этого не дошли. Мы просто научились наблюдать.
Можно тестировать отдельные изолированные кусочки кода, это похоже на unit-тесты. При улучшении совершенно не обязательно, что у клиентов все стало лучше работать. Они могут и не заметить разницы. А может, какой-то кусочек кода ускорился в два раза, но при этом все остальные куски кода замедлились на полпроцента, и эти полпроцента нигде не видны. Такие тесты помогают понять, когда произошло какое-то замедление, в каком именно месте произошла регрессия.
Есть и другие способы измерять производительность. Что называется, always on profiling. То есть всегда включенное профилирование на продакшене. В КликХаусе встроен семплирующий профайлер. С небольшим интервалом семплирования, всего лишь один раз в секунду, собираются стектрейсы во всех потоках. А потом по большому кластеру мы агрегируем все за неделю и делаем выводы, стал ли продукт быстрее.
— Есть же дилемма — чтобы написать более быстрый код, ты пишешь сильно менее читаемый код. Для вас это проблема в кодовой базе КликХауса?
— Мне кажется, что так делать не нужно. Действительно, если ты пишешь более быстрый код, он получается идейно сложнее. Но его нужно просто максимально подробно описать. Я сторонник того, что в коде должны быть комментарии. Сам я пытаюсь писать такой код, чтобы другой человек мог прочитать его от начала и до конца прямо как будто это учебник или пост в блоге, который этот же код объясняет.
Иногда это называют литературным программированием, но это экстремальный случай, когда пишут целиком текст или книгу, а потом внутрь вставляют кусочки кода. И все это компилируется и работает.
— В C# или Java хороший код — это максимум 200 строк на файл. Ты заходишь в любой файлик, и он умещается в экран. На C++ это вообще нереально, особенно на больших проектах. У вас есть файлы на 5.000 строк?
— Сейчас посмотрю мой любимый StorageReplicatedMergeTree.cpp, сколько там строк...
Кстати, сейчас я использую Linux, и в моей любимой среде разработки что-то напутали со шрифтами, и номера строк отображаются так, что первая цифра наполовину не видна.
Как-то я был в Индии, там особенность такая, что везде на улицах все засыпано мусором. Меня это, конечно, раздражало, но через несколько дней я понял, что привык.
Такое же ощущение может быть, когда работаешь с современными технологиями. На каждом шагу поджидает маленькая несуразность, что-то не доделано. Какой-то баг. И особенно печально, когда люди к этому привыкают. Еще хуже, когда считают, что это неизбежно, и так и должно быть.
...итак в нашем файле 6.368 строк. Это один из самых больших файлов в нашем проекте. Таких немного. В основном у нас небольшие файлы.
— Зачем КликХаус в опенсорсе?
— Изначально технология возникла для задач вообще одной команды — Яндекс.Метрики. Идея состояла в том, чтобы создать чуть более общее решение для обработки данных. И она казалась безумной, я держал эту идею в уме как мечту, которую как-нибудь все-таки удастся воплотить. Постепенно начал пилить. Где-то десять лет назад уже можно было посмотреть на рабочий вариант. Показал его коллегам, им понравилось. Артур Суилин из Вебвизора тогда был руководителем Яндекс.Метрики. Он человек технический, ему эта штука понравилась. Мы ее внедрили в Метрику для одной из задач, и я продолжил спокойно допиливать.
Постепенно к технологии появился интерес и в других отделах Яндекса. Наша разработка давала возможность использовать систему внутри Метрики напрямую для аналитиков, чтобы можно было выполнить обобщенный запрос по данным всего интернета. На самом деле, это очень круто. Потому что метрика стояла на 70% сайтов: покрывается совершенно нереальное количество трафика и можно делать глобальный запрос, чтобы посчитать что-нибудь важное.
Инструмент стал популярным внутри компании, люди стали приходить, интересоваться. Я создал документацию, в которой рассказал, как самому провести установку, какие запросы можно писать. Через некоторое время появились люди, которые пользовались инструментом уже без моей помощи.
Стало казаться, что наша технология занимает нишу, которая пока пустует. После этой мысли стало даже немного страшно. Если нишу долго не занимать, она так или иначе будет занята снаружи какой-то другой технологией.
В конце 2015-го года я перешел в группу Кликхаус (ее выделили из группы Яндекс.Метрики). Мы обсуждали идею КликХауса на опенсорсе с моим руководителем, он предложил ее Михаилу Парахину (тогда он был СТО в Яндексе). Тот дал добро. Я тогда написал мотивационное письмо: какие возможности, какие риски. Мы стали пробовать, несколько месяцев ушло на подготовку, но летом 2016 года все было готово, и мы выложили КликХаус в опенсорс. Серьезных надежд не было. У меня был такой принцип: если ничего не получится, то ну и ладно, не надо будет тратить силы. Но если полетит и все будет хорошо, то у нас будет некоторое достижение. Возможность получить это достижение перекрывала риски.
— Взлетела технология?
— Уверенно растет. Будем стараться дальше.
— Опенсорс принес какие-то плоды? Контрибьюторы со стороны приходят?
— Да, принес. Сейчас у нас 46% пул-реквестов — внешние. И даже есть случай, когда человек реализует внешнюю функциональность или исправляет баг, и вот эту функциональность как раз хотели попросить у нас внутренние заказчики. А баг исправлен до того, как вообще кто-либо внутри мог его заметить.
— Слушай, вас очень ругают за документацию.
— С документацией интересно — многие люди нас хвалят за нее и говорят, что документация — одно из наших преимуществ. И я могу сказать, что она для уровня опенсорс продукта достаточно качественная. Но не является достаточно качественной, если бы ей занималась команда хотя бы из нескольких человек. Сейчас получается, что такая команда отсутствует. И получается неидеально.
— Почему Кликхаус так сильно отличается от других БД, что даже появилось выражение "ClickHouse way"?
— Мы исходили из своих задач и брали самое простое естественное их решение, которое не обязательно соответствовало стандарту SQL. Я приведу простой пример: у нас в Кликхаусе можно написать не «селект каунт звездочка», а просто: каунт и все! И я до сих пор думаю, что это логичнее.
— Не страшно принимать такие решения? Привычка сообщества — это тоже часть простоты инструмента.
— Когда я сделал селект каунт, я вообще не парился. Тогда это не было опенсорсом. Сейчас любое решение по синтаксису я обязательно сравниванию с опытом нескольких других СУБД. И выбираю лучшее.
— Говорят, Яндекс сначала занимается собственными внутренними заказчиками и только потом — сообществом и нуждами внешних пользователей. Что думаешь про это?
— Внутренние задачи, конечно, являются приоритетными. Но удается учесть интересы и сообщества, и внутренних пользователей. В подавляющем большинстве случаев то, что нужно пользователям, нужно сообществу.
— Что думаешь про компании, которые строят целые бизнесы на внедрении КликХауса?
— Я всецело это приветствую. Чем больше будет этот бизнес, тем лучше.
— Если КликХаус вырастет на рынке, не будешь переживать, что многие решения, которые ты принял в самом начале, уже не исправить?
— Ничего, придется объяснять. Такое часто бывает. Взять линукс или BSD, в котором многие вещи тянутся из допотопных времен. Например, спрашивают, почему язык csh такой ужасный? Чем разработчик думал, когда его писал? Автора нашли (хотел сказать — откопали). Он ответил: у меня просто не было опыта. Какую технологию не возьми, везде есть какие-нибудь «грабли».
— Как тебе индустрия прямо сейчас?
— Индустрия растет вширь и покрывает все большие области. Сейчас даже возникает вопрос: писать код — это новый признак грамотности? Это как читать и писать? Мне кажется, скоро будет нормальным программировать раньше, чем читать, программировать раньше, чем ходить.
— Ты видишь проблему в том, что порог входа снизился? В индустрии много программистов разного уровня.
— Иногда порог входа работает в обе стороны. Где-то он снижается, а где-то наоборот — все труднее его перешагнуть. К примеру, сейчас практически невозможно разобраться во всех наслоениях кода. И в этом смысле порог входа только увеличивается.
— Часто программисту и не нужно понимать, как работают инструменты изнутри. Но иногда все-таки нужно, и когда такой момент наступает, приходится искать экспертов, а их почти нет.
— Это нормально. В некоторых областях поиск эксперта даже задекларирован: «Не занимайтесь самолечением, обратитесь к специалисту». Эксперты проходят долгое обучение, получают опыт и только после этого к ним возникает доверие. В нашей области такого пока нет. В каком-то смысле это даже хорошо. Настоящие энтузиасты ничем не скованы и могут проявить себя в своем творчестве.
— Не слишком ли много стало инструментов в индустрии? На любую задачу найдется сотня решений, и все их надо знать. Кажется, поэтому поверхностное знание становится нормой.
— Да, это плохо. Можно понять, почему так получилось. Старые инструменты были слишком глубоко запрятаны. Если люди не видят старое, они просто изобретают новое.
Недавно все дружно похоронили технологию flash. Раньше, если ты хотел сделать что-то интерактивное на своем сайте, ты не мог обойтись без flash. Зато ты был уверен, что на всех платформах, которые поддерживают эту технологию, все работает одинаково. Когда начался переход на HTML5, я думал так: «HTML5 — совокупность слабосвязанных технологий, которые кое-как взаимодействуют друг с другом. Технология реализована частично и везде работает по-разному. Как вообще можно говорить, что она заменит flash?» Но прошло время, и теперь почти все работает.
Эти процессы не остановить. Люди пишут новые инструменты просто потому, что хотят. Все-таки в нашей профессии есть доля творчества. Человек может плохо разбираться в вопросе, но в процессе разработки очередного велосипеда он получит много пользы лично для себя. Возможно, все, что он сделает, нанесет вред индустрии. Но он точно станет более квалифицированным специалистом. Пусть свет увидит еще 10 новых конкурирующих JavaScript фреймворков, но один из них когда-нибудь да привнесет новую идею. Людям нельзя запрещать пытаться только потому, что большинство их разработок не будут нужны.
— Современные языки программирования — что ты о них думаешь?
— Прогресс есть. Медленно, с повторением пройденного, но все становится лучше. Это не просто поступательное движение, это хождение по кругу, где каждый оборот круга — небольшое улучшение. При этом остается много технологий, которые можно описать как наслоение несуразностей. Это касается как раз-таки самых востребованных, широко используемых технологий.
Вспомнить JavaScript, который вырос из пережитков прошлого, или С++, рост которого был продиктован разными практическими соображениями. Принципы, по которым он построен, почти все разумные. Конечно, есть и неконсистентности. С++ — сложный язык и это его основная проблема. Rust, кстати, тоже находится в группе риска, он не менее сложный и становится все труднее. Чтобы программировать простые вещи, нужно чувствовать себя уверенно при использовании языка.
По пятницам мы с ребятами из КликХауса собираемся и читаем чужой код ради смеха. Возможно, когда-нибудь выйдет юмористическое видео «Разработчики КликХауса читают код и ржут». Вот недавно смотрели код на Rust. При этом никто из нас не знает этот язык. Можно открыть код КликХауса и тоже поугорать над этим.
— Разработчики часто уходят от перфоманса к удобству, жертвуют производительностью ради удобных абстракций. Это плохо?
— Обычно это неосознанная жертва. Если не следить за производительностью, она будет настолько плоха, насколько это устраивает разработчика. В коде есть тысячи мелких вещей, которые связаны с производительностью. Где-то неправильный алгоритм, где-то мы заново на каждой итерации собираем структуру данных. Когда все работает невыносимо медленно, автор может этот поправить. Но работу никто не оптимизирует, когда все приемлемо. В одних задачах это неправильно, в других — нормально.
Чуть ли не единственное решение, которое следит за производительностью по максимуму — это КликХаус. Мы действительно докапываемся, чтобы каждая штука в нашем коде работала так, как позволяет железо. А современное железо, поверьте, очень крутое! Для многих это обыденность, я и сам воспринимаю эту силу как некую магию. История человечества, вся совокупность знаний привела нас к тому, что мы имеем процессор, который обрабатывает миллиарды операций. Это нереальное достижение. Ты приезжаешь в аэропорт, видишь там авиалайнер и восторгаешься тем, как он сделан. В кармане каждый день лежит обычный телефон, и на его счет я испытываю те же самые чувства.
Невероятно важно осознавать все то, что привело к этому.
От редакции Rebrain
Что вы сами думаете про ClickHouse? Лично мы накопили уже очень много опыта в работе с ним и постоянно этим опытом делимся — рассказываем про все тонкости, где, как и что лучше применять.
Заходите к нам в сообщество — там мы постоянно разбираем различные проблемы и задачи из сферы Devops, обсуждаем вещи, которые пригодятся и на собеседованиях, и в работе.