Clickhouse — это ориентированная на аналитику система баз данных с открытым исходным кодом, состоящая из 1,5 миллионов строк кода, в основном на C++, заведомо небезопасном языке с точки зрения сокрытия ошибок, которые могут быть использованы злоумышленниками.
Часто пишут, даже здесь, в The New Stack, что язык программирования Rust может заменить C/C++ благодаря его превосходному управлению памятью и безопасности потоков. И существует множество крупных баз кода, таких как ядро Linux (C) и Windows (C++), написанных на некоторых вариантах языка, которым уже несколько десятилетий, поэтому многие задают себе одни и те же вопросы.
Разработчики Clickhouse пошли по этому пути с целью преобразовать функциональность Clickhouse, написанную на коде C++. А может быть, даже переписать всю саму кодовую базу.
Оперативный вопрос был: «Если бы мы начали сегодня, написали бы мы Clickhouse на Rust?» — спросил Алексей Миловидов, технический директор и соучредитель Clickhouse, который обсуждал результаты в докладе на виртуальной конференции P99 ScylaDB.
В конце концов, основные разработчики выбрали более поэтапный путь миграции, объяснил Миловидов. Сначала они интегрировали Rust в систему сборки, затем построили модули для различных функций.
По пути они столкнулись с многочисленными проблемами, включая обеспечение воспроизводимых сборок и управление зависимостями.
«Rust может быть идеальным, но когда вы используете C+ и Rust вместе, это может стать проблематичным», — посоветовал Миловидов.
Цена C++ — огромная система сборки
Как отметил Миловидов, написание критически важного приложения на C++ по-прежнему имеет множество преимуществ. «Он хорошо известен. Он широко известен. Он довольно популярен. Легко нанимать людей со знанием C++. В университетах до сих пор преподают C», — сказал он.
Но использование C++ требует «столько усилий», посетовал он. «Почти неизбежно» вы столкнетесь с проблемами безопасности, связанными с повреждением памяти, ошибками сегментации или гонками, добавил он.
Фактически, Clickhouse в конечном итоге создала «гигантскую» систему непрерывной интеграции на базе CMake только для того, чтобы гарантировать выявление и исправление всех типов ошибок.
В среднем из 70 запросов на включение и 145 коммитов в день система CI производит «десятки миллиардов тестов», что на самом деле представляет собой «десятки миллионов» отдельных тестов, выполненных в различных комбинациях — и все это для того, чтобы гарантировать, что новый код не содержит новых ошибок.
C++ — это боль? У Миловидова на эту тему был целый слайд…
Ржавое путешествие
«Так, возможно, пришло время переписать на Rust», — задавалась вопросом основная команда разработчиков. Язык предлагал как память, так и потокобезопасность. Он также предлагал больше библиотек, особенно для новых стандартов данных, таких как Apache Iceberg. И этот язык, казалось, привлекал всех молодых, амбициозных инженеров-программистов.
Тем не менее, полное переписывание Clickhouse на Rust займет годы.
Вместо этого команда выбрала итеративный подход, при котором различные части системы Clickhouse можно было переделать в Rust. Они использовали Corrosion для интеграции с CMake.
Во-первых, они добавили в SQL небольшую функцию для хеширования BLAKE3, написанную на Rust и обернутую для C++. Затем они дополнили интерфейс командной строки clickhouse-client улучшенной историей и навигацией благодаря стороннему разработчику. Они также приняли запрос на получение альтернативы SQL — библиотеки PRQL (язык конвейерных реляционных запросов), написанной на Rust.
Поскольку их уверенность в Rust росла, проекты стали больше. Следующим тестом Rust была интеграция основанной на Rust библиотеки для нового формата Delta Lake — библиотеки Delta-kernel-rs. Это был случай, когда библиотека стала доступна в Rust раньше, чем она станет доступна (если вообще когда-либо станет доступна) в C++.
Clickhouse мог бы написать собственную библиотеку на C++ для Delta Lake, но работа была бы «бессмысленной», сказал Миловидов. Жаль бедного программиста, который будет тратить время на написание кода для анализа файлов JSON и перенаправления HTTP-запросов. Было проще использовать официальную версию Databricks на основе Rust.
Опасности, связанные с Rust и C++
Благодаря этим экспериментам разработчики Clickhouse узнали о некоторых недостатках Rustlang, особенно при использовании совместно с C++.
Одной из проблем были воспроизводимые сборки, необходимые для обеспечения безопасности кода и отсутствия случайной загрузки откуда-либо из Интернета. Clickhouse прошла процесс обеспечения воспроизводимых сборок на C++, но с Rust им пришлось продумать процесс, как снова обеспечить герметичность сборок.
Написание оболочек C++ для программ на Rust также является непростой задачей. Разобраться, выделять ли память в C++ или Rust, может быть непросто. Инструменты фаззинга и система CI Clickhouse помогают здесь найти ошибки.
Были различия в том, как каждый язык вел себя под принуждением.
По сравнению с C++, программы и библиотеки на Rust, по мнению Миловидова, склонны слишком сильно паниковать. Паника может быть вызвана ошибкой (что указывает на необходимость более тщательного тестирования библиотеки). Или автор кода использовал аварийное завершение вместо вызова исключения (что, как правило, не одобряется сторонниками Rustace).
Panic хорош для пакетных заданий, но гораздо менее эффективен для серверных и интерактивных приложений, работающих в режиме реального времени.
«Библиотеки на Rust склонны слишком часто использовать Panic, даже когда это неуместно, и нам приходится находить и исправлять все эти случаи, чтобы избежать резкого завершения работы нашего серверного приложения», — сказал Миловидов.
Rust-коду не следует так паниковать, утверждает Миловидов.
И так же, как команда Clickhouse обнаружила ошибки, требующие исправления в библиотеках C++, они также нашли множество ошибок в библиотеках Rust.
Миловидов также углубился во многие особенности, которые возникают именно при смешивании C++ и Rust в одной среде, а также конкретные вопросы, связанные с использованием очистки, управлением перекрестными зависимостями и кросс-компиляциями, а также компоновкой кода для разработчика. И многие из этих проблем связаны со сложностью необходимой системы сборки.
Еще один неожиданный побочный эффект перехода на Rust: больше зависимостей. На всю кодовую базу Clickhouse было всего 156 зависимостей. Когда были внедрены модули Rust, они обнаружили, что им приходится управлять еще 672 транзитивными зависимостями Rust (все еще не так много, как с NPM, пошутил Миловидов).
Вывод от Clickhouse
Во всяком случае, на данный момент Clickhouse решила не переписывать всю систему баз данных на Rust. Но он настолько уверен в языке, что позволяет сторонним участникам отправлять свои собственные дополнения Clickhouse на этом языке.
«Rust — отличный язык», — сказал Миловидов.
Чтобы услышать всю презентацию, зарегистрируйтесь на P99 Conf.
ТЕНДЕНЦИОННЫЕ ИСТОРИИ YOUTUBE.COM/THENEWSTACK Технологии развиваются быстро, не пропустите ни одной серии. Подпишитесь на наш канал YouTube, чтобы смотреть все наши подкасты, интервью, демонстрации и многое другое. ПОДПИСАТЬСЯ Группа, созданная в Sketch. Джоаб Джексон — старший редактор The New Stack, специализирующийся на облачных вычислениях и системных операциях. Он освещал вопросы ИТ-инфраструктуры и ее развития более 30 лет, в том числе работал в IDG и Government Computer News. До этого он… Подробнее от Джоава Джексона