Однажды я работал дата-инженером в стартапе. Он быстро рос и в какой-то момент решился на покупку одной крупной компании. Там было больше сотни сотрудников — оказалось, почти все из Индии. Пока наши разработчики возились с экзотическим кодом, не поддающимся расшифровке с наскока, мое внимание привлек индийский отдел мониторинга.
Чтобы мониторить сеть и сервера, можно использовать самый разный софт. Главное — быть уверенным: если что-то пойдет не так, то сработает алерт. Вы увидите уведомление и успеете все починить. У них же было свое представление о мониторинге. Представьте, несколько комнат со столами, стульями и огромными плазмами на стенах, внутри сидят почти два десятка человек. На каждый монитор выведены разноцветные графики и рядом приклеены бумажки с номерами телефонов.
Работа этих двадцати людей заключалась в том, чтобы сидеть и смотреть на графики, а если линия вдруг окажется выше приклеенного рядом стикера — звонить по номеру телефона, который там написан, и бить тревогу. Вот они сидели и не отрываясь следили.
Покупка компании обошлась недорого, но содержание такой инфраструктуры стоило заоблачных денег. Индусы использовали дорогущую Vertica, где, кроме оплаты железа, нужно было еще отстегивать за лицензию. Мы решили попробовать переезд на ClickHouse. Это практически бесплатный аналог Vertica. Оба продукта работают по схожему принципу: колоночное СУБД с шардированием, с партиционированием данных.
И это было то еще приключение.
Киллер-фича ClickHouse — конечно, экономия денег
Как раз то, что нам было нужно. ClickHouse умеет писать миллионы ивентов в секунду и также быстро читать. Если правильно организовать агрегационную таблицу в ClickHouse, она будет выполняться за минуту, когда в классических агрегационных базах (например, PostgreSQL) запрос выполняется час.
Я загорелся ClickHouse на одном кейсе, когда провел тест на сжатие с новенькими кодеками: тот же DoubleDelta ужал наши полуслучайные последовательности в пять раз! И ClickHouse не смущает количество данных, если подобрать правильный ключ сортировки и степень детализации индекса в настройках MergeTree.
В результате увидел, что данные, которые на HDFS занимали гигабайты, в ClickHouse уместились в 700 с хвостиком мегабайт, а скорость запросов по ним была на порядок выше. Особенно, когда получается удачно переписать стандартный «хакерский» SQL-запрос на тыщу строк во что-то максимально понятное ClickHouse, с использованием корректных встроенных функций, массивов, агрегатов и других подходящих альтернатив.
Но в то время у инструмента был большой минус — высокий порог вхождения. Результат комбинации маленького на тот момент комьюнити, не сильно выходящего за пределы СНГ, фундаментальных отличий ClickHouse от «обычных» СУБД и невнятной документации. Приходилось проводить личные опыты: грузить в него TSBS и экспериментировать с функциями, разными версиями, настройками движков и так далее — доходило даже до флагов компиляции. Драйвер существовал для галочки — он использовал http-протоколы ненативно, просто обертка над Rest клиентом.
ClickHouse постепенно допиливался, было много багов, не хватало множества критических фич, альтернативами удобнее пользоваться и легче поддерживать, но они все обходятся в разы дороже. Кликхаус опенсорсный и мощный, но в нем не разберешься без стакана. Он похож на стереотипную русскую вещь — неидеальный, шероховатый, дешевый. Но сжатие и скорость работы все перекрывают.
Как построить бэкенд так, чтобы ничего не падало, не сжирало тонну денег, могло хранить и обеспечивать доступ к отчетам?
При условии, что есть миллиарды строк данных, терабайты, километры.
Компания занималась монетизацией пираток. Человек пиратил андроид-приложение, не платил за него, но видел рекламу. Для того, чтобы посчитать клиента по биллингу, посмотреть, сколько он накликал рекламы, компания начала собирать статистику. До моего прихода там были написаны собственное SDK и бэкенд. PHP принимал JSON ивент, его парсили и писали в MySQL. Никаких пулов соединений не было, пришел ивент — открыли и записали.
Когда нагрузка стала расти (несколько тысяч событий в секунду), эта система перестала вывозить. Бэкенд-разработчик узнал про Hadoop, HDFS и решил его применить. Собрали кластер из нескольких машин. Идея была такой: просто пишем JSON-файлы, запихиваем в Hive. И вот уже все считается и работает.
Когда ребята начали мигрировать биллинг на Hive, поняли, что у них резко вырос чек за кластер. Все хранилось в виде несжатых JSON-файлов. К тому же HDFS и Hadoop не были заточены на риал-тайм вычисления. Приходилось планировать любую джобу заранее. Ставили на всю ночь, утром видели результат в виде огромной кучи неструктурированных данных, которые лежат прямо в тексте. И все это за деньги! Скорость никакая, запрос делать долго, на выходе — свалка. Это никого не устраивало.Когда я начал выяснять, как устроена текущая архитектура проекта, то оказалось, что Spark используется в автономном режиме на нескольких узлах, что выглядело подозрительным и специфичным. Разобравшись в скрипте запуска, я понял, что текущие настройки приводили к тому, что узлы грузились на все двести, а RDD все равно читались в один поток.
После некоторого разбирательства я выяснил, что это было сделано не из-за каких-то архитектурных ограничений. Тот же относительно большой HDFS был корректно настроен как кластер, с резервированием — нареканий по этой части инфраструктуры и железа не было.
Тем не менее, при правильном распараллеливании джобы на выходе получались не совсем корректные данные. Документация по коду, как это традиционно в наших краях, была устаревшая, поэтому пришлось максимально сосредоточиться, чтобы эффективно раскурить текущие исходники на Java, понять желаемую бизнес-логику и починить багу. В итоге получилось совершенно новое приложение на Scala, которое работало настолько лучше, что отдел инфраструктуры смог спланировать снижение стоимости поддержки бэкенда в тысячи долларов!
И наконец мы начали добавлять запись в ClickHouse. Исходный код сервера будет достаточно понятным любому, кто знает C++. Он также иногда покрыт тестами, а если и нет, то зачастую можно найти тест, реализующий схожий кейс. Так что в итоге у нас появился свой отказоустойчивый драйвер на Scala, работавший по TCP, в бинарном Native формате, учитывающий конфигурацию кластера и позволявший нам максимально эффективно писать в несколько потоков.
Я решил еще доработать бэкенд и рискнул — убрал HDFS. Поставил нормальный кластер Kafka, бэкенд стал писать в нее, из Kafka все читалось консьюмером и писалось в ClickHouse. При этом я не исключил кластер HDFS из схемы совсем, сделав из него подобие бэкапа: данные залетали и в урезанный HDFS тоже.
В какой-то момент встала задача переводить все остальные сервисы и отчеты на работу с ClickHouse. Большинство было переведено в процессе создания нового приложения, но оставалось еще много работы касательно того, куда эти данные планировалось в дальнейшем интегрировать.
Но главная проблема оказалась не в самом ClickHouse — а в том, что никто не мог сходу в нем разобраться
Если для того, чтобы научиться эффективно писать в ClickHouse и создать production-ready сервис, достаточно было только моих вложений, то с запросами и, в целом, с полноценным использованием DWH ситуация обстояла несколько иначе.
По опыту получалось, что задачи, которые отдел аналитики и разработчики раньше могли решить «с наскока» в каком-нибудь Hive или MySQL, в ClickHouse так сходу не решались – где-то функцию надо использовать, где-то JOIN из-за дистрибуции данных некорректный и т.д.
И хорошо еще, если разработчик заподозрил неладное с запросом и обратился, если не к документации, то хотя бы в чат. Но бывало и так, что ошибки при переносе оставались скрытыми. В таких случаях все выяснялось уже тогда, когда было слишком поздно – данные либо попадали в отчеты, либо так или иначе светились в клиентских кабинетах.
Конечно, такое можно сказать про любые относительно молодые технологии. Но в нашем случае также были баги, когда по документации и отзывам запрос должен работать, а он приводил к падению сервера или некорректному результату.
Например, можно вспомнить раннюю поддержку UUID, когда запрос вида:
```
SELECT * FROM db PREWHERE uuid != '00000000-0000-0000-0000-000000000000'
```
Приводил к segfault.
Или когда можно было случайно потерять данные в процессе дедупликации реплицированных партиций. Уникальных случаев у комьюнити наберется ого-го! Поэтому получается, что иногда даже полезнее и достаточно искать свою проблему именно в GitHub, в Issues, по ключевым словам.
А потом оказалось, что данные из ClickHouse слишком трудно визуализировать
Тот же Hive предлагал инструменты, которые позволяли писать запросы и делать визуализацию. Поначалу мы использовали Tabix. Это довольно примитивный клиент, он ходит напрямую в ClickHouse и отображает в браузере результат в виде таблички и простых графиков. Но в итоге взяли инструмент поинтереснее. Redash как раз выкатил бета-версию поддержки ClickHouse.
Параллельно у нас появилась часть данных на базе Redshift. В какой-то момент компания предложила брать данные из ClickHouse и перекладывать в Redshift (который, по сути, обычный SQL и можно использовать инструменты желанной визуализации). Но идея отпала сама собой — я просто посчитал, сколько будет стоить кластер Redshift, который поддержит такой поток данных с ClickHouse. Мы тратили около тысячи долларов, если бы заморочились с Redshift — платили бы все 30 тысяч. Поэтому продолжили работать с ClickHouse через Redash.
Но все пошло прахом, когда мы решили прикрутить к ClickHouse Tableau и в итоге влетели на 70 тысяч долларов!
Tableau — это известная визуализация для баз данных. Когда мы решили это провернуть, официальной поддержки ClickHouse там не было. Зато у них была поддержка PostgreSQL. Какой-то безумец подсказал, что в PostgreSQL можно писать кастомные скрипты и протоколы форвардинга. Через питоний скрипт скрестить ClickHouse и PostgreSQL и добиться визуализации в Tableau! Это была очередная провальная идея. Данные шли только с PostgreSQL. Смысла в этом не было никакого.
Но наш аналитик настаивал. Ему нравился Tableau — красивый, понятный, никаких тебе запросов SQL делать не надо, все кнопочками. И нам его все же купили. Потратили около 70 штук и принялись танцевать с бубном вокруг покупки.
Мы даже созвонились с продажниками из Tableau и убеждали их подружить свой продукт с новейшей российской технологией. Уже тогда было понятно, что ClickHouse потихоньку завоюет весь мир. Они лишь вежливо выслушали нас. Что забавно, недавно Tableau сделал кое-какую поддержку драйвера для ClickHouse. Не прошло и двух лет!
Перевести отчеты с Redash на Tableau у нас так и не получилось — деньги улетели на ветер. Хорошо, что к тому моменту часть сотрудников освоила ClickHouse — я потихоньку всех обучал. Оказалось, что он удобен для андроид-разработчиков и предлагает даже больше возможностей, чем красавчик Tableau.
Самая большая проблема ClickHouse — в нем никто не шарит. Там много подводных камней, которые нигде не описаны. Хорошая технология с плохой документацией.
Потребность в использовании есть, но разбираться, как это работает — времени нет. Поэтому и случаются разные казусы, вроде целых компаний, которые зарабатывают на консалтинге по ClickHouse.
Сейчас он стал сильно проще, но это по-прежнему не тот продукт, которым можно пользоваться сразу из коробки. Зато когда он таким станет — всяким Vertica и Redshift можно будет сворачивать свой бизнес.