Запрос, на который ваша база данных не может ответить

Запроснакоторыйвашабазаданныхнеможетответить

Что, если я скажу вам, что есть запрос, на который ваша база данных не может ответить? Возможно, это вас удивит. Благодаря десятилетиям усилий, базы данных являются одним из самых надежных существующих программных продуктов. Поскольку они остаются чрезвычайно популярными в своем нынешнем виде, многие инженеры полагают, что их база данных может ответить на любой запрос, который у них есть, если они готовы подождать достаточно долго.

Однако это не так. t отличное предположение. Почему? Почти все базы данных связаны одной общей чертой: они запрашивают исключительно данные в состоянии покоя. Когда вы отправляете запрос, база данных выполняет его, просматривая данные и возвращая результат. Проблема в том, что эта архитектура по своей сути делает некоторые запросы недоступными. А именно, вы не можете написать запрос, результат которого обновляется каждый раз при изменении базовых данных. Вы слепы ко всему, что происходит между двумя вызовами запроса. И это важно, если то, что вы делаете, управляется программным обеспечением .

Мы уже на месте? Завершены ли базы данных?

Настоящая конечная цель

Если бы у вас была база данных, которая могла обновлять результаты запроса каждый раз при изменении данных, вы могли бы сказать, что она является реактивной. Хотя реактивность отсутствует во многих базах данных, это основа потоков событий и потоковой обработки – при получении новых событий приложения немедленно реагируют, обрабатывая данные, чтобы предпринять какое-либо действие.

Потоковая обработка реактивность почти делает его идеальным для обслуживания запросов приложений. Хотя это может сработать, у него есть серьезный недостаток – он подрывает аккуратную абстракцию базы данных. Базы данных, в частности SQL, скрывают всю сложность, лежащую в основе выполнения запросов, индексации, управления параллелизмом, восстановления после сбоев, репликации и т. Д. Когда вы возлагаете на потоковый процессор ответственность за обслуживание запросов, вы берете компоненты, которые раньше были аккуратно скрыты вашей базой данных, и переносите их в свое приложение. Теперь вы на крючке, чтобы заставить намного больше вещей работать правильно.

Я думаю, что лучший способ – распознать скрытые отношения: потоковая обработка – это вторая половина баз данных. Базы данных управляют данными в состоянии покоя; потоковая обработка управляет данными в движении. Они просто еще не подходят друг другу.

Так что же нужно, чтобы соединить эти два мира?

Confluent работает над новым типом базы данных под названием ksqlDB , который пытается сделать именно это. Это помогает вам как запрашивать данные, так и реагировать на изменения. Но вместо того, чтобы самостоятельно управлять всей сложностью, вы взаимодействуете с ней исключительно через абстракцию реляционной базы данных, например Postgres. Для ведения журнала транзакций он использует исключительно Apache Kafka ® .

Позволь мне встать front: Несмотря на то, что ksqlDB сегодня обладает мощным набором функций, реализация его более широкого видения объединения баз данных и потоковой обработки остается амбициозной работой. Этот прогресс – тема этой статьи – зависит от большой глубокой работы, проводимой в экосистеме Kafka.

Итак, давайте посмотрим на эту глубокую работу на каждом уровне стека – от сбора данных , в хранилище, в обработку, в выполнение запроса – чтобы понять, что нужно для ответа на неотвеченный запрос.

С чего лучше начать, чем начало?

Подключение мир программного обеспечения

Всякий раз, когда вы представляете, как построить систему, управляемую событиями, легко сделать одно важное, но неверное предположение о том, как она будет работать: что события вы хотите, будет уже захвачен в потоке.

Но на практике это работает не так. События рождаются вне потоков: в других базах данных, других веб-приложениях, других серверах. Какой-то фрагмент кода где-то должен быть достаточно умным, чтобы отправлять данные в поток (или получать данные от него). Это почти всегда упускается из виду, потому что интуитивно кажется, что проблема решена; Вся крутая работа по информатике, связанная с потоковой передачей событий, о которой вы слышите, как правило, связана с обработкой или хранением. Вы, как правило, меньше слышите о копании байтов.

Но, как и все в жизни, нет ничего бесплатного. Вначале не было встроенного программного обеспечения, которое могло бы сделать это с Kafka. Вы должны были написать свои собственные специализированные программы для передачи данных масштабируемым, отказоустойчивым и правильным способом. Вы должны были сделать это для каждой системы данных, с которой вы хотели интегрироваться, источника и приемника. Это не просто надоедливое ворчание; это довольно сложно построить для систем, которые изначально не предоставляют механизм сбора измененных данных.

Если эта часть работает неправильно, все остальное не имеет значения. Какой в ​​этом смысл без событий? Первым делом нужно было создать структуру, чтобы мы могли изолировать всю общую сложность взаимодействия с внешними системами. Kafka Connect был добавлен в Apache Kafka в 2020, чтобы сделать именно это.

С тех пор миссия Connect была восхитительно целеустремленной: построить соединение между все. Сейчас больше, чем интеграции соединителей , многие из которых являются жемчужинами инженерной мысли. Рассмотрим набор соединителей Debezium , которые осуществляют сбор данных об изменениях в MySQL, Postgres, MongoDB. , и друзья. Или возьмите соединители, которые интегрируются с приложениями SaaS, такими как Salesforce . Есть даже коннектор для получения данных из Oracle .

Не в фокусе приходит сила. ksqlDB строится на этом, чтобы упростить отправку и прием событий с помощью управления коннекторами. Используя SQL, вы можете в интерактивном режиме создавать объекты соединителя:

 СОЗДАЙТЕ ИСТОЧНИК СОЕДИНИТЕЛЯ с помощью ( 'connector.class' = 'JdbcSourceConnector', 'connection.url' = 'jdbc: postgresql: // ...', 'topic.prefix' = 'rider', 'table.whitelist' = 'geoEvents, profiles', 'key' = 'profile_id', ...);  
 

Разбейте лопаты - байты теперь в движении. Соединители работают отказоустойчивым и масштабируемым образом на серверах ksqlDB, и все это благодаря Kafka Connect.

Журнал можно зависеть от

После того, как вам удалось захватить события, вам понадобится дом для них. В базах данных мы называем это журналом. Если журнал, хранящийся в виде потока Kafka, станет основой вашей архитектуры, у вас не может быть никаких сомнений в его стабильности.

Но десять лет назад это было не так. Не совсем так. Было множество вопросов без ответов о том, каково будет использовать Kafka для критически важных случаев использования.

Да, это круто, мы сказали, Но может ли он хранить все мои данные? Kafka раньше хранил данные только на дисках брокеров , что означало, что хранилище было привязано к брокеру с наименьшей емкостью. Вам приходилось выбирать между выделением дорогих дисков большой емкости и хранением меньшего объема данных. Но было еще хуже. Многие варианты использования, такие как аудит и машинное обучение в Интернете, не могут работать с потоками с коротким сроком хранения.

Что может быть лучше? Хранилища объектов, такие как Amazon S3 и Google Cloud Storage, предлагают практически неограниченную емкость хранилища. Если бы Kafka использовал эти сервисы как серверные части хранилища, его можно было бы заставить хранить огромные объемы данных. В 43864, введен Confluent Многоуровневое хранилище , чтобы это стало реальностью. А для Apache Kafka KIP - 501 направлен на введение аналогичных функций. Этот метод позволил хранить неограниченные объемы данных в потоках по абсурдно низкой цене.

Конечно, но сможет ли он пережить региональный сбой? Мы живем в мире, который всегда включен, 260 × 7. Выход из строя центра обработки данных больше не просто неудобен - он может нанести серьезный ущерб. Если Kafka будет использоваться для чего-то критически важного, вы должны иметь возможность рассчитывать на то, что ваши данные будут доступны, даже если вся зона доступности потеряна. До недавнего времени обычным методом защиты Kafka от сбоев было простое «растягивание» узлов кластера по центрам обработки данных. Эта идея несколько сработала, но была далека от совершенства. Чем дальше узлы удаляются друг от друга географически, тем сложнее становится управлять кластером.

Нет ни одной души, которая работала бы с Kafka и не хотела бы более легкого способа работы. выполнять репликацию между центрами обработки данных. И в 43864, он получил один, фактически два. Apache Kafka добавил георепликацию (под название проекта MirrorMaker2), который представляет собой часть программного обеспечения, которое находится в середине двух кластеров Kafka, реплицируясь между ними (оно искусно построено на Kafka Connect). Второй был дополнением к Confluent под названием Cluster Linking - вместо использования посредника для репликации он использует собственный протокол репликации Kafka для прямого копирования данных.

Хорошо, но могу ли я продолжать? Когда дело доходит до инфраструктуры, все зависит от вашего уверенность в том, что он будет в сети. Если с ним трудно работать, он не будет работать и не принесет вам никакой пользы. Раньше было сложно запустить Kafka самостоятельно. Он не был так проверен в боях, как сегодня, и ни у кого не было времени специализироваться на его эксплуатации. Вам нужно было тщательно выбрать размер кластера, а затем контролировать всех, кто его использовал, в соответствии с вашими административными правилами.

Программное обеспечение как услуга в облаке полностью изменило это. Kafka больше не подходит только для больших проектов или больших рабочих нагрузок. Вы можете получить недорогой кластер Kafka от многих поставщиков облачных услуг, например Confluent Облако - с SLA. Вы защищены от всей тяжелой работы по поддержанию здоровья брокеров. Теперь запуск Kafka - это чья-то проблема.

Проще говоря, база данных - ничто без своего механизма хранения. Точно так же ksqlDB - ничто без Kafka. Это полезно только потому, что его журнал транзакций вместительный, удобный, надежный и недорогой. Но что нам делать с этими данными после того, как мы их сохранили?

Обработка потока кусочков головоломки

Поток, полный событий, полезен только в том случае, если его можно обработать. В этом суть того, где потоковая обработка встречается с базами данных - вы пишете запросы, результаты которых пересматриваются, как только получена новая информация.

Для новичков эта идея звучит экзотично, но ее легко понять. проведем аналогию: обработка данных похожа на решение головоломки. При традиционной обработке запросов к базе данных каждый запрос похож на новую головоломку. Вам даны все части заранее, но вы не можете увидеть картину, которую покажет головоломка, пока все ее части не будут собраны вместе.

При потоковой обработке запросы выполняются бесконечно - это похоже на непрерывное решение одной головоломки, когда вам дается только несколько частей за раз. Вы сразу же как можно лучше вставляете полученный кусок в головоломку. В отличие от традиционной обработки запросов, потоковая обработка позволяет увидеть картину головоломки по мере ее развития. Это похоже на решение настоящей головоломки - вам не нужно ждать до конца, чтобы узнать, что он откроет.

Аналогия работает потому что увидеть грань головоломки - все равно что увидеть результаты запроса. Но это не только привлекательно, потому что вы можете получать результаты запроса раньше. Это привлекательно, потому что промежуточные состояния запроса часто имеют ценность сами по себе.

Полезность потоковой обработки очевидна, но как вы построите систему для этого? До Кафки ответ не был очевиден. Потоковая обработка была и остается новой парадигмой программирования. В то время у него были ограниченные API, и теория, лежащая в основе этого, все еще разрабатывалась. Давайте посмотрим на три наиболее важных концепции, которые развились с тех пор: ti я, масштабирование и синхронизация.

Время

Первый раз. Чтобы отойти от метафоры, задача обработки потока никогда не заканчивается, потому что вы еще не знаете, все ли у вас есть части. Это отражает реальную жизнь - трудно понять, есть ли у вас когда-либо все данные, которые вы получите. В 2017, В документе Google Dataflow исследуется это противоречие, оформленное как компромисс между правильностью, задержкой и и стоимость.

Одно из последствий незнания того, есть ли у вас все данные, - это получение данных не по порядку. Данные о событии по определению содержат метку времени - время, когда событие произошло. Что произойдет, если вы получите «старые» события после «новых» событий? Это может произойти во многих ситуациях.

Вот небольшой пример. Рассмотрим простую программу обработки потока, которая подсчитывает, сколько денег зарабатывает бизнес каждый день. По мере поступления заказов суммируется выручка за любой сегодняшний день. А теперь представьте, что партия заказов поступила с опозданием. Заказы были размещены вчера, но вы получили их только сегодня. Соответствующее действие - скорректировать дневную выручку за вчерашний день. Но если ваша программа умеет только прибавлять к сегодняшнему результату, вы тост.

Раньше вам приходилось выбирать себе яд: либо выбросить данные, либо или используйте пакетный процессор, чтобы позже устранить проблемы. Последняя, ​​известная как лямбда-архитектура, была особенно пагубной, поскольку означала, что вам приходилось писать свою программу дважды - как в потоковой обработке, так и в структуре пакетной обработки.

Нет единого вещь, которая изменилась, чтобы упростить обработку потока вне очереди. Скорее, в течение по сегодняшний день.

Кафка Потоки , Flink и Dataflow - все встроенные API-интерфейсы, которые по умолчанию в основном обрабатывают неупорядоченные данные. Это означает, что кроме указания фреймворку потоковой обработки, где найти метку времени, вам не нужно ничего делать, чтобы получить правильные ответы. Большинство API-интерфейсов достигают этого с помощью оконное управление - окна переворачивания, прыжков, скольжения и сеанса помогают вам разрезать время по-разному, но все они позволяют прозрачно управлять беспорядком.

В то же время нам приходилось иметь дело с данными, которые «слишком поздно» стали полезными. Kafka Streams впервые применил концепции времени потока, льготных периодов и удержания. Flink разработал водяные знаки и унифицированный API для пакетной и потоковой обработки.

Программирование со временем, вероятно, всегда будет сложным, но прогресс неоспорим.

Windowing

Шкала

Теперь масштаб. Что побуждает кого-то создавать архитектуру с потоками событий? Одна из причин - часто масштабируемость. Когда вы поддерживаете состояние с помощью потокового процессора, вы децентрализуете место выполнения ваших запросов; вместо того, чтобы запускать их все вместе на серверах баз данных, вы размещаете их в разных службах приложений. Это позволяет вам настроить, сколько ресурсов выделяется для каждого запроса. Если у вас есть запрос, который требует обработки большого количества данных, вы можете добавить больше машин для распараллеливания работы.

Это очень полезно, но как это работает на практике?

Представьте, что у вас есть кластер из двух узлов, обрабатывающих запрос с отслеживанием состояния. Два узла разделяют пространство ключей и создают локализованное агрегированное состояние. Что произойдет, если вы добавите в кластер третий узел? Вначале это был рецепт боли. Что вам нужно сделать, так это перераспределить пространство ключей и равномерно перетасовать данные по трем узлам. Перетасовка данных всегда была сложной проблемой, но в системе с постоянным потоком она становится еще сложнее. До недавнего времени решение этой проблемы Kafka Streams заключалось в том, чтобы остановить мир. Произойдет глобальная перебалансировка, и доступность будет восстановлена ​​только после завершения перебалансировки. Чем больше у вас было состояний, тем дольше это длилось.

Глобальная перебалансировка - до свидания. Поздороваться с кооперативная, пошаговая ребалансировка . Добавлено в 1622738024111, добавочная перебалансировка помогает Kafka Streams перетасовать минимальный объем данных между узлами при изменении размера кластера. В системах распределенной обработки невозможно избежать перетасовки, но вы можете минимизировать количество пауз и перемещения данных. Kafka Streams теперь делает это по умолчанию.

Синхронизация

Наконец, синхронизация. Если события - это валюта вашей системы, важно, чтобы кассир точно выполнял ваши инструкции. Но всякий раз, когда задействованы распределенные системы, обязательно найдутся простые способы ошибиться. В частности, когда распределенные узлы обмениваются сообщениями, сбои могут создавать повторные попытки, которые, в свою очередь, могут создавать дублирующиеся сообщения, потерю сообщений или частичное выполнение инструкций.

Кайл Кингсбери зарабатывал себе на жизнь, показывая, какой это может быть беспорядок.

Когда Кафка взлетел, он не мог стать сильным. гарантии того, как будут обмениваться сообщениями в сценариях сбоя. Не было никакого способа обойти это - это низкоуровневые гарантии, которые должна предоставить вам инфраструктура.

Если бы Kafka собирался использовать для критически важных задач. рабочих нагрузок, это нужно было изменить. Итак, в 1622737881635, добавлен Apache Kafka семантика ровно один раз (EOS). EOS означает три вещи: отправку идемпотентных сообщений, транзакции и идемпотентную обработку с отслеживанием состояния. Все три необходимы для полного решения проблемы надежной обработки сообщений. Благодаря этому, Kafka стал доверять в ситуациях, когда просто нет места для ошибки.

Где во всем этом ksqlDB? Удачно разгадывая головоломки. Данные, не соответствующие порядку, обрабатываются прозрачно благодаря API Kafka Streams. Масштабирование кластера работает без особых усилий. И семантика ровно один раз может быть активирована с помощью одного флага сервера.

Мы прошли весь стек: от сбора данных до хранения и обработки. Что осталось? Самая яркая особенность баз данных - это то, что осталось.

Запросы под одной крышей

Закрой свои (образные) глаза. Подумайте о том, чтобы сесть за ноутбук и использовать базу данных. Что вы видите?

Вероятно, вы видите, как печатаете какой-то текст в консоли. Этот текст, вероятно, является SQL.

Базы данных на основе SQL доминировали на протяжении десятилетий, и это правильно. Их модели запросов просты в использовании и понятны. Если потоковая обработка должна стать второй половиной баз данных, нам необходимо разработать аналогичную абстракцию, охватывающую все, о чем мы говорили до сих пор.

ksqlDB - одна из попыток этой абстракции.

Его уровень запросов, построенный на SQL, использует простую архитектуру клиент / сервер - точно так же, как работает Postgres. Вместо того, чтобы напрямую связываться с базовыми компонентами, вы используете SQL для создания потоков, проверки таблиц, получения материализации и выдачи запросов. Вы видите только два уровня: хранилище (через Kafka) и вычисление (через ksqlDB). Оба упруго масштабируются независимо друг от друга.

Если вы хотите запросить данные, получить доступ к таблицам состояния очень просто. Поскольку вся работа по обновлению состояния вашего запроса (подгонка каждой части головоломки) происходит во время обработки, чтение результатов запроса (видение лица головоломки) происходит предсказуемо быстро. Нет никакой работы. Хотя эта идея проста в теории, построить вашу архитектуру вокруг нее сложнее.

Например, в распределенном кластере, как вы найдете правильный сервер для выполнения запроса? А что должно произойти, если данные, которые вы ищете, недавно переместились на другой сервер? Как сделать так, чтобы сетевое взаимодействие между клиентом и серверами не было проблемой для всех, у кого есть запросы?

ksqlDB упрощает эту задачу благодаря поддержке двойных запросов. Когда вы отправляете запросы на серверы ksqlDB, он может автоматически направить ваш запрос на нужный узел - даже в случае сбоев. Все это благодаря КИП - 600 в Kafka Streams, который расширил свои API хранилища состояний для поддержки информации о репликах. Используя это, ksqlDB может обслуживать запросы на вытягивание (стиль запроса / ответа) и запросы push (стиль потоковой передачи).

Так вот оно? Мы уже на месте?

Дорога впереди

Несмотря на весь наш прогресс, мы еще не достигли его. Книгу можно заполнить оставшимися пробелами, но пока я кратко коснусь трех из них. В следующем посте я подробно расскажу о других из них.

Первая область, в которой есть ряд открытых проблем, находится на вершине стека, на уровне запросов. Для поддержки запросов в стиле запрос-ответ ksqlDB должен обрабатывать специальный SQL. Сегодня он имеет более ограниченную выразительность, ограниченную его способностью генерировать дополнительные индексы. А для поддержки запросов в стиле потоковой передачи язык SQL необходимо переосмыслить и расширить. Постоянно действующий комитет по стандартам (

DM 200 Технический комитет INCITS ), состоящий из таких компаний, как Microsoft, Google, Oracle, IBM и Confluent, попытка решить эту проблему.

Другая часть картины, которая требует большего внимания, - это согласованность с отказоустойчивостью как между репликами, так и между источниками / приемниками. При прочих равных легче создавать приложения для систем данных с более сильными гарантиями согласованности, чем более слабые. Сегодня ksqlDB - это отказоустойчивая, в конечном итоге согласованная система. Другие проекты приближаются к этому в обратном направлении, начиная с строгой согласованности и отсутствия отказоустойчивости. Конечная цель явно состоит в том, чтобы получить и то, и другое.

Наконец, в мире потоковой обработки есть скрытая жемчужина, о которой стоит помнить. Одним из преимуществ использования потоковой обработки для материализации состояния является то, что вы можете выбрать серверную часть хранилища. Если вам нужно выполнить быстрый поиск, вы можете использовать хранилище ключей / значений. Если вам нужно делать аналитические запросы, вы можете подключить колоночное хранилище. Реляционные базы данных в некоторой степени поддерживают заменяемые механизмы хранения, но потоковые процессоры традиционно предоставляют гораздо больше возможностей. Сегодня ksqlDB использует выбор RocksDB. Но в более зрелой версии этот выбор следует вернуть вам, чтобы восстановить гибкость.

Что дальше?

Базы данных и потоковая обработка все чаще становятся двумя сторонами одного и того же монета. На данном этапе инженерной истории металл этих технологий все еще сливается воедино. Но если это произойдет, 32 Через несколько лет определение базы данных будет расширено, и потоковая обработка станет его естественной частью.

Это на данный момент в сообщении в блоге. что вы обычно найдете призыв к действию - попробуйте учебное пособие или отправьте свое резюме на вакансию. Но если ты прочтите это далеко, я хочу мотивировать вас попробовать что-то другое: поработать с абстракциями; читать научные статьи; познакомиться с новыми людьми в области вычислений. Выявление скрытых взаимосвязей - например, между базами данных и потоковой обработкой - является ключом к улучшению программного обеспечения. И это действительно весело.

Майкл Дрогалис - руководитель отдела продуктов для потоковой обработки Confluent, где он работает над направлением и стратегией, лежащими в основе всего, что связано с вычислениями. Перед тем, как присоединиться к Confluent, Майкл работал генеральным директором Distributed Masonry, программного стартапа, который построил хранилище потоковых данных. Он также является автором нескольких популярных проектов с открытым исходным кодом, в первую очередь Onyx Platform.

Leave a comment

Your email address will not be published. Required fields are marked *