Инженер и данные
721 subscribers
39 photos
30 links
Канал про инженерный подход к работе с данными


Автор: Андрей Демидов - lead data engineer.
Связаться: @andrewdemidovv
Download Telegram
Channel photo updated
Meta data или данные о данных

✏️ Meta data - это данные о данных. То есть это информация именно о самой записи, о строке: откуда она взялась, кто записал, когда создана запись, когда изменена и многое другое.

Это важно знать и записывать, чтобы иметь больше контроля над данными, чтобы знать больше деталей о конкретно этой записи (строке) в этой таблице. Иметь её "паспорт". 💪

На практике это просто дополнительные колонки в той же таблице. Ну или если у вас json, то дополнительный meta объект внутри. При этом их стоит явно отделить от данных, например используя префикс. Мы вот используем meta_.

Еще раз подчеркну, что важно не путать мета данные и данные!
Вот несколько примеров, объясняющих суть различия:

🔵 заказ создан 1 мая 21:00, а запись в DWH о нем создана 1 мая 22:35 (потому что у вас периодический батч процесс), created_at заказа будет отличаться от meta_created_at. А если потом уже внутри DWH на основе таблицы заказов будет обновлен дата март, то там опять же будет свое meta значение, например 22:45. Дата создания заказа не меняется, а вот дата создания записи о заказе в той или иной таблице будет своя.

🔵 Еще более наглядный пример при бэкфиле. Заказ создан в приложении 1 мая 2025 года. По какой-то причине данные о нем собраны вчера - 2 июня 2025. Важно знать, что эта запись была создана только вчера, и что отчеты построенные, например, 1 июня еще ничего о нем не знали! ☝️

🔵и ещё пример. вы сохраняете run id - идентификатор процесса, в рамках которого создана/изменены строка. Это поможет, например, при траблшутинге, так как вы точно знаете какие данные затронул тот самый ран.

В метаданные можно действительно засунуть много всего, и то, что я перечислил выше, — лишь малая часть того, что можно придумать. Все зависит или от проблем (в том числе потенциальных), которые вы хотите решить с их помощью, или от сложности потоков данных, которые ведут к таблице, особенно если там несколько пайплайнов. 😵‍💫
В каких-то таблицах мы накидываем чуть больше мета данных, в каких-то меньше.

Я даже думаю, что если у вас еще нет мета колонок в данных и вы считаете, что они вам не нужны, то просто вы еще не созрели 😁 Вы почуствуете этот момент, когда они вам понадобятся. Даже если вы просто собираете отчёт, стоит как минимум знать дату последнего обновления строки, которую вы взяли в отчёт.🫣

Минимальный набор по-моему должен включать две колонки:
©️meta_created_at
©️meta_updated_at
Я бы прям рекомендовал вставлять их во все таблицы. Для зависимых (downstream) процессов необходимо знать именно изменённые записи и meta_updated_at будет как раз кстати.👍

Ниже список колонок, которые мы используем в разных местах в зависимости от того, что мы хотим знать о записях табличке. Я сгруппировал их по "участнику" потока, через "руки" которого прошли данные, и он добавил свои мета "следы".

📎 Если есть записи из разных источников:
🔵meta_source
🔵meta_source_object_type
🔵meta_source_object_id

📎Об оркестраторе:
🔵meta_orchestrator_run_id
🔵meta_orchestrator_run_timestamp

📎 Хранилище:
🔵meta_created_at
🔵meta_updated_at

Плюс если храним историю изменений:
🔵meta_is_current
🔵meta_valid_from
🔵meta_valid_to
🔵meta_version_hash
🔵meta_version_number
🔵meta_version

Я напишу на эту тему ещё пару постов, например чуть подробнее напишу про meta_updated_at 🙌 так что продолжение следует... 😊
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥3✍1
Meta данные - meta_updated_at. Часть 1

В прошлом посте писал о мета данных в целом, а в этом двойном посте остановлюсь на реализации одного из самых важных мета свойств - таймштамп последнего изменения. ☝️

Будет длинный двойной пост.
Конечно, я мог бы просто написать как мы делаем, но так неинтересно, по крайней мере мне самому 😁 я напишу почему именно так. Спойлер: во второй части будет код функциии на postgresql 👍

📝 meta_updated_at - таймштамп последнего изменения записи, то есть необходимо обновлять таймштамп каждый раз когда значение одной из колонок в строке изменилось.

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

Для начала нужно решить кто ответственен за эту свойство. У нас есть три (как минимум) участника, через "руки" которых проходят данные и которые могут добавить свой мета след:
🔵источник
🔵исполнитель (оркестратор)
🔵хранилище.

Порассуждаем: чтобы сказать изменится ли что-то, нужно знать в каком состоянии это что-то сейчас.

Источник ничего не знает о том, в каком состоянии сейчас запись в месте назначения, более того он вообще не знает о существовании этого самого места назначения. Есть соблазн в момент извлечения данных добавить прям в select что-то вроде now или current timestamp, но это будет время извлечения, а не каждое извлечение = изменение!

Примерно по той же причине этого не может знать и исполнитель (оркестратор). Он может только знать о времени обработки, что опять же не тоже самое, что время изменения.

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

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

Вторая часть поста⬇️
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤3
Meta данные - meta_updated_at. Часть 2

(сначала смотри два предыдущих поста ⬆️)

У нас хранилище на postgresql, поэтому его и рассмотрим для примера. (хотя я думаю общий смысл можно реализовать и в других базах)

В postgresql можно создать триггер на update. Однако простой тригер на update будет менять таймштамп каждый раз, когда выполняется операция update независимо от того, изменилось ли что-то по факту в строке или нет. То есть, делая, например, бэкфил за месяц, все затронутые записи получат новый таймштамп! Так мы не хотим. Нам надо ставить новый только тогда, когда что-то изменилось. Значит нужна функция внутри тригера чуть похитрее.

Тригер на update очень удобен тем, что в нем одновременно есть и новая (new) и текущая (old) версия строк. Вот и сравним внутри функции значения колонок этих двух состояний, да так чтобы было неважно на какую таблицу повесили триггер: одна функция на всю базу.

Вот наша:

CREATE OR REPLACE FUNCTION set_meta_updated_at()
RETURNS TRIGGER AS $$
DECLARE
old_jsonb jsonb;
new_jsonb jsonb;
BEGIN
-- Convert rows to jsonb and remove metadata fields
old_jsonb := to_jsonb(OLD) - 'meta_updated_at' - 'meta_created_at';
new_jsonb := to_jsonb(NEW) - 'meta_updated_at' - 'meta_created_at';

-- Compare entire row contents
IF old_jsonb IS DISTINCT FROM new_jsonb THEN
NEW.meta_updated_at := CURRENT_TIMESTAMP;
RETURN NEW; -- proceed with update
END IF;

RETURN NULL; -- no changes → cancel the update
END;
$$ LANGUAGE plpgsql;


А сам тригер - обычный вызов этой функции, поэтому его приводить здесь я не буду.

Результат:
1️⃣ Покрыты ВСЕ способы апдейта строки. Невозможно выполнить update, не запустив тригер. Это техническая гарантия, что meta_updated_at всегда обновится. То есть неважно, как и кто обновляет данные: батч процесс, реалтайм запись, руками через консоль - тригер всегда запустится и всегда поставит таймштамп, ЕСЛИ что-то изменилось.
2️⃣ Обновление meta_updated_at в одной транзакции с самой операцией update. Это тоже техническая гарантия, что если что-то идет не так, то транзакция целиком не будет принята: нет изменений нет и нового таймштампа.
3️⃣ Нет лишних dead tuples. Это особенности именно postgresql.

В двух словах про dead tuples: update строки приводит под капотом к созданию новой версии строки, а старая удаляется позже только при уборке - vacuum. То есть, по умолчанию postgresql не проверяет есть ли по факту отличия, и если 1000 раз запустить операцию update с одними и теми же данными на одну и ту же строку, postgresql создаст 1000 версий под капотом. Все они займут место на диске, создадут запись в лог, нагрузят диск операцией записи, нагрузят cpu чтобы все это провернуть.

Так вот функция в тригере отменяет update, если понимает, что изменений нет. Возврат null в коде выше как раз для этого. Нет новой версии -> нет dead tuple -> нет дополнительной нагрузки.
4️⃣ Быстро настроить для любой таблицы. Все очень просто. Одна функция на всю базу! В любой таблице создал колонку и создал тригер. Готово!
Более того, всё это можно обернуть в скрипт, и одним движением руки вы раскатаете решение на всю базу или всю схему. Мы так и сделали 😊

✏️Минус. (или нет)
Каждая операция update запускает функцию. Внутри функции какие-то операции, а выполняет операции cpu. Следовательно, появляется дополнительная нагрузку на cpu. Однако это сглаживается тем, что я писал выше про dead tuples. Справедливости ради скажу, что у нас нагрузка на cpu слегка выросла после введения этих тригеров, но скорость увеличилась из-за меньшего количества операций с диском. 👌

©️Очень простой способ получить мета колонку с таймштампом последнего изменения, да еще и с гарантией на техническом уровне. 🙌
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥3👏1
Изменения: предвидеть vs сделать так, чтобы они были неважны

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

Может возникнуть такая постановка вопроса:
давайте продумаем все, что может измениться в будущем, и сразу напишем код так, чтобы он подходил под те изменения, чтобы не пришлось потом все переделывать

Проблема в том, что вопрос поставлен так, что решения нет.

Предвидеть будущее невозможно. Невозможно сегодня сказать, что там изменится завтра, через месяц, через год. Разве что вы обладаете экстрасенсорными способностями. 😁. Но все-таки хочется же как-то облегчить жизнь себе в будущем. 🤔

Неопределенность всегда существует. Даже если вам кажется, что вы все продумали. Просто не нужно ее бояться. Пытаться все продумать наперед = бояться. Лучше принять ее и быть готовым к тому, что изменения будут. 🥲

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

❌Предвидеть - создать решение, подходящее заранее предусмотренным изменениям.

✔️Сделать так, чтобы было неважно - создать решение, которое легко адаптировать при любом изменении.

✳️есть еще третий вариант, но он немного офтоп для этого поста. Сделать так, чтобы не жалко было сломать и выкинуть - fail fast. Это тоже интересный вариант для случаев, когда неопределенность на другом уровне - под сомнением сама необходимость решения проблемы или даже само ее существование. Однако это другая история

📎Правильная постановка вопроса:
Как сделать решение, которое легко адаптировать/расширять в случае изменений?

Это запускает мышление в другую сторону.

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

Эта финальная мысль мне напомнила книгу Роберта Мартина Clean architecture, которая несколько лет назад дала мне ответы на многие вопросы 😉
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7
Квантовая аналитика 😄

Такой перл у нас родился сегодня на дейлике 😆

А тема вообще очень серьёзная. И это я не про квантовую физику😁.

Auditability - полная прослеживаемость и проверяемость данных: почему, в какой момент менялись. И как следствие этого свойства — возможность получить данные на определённый момент времени.

©️Чтобы получать предсказуемые отчеты, а не квантовую аналитику, всегда собираем историю изменений и метаданные 🙌
Please open Telegram to view this post
VIEW IN TELEGRAM
😁6👍5
Без паники!

Пост про траблшутинг и проблем солвинг.

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

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

Вот что поможет избежать паники:
1️⃣ Доверяй себе — если исходить из того, что вы хороший инженер и просто так на удачу ничего не релизите, то значит, вы всё сделали правильно.
2️⃣ Доверяй коллеге — это следующий шаг от доверия себе — он/она тоже хороший инженер и т. д.

Так что вместо того, чтобы сразу по умолчанию признавать всю работу некачественной, стоит потратить немного времени на поиск причины.

Несколько возможных сценариев:

©️ Причина может вообще не быть связана с последними изменениями непосредственно (см. пост). Например, кто-то где-то что-то поменял и то, что вы сделали релиз - просто совпадение.

©️ Причина может быть связана косвенно: изменения выявили скрытую проблему в другом месте.

©️ Причина в небольшой ошибке в релизе - баг.

©️ Причина в критической ошибке в релизе.

Очевидно, что в зависимости от причины будут предприняты разные действия. И да, бывает, что откатить все - лучшее решение, однако и оно должно быть принято спокойно на основе анализа ситуации, а не паники.

Берите пример с кота на картинке: без паники! ❤️
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👏2
Сфотал недавно на одном ларьке.

Эта картинка почему-то напомнила мне документацию.

Любую.

К чему бы это.🤔😁
😁13👍2
Google, heavy is the crown?

Раньше я думал, что гугл это идеал, если бы это был человек, то у него был бы нимб или корона. Но поработав с сервисами гугла, я понял, что ничего там особенного:
🔸ошибки (да, я и 503 видел от одного из их сервисов в течение нескольких часов😳),
🔸странное поведение,
🔸запутанная и где-то неполная документация

Все как у людей. 😁 То же самое могу сказать и про facebook, bing и ещё ряд разных не таких известных сервисов. Google — просто яркий пример, чтобы донести саму идею.

Я осознал что все это просто сервисы, написанные простыми разработчиками, которые не факт, что умнее меня или вас. 🧐 (Дисклеймер: я сейчас не имею ввиду топ инженеров того же гугла, которые меняют мир, я имею ввиду ребят, которые работают "в поле" и каждый день пишут код)

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

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

❌Опасно! Есть риск уйти в крайность и стать вечно ворчащим разработчиком, который ругает всё, кроме того, что сделал сам! 🙅‍♂

©️Я разработчик ©️ Я могу ошибаться ©️ Все сделали люди ©️Они такие же разработчики как я ©️Они могут ошибаться 🙌
Please open Telegram to view this post
VIEW IN TELEGRAM
👏6
Дата инженерная доля

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

Ошибки, неточности могут быть в любом сервисе, с которым мы интегрируемся. Но это не всё...

📖 Проблемное поведение сервисов, приложений, источников данных:

🔸Ошибки - сервис не выполняет предъявляемые ему требования

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

🔸Неполные данные - сервис выполняет все известные требования, но в данных не хватает деталей, однако сервис не может добавить эти детали в принципе. Например, есть три внешних сервиса, выполняющие одинаковую функцию. Сервис 1 предоставляет свойства A, B, C; сервис 2 - тоже A, B, C; сервис 3 только A, B.

🔸Нестабильный источник - сервис и требования выполняет и данные полные, но... периодически может быть недоступен.

🔸Разные комбинации всего этого одновременно в рамках одного сервиса

А теперь самое интересное.
Бизнес требует полные, точные данные без ошибок и стабильно.😐


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

➡️ Ошибки? Ну вы же их видите - добавьте в код костыль, фильтраните, пока мы делаем фикс.
➡️ Ошибку исправили. В исторических данных она осталась? Конечно, как мы в прошлом ошибку исправим. Проблема была такая-то - исторические данные исправьте сами.
➡️ Неточности? Да, знаем — добавьте логику на своём уровне, пока у нас руки не дошли туда (никогда не дойдут).
➡️ Неполные данные? Заполните. Сделайте допущение, мы и правила вам расскажем. Примерно.
➡️ Нестабильный источник? Ну есть же второй еще. Берите из него, если первый недоступен, да смотрите, чтобы дублей не было.

⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️⬇️

Бизнес:
- В общем сделайте так, чтобы данные отвечали на наши вопросы.
Дата инженеры:
- ок


Такая вот дата инженерная доля. 🥲🫡
Please open Telegram to view this post
VIEW IN TELEGRAM
🫡9👨‍💻3
Data Maturity Levels

Прошлый пост получился немного грустный. Дата инженерная доля... 🫡

✅ То, какая она эта доля у дата-инженера зависит от уровня зрелости компании в отношении работы с данными - Data Maturity Level.

Мне очень нравится модель зрелости, предложенная в книге Fundamentals of Data Engineering. И я хочу привести её в этом посте в сокращенном виде ✏️

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

1️⃣ Starting with data
Архитектура и инфраструктура данных находятся на начальных стадиях планирования и разработки. (дополнение от меня: Если какие-то инструменты и сервисы и внедрены, то разрознены)
Уровень внедрения и использования данных низкий.
Практическое понимание ценности данных невелико, но стремление к этому есть.
Отчеты и аналитика не имеют формализованной структуры, а большинство запросов к данным выполняется в режиме ad hoc.
На этом этапе дата-инженер обычно выступает как универсальный специалист и берет на себя сразу несколько ролей, например, аналитика или разработчика. Цель дата-инженера — двигаться быстро, добиться первых результатов и принести пользу. Задача здесь - заложить прочный фундамент для работы с данными.

2️⃣ Scaling with data
Компания уходит от разовых запросов к данным и формирует формальные практики работы с ними. Теперь главная задача — создание масштабируемой архитектуры данных и подготовка к будущему, в котором компания действительно будет управляться на основе данных. Роль дата-инженеров постепенно переходит от универсального специалиста к фокусированию на определённых аспектах жизненного цикла работы с данными.
Основным узким местом масштабирования является не число узлов в кластере, не хранилище и не сама технология, а команда дата-инженеров. Нужно делать ставку на решения, которые просто внедрять и поддерживать, чтобы увеличить пропускную способность команды. Внедрять DevOps и DataOps практики.
При этом важно общаться с другими командами о практической пользе данных, обучать организацию тому, как использовать и извлекать ценность из данных (дополнение от меня: правильно использовать).

3️⃣ Leading with data
На этом этапе компания уже действительно управляется данными. Автоматизированные пайплайны и системы, созданные дата-инженерами, позволяют сотрудникам самостоятельно выполнять аналитику и использовать ML. Подключение новых источников данных происходит бесшовно, и из данных извлекается реальная ценность. Дата-инженеры внедряют необходимые механизмы контроля и практики, чтобы данные всегда были доступны людям и системам: governance, catalog, lineage, metadata management, etc.
Дата-инженер на этот этапе может уделять много времени разработке кастомных инструментов и систем, которые используют данные как конкурентное преимущество. Однако здесь возникает соблазн браться за дорогие «хобби-проекты», которые не приносят ценности бизнесу.
Серьёзную угрозу представляет самоуспокоенность. Достигнув третьего уровня зрелости, организации должны постоянно уделять внимание поддержке и улучшению процессов, иначе есть риск отката на более низкий уровень.


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

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

А ещё, по-моему, такого чистого разделения на этапы в реальном мире не существует: всегда будут признаки разных уровней одновременно, особенно в рамках целой компании. Наверное уровень можно примерно определить по правилу большинства признаков. Я бы сказал, что мы год-полтора назад были в большей степени на уровне 1, а сейчас основной массой перевалили на уровень 2, и, хотя кое-где нога застряла еще на 1, смотрим на уровень 3. 🫣😋

На каком уровне ваша компания? ⬇️
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Data Maturity Level. Опрос.

На каком уровне зрелости в отношении работы с данными ваша компания? Или проект, если компания слишком большая, и вы не знакомы со всеми практиками.
Anonymous Poll
33%
Starting with data
45%
Scaling with data
22%
Leading with data (data driven)
Профессиональная независимость

* это я сфотал картину Tennis Player в музее Современного искусства в Мюнхене.

Я занимаюсь большим теннисом с тренером. Как любитель. 😎 Иногда мы разговариваем с ним о его тренерской жизни, и однажды он поделился со мной интересной мыслью об отношениях тренер<>спортсмен которую, если подумать, можно распространить и на отношения сотрудник<>компания.

То, что тренеры конкурируют за спортсмена, особенно в любительском секторе, очевидно: такая модель продавец услуг -> клиент. Но что, если есть и обратная конкуренция?

Дальше примерно его мысль: ⬇️

С одной стороны выглядит хорошо, когда тренера нанимает богатая семья, чтобы он тренировал и детей и немного родителей тоже. Работа только на них - удобно. Платят много. Стабильный доход. Есть одно но. Со временем спортсмены (и дети, и взрослые) начинают лениться, меньше выкладываться на тренировках и даже пропускать их. Чтобы этого не произошло, нужна конкуренция: спортсмен (клиент) должен конкурировать за тренера (исполнитель). Другими словами у тренера должна быть реальная возможность сказать "до свидания" и пойти работать с тем, кто хочет расти. И все стороны должны это понимать.

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

©️Перейдем на отношения компания<>сотрудник.
В этой аналогии сотрудник - это тренер/исполнитель, а компания - спортсмен/клиент.

Майндсет зависимого, наемного, удобного мешает обеим сторонам и приведет к деградации. Поэтому я люблю рассматривать найм как партнерство, договоренность, где я предоставляю услуги и получаю вознаграждение. Работаю плохо? Можете меня выгнать. Работаю хорошо? Платите.
При этом "хорошо" — это не просто "сделал как попросили", а ещё и про профессиональный уровень, принятый в индустрии 🧐

Дисклеймер: Я не предлагаю работать на нескольких работах одновременно или идти во фриланс. Речь о майндсете.

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

©️Хороший тренер специалист всегда найдет работу 😉 💯
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10❤2👍1💯1
Грузоперевозки данных

У AWS еще недавно была услуга по трансферу данных... на грузовике. 😳

Можно было заказать себе такой грузовик, подключить к своему дата-центру, загрузить данные (в прямом смысле) и отправить их куда надо. Грузовик вмещал до 100 PB данных.

В прошлом году AWS все таки отказались от этой услуги именно в виде грузовика и теперь предлагают только "небольшие" контейнеры с SSD на сотни TB. (AWS Snowball)

Бизнес-смысл услуги физического трансфера данных очень прост. Например используют для миграции в cloud. Представьте, что у вас свой дата-центр, где вы нажили непосильным трудом петабайты данных. 1 PB данных при скорости 1 Gbps передавался бы около 100 дней непрерывно. А тут AWS как раз со своими грузовиками или контейнерами поменьше... 😁

Вот такой big data transfer. 💪

PS. Вы заметили, что слово snow часто фигурирует в названии дата инструментов? 🤔
👍9😁8❤2🔥1
Настоящий детектив.
Основано на реальных событиях.

Очень интересная история приключилась в нашем офисе на днях.

Хитрость, бдительность, находчивость, арест. В жанре драма, криминал, комедия 😁

В офис проник посторонний парень (проскочил в открытую дверь когда кто-то выходил). Как выяснилось потом, это был вор, который проникал в офисы и, видимо, в расчёте на то, что не все знают друг друга в лицо, ходил по офису и в итоге выносил какие-то вещи. 🫣 Назовем его хитрый. Так вот поднялся хитрый на один этаж, заглянул в дверь, на второй, на третий... а там у нас бар и зона, где можно покушать. Дело было после обеда и пара наших ребят припозднились и были там. И тут хитрому не повезло, потому что это были именно те ребята, которые знают всех в лицо. Они начали расспрашивать хитрого, кто он и зачем пришёл. Тот сказал, что он пришёл на собеседование (цитата) "программистом за любые деньги". Но наших ребят не проведешь, они уже поняли, в чём дело, и проявили удивительную находчивость: предложили хитрому наивному пройти в митинг-рум для "собеседования" и, пока один из наших находчивых делал вид, что собеседует его, второй вызвал полицию.

Полчаса шло это "собеседование", пока полиция не приехала и не арестовала наивного. Оказалось, что он уже три месяца был в розыске за кражу на сумму более 10К евро из разных офисов. Но потом вошёл не в ту дверь... 🙌

Из офисного чата: 😂
🤣17🏆4❤1
Маленькая инженерная задача. Часть 1. Контекст.

На гифке выше — голова Франца Кафки в Праге.

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

📝 Задача связана с Apache Kafka — брокером сообщений, частым участником архитектуры приложений и дата-платформ.

Брокер сообщений работает в producer-consumer схеме, то есть продюсер закидывает туда сообщение (публикует), а получить его может множество подписчиков (консьюмеров) – сервисов, которым нужно как-то использовать этот опубликованный факт: запускать внутреннюю логику или просто сохранять данные.

У нас Kafka в первую очередь используется как инфраструктурный элемент для общения между приложениями (асинхронный API, декаплинг) и только во вторую для публикации данных. То есть это даже не часть дата платформы. Дата платформа тут выступает лишь как один из консьюмеров.

Еще одна важная особенность. Мы используем один общий поток для всех событий (в kafka это называется топик). Решение со своими плюсами и минусами. И именно с минусами этого подхода и связана задача, о которой я пишу.

Плюс единого потока:
🔵участникам легко интегрироваться (всегда только один поток),
🔵 легко поддерживать инфраструктуру (не нужно добавлять топики),
🔵 команда продюсера ни о чем не думает, не делает запросов на создание топиков в команду поддержки (девопсы или дата инженеры), а просто начинает отправлять события.
Все очень просто, а значит надёжно.
Минус:
🔸 консьюмер вынужден читать весь поток и выбирать из него только интересующие его события. Вполне может быть так, что подписчик "пропускет" 90% всех событий в ожидании "того самого". 😵‍💫

Вот история с применением СПР паттерна (писал про него тут).

📝 Ситуация: есть kafka с одним общим топиком, в который попадают все события. Еще есть http proxy микросервис (написан на Go), который принимает http post запрос, валидирует пейлоад и отправляет его в kafka. Все события имеют единую схему метаданных и пейлоад. Есть несколько продюсеров и несколько консьюмеров. kafka и прокси развернуты в кубернетес (aws eks).

🐞 Проблема: есть флоу, которые выполняются с превышением SLO, то есть end-to-end время превышает требование бизнеса.

End-to-end для бизнеса означает от одного бизнес-события до другого. Например, клиент на сайте нажал кнопочку "купить" и через 5 секунд получил email с подтверждением. Заметьте, что бизнесу пофиг: Kafka там или что-то ещё под капотом (пост бизнесу пофиг).

💡 Решение: 1) предоставить консьюмерам возможность потреблять часть событий; 2) организовать мониторинг каждого шага, времени работы каждого участника, чтобы такие вопросы не возникали в будущем, чтобы точно знать, кто и где даёт задержки; 3) переключить консьюмера на "урезанный" топик и наблюдать за флоу, так как есть вероятность, что задержки в этом конкретном флоу были вызваны чем-то другим.

Пункт 3 решения может показаться вам странным, как будто мы гадаем. Вам не показалось 🙂 Выглядит логично сначала организовать мониторинг на всех этапах, выяснить точно, а потом действовать. Так бы и было где-то в книжке, но на решения в жизни влияют еще и другие факторы (ресурсы, загруженность команд, другие приоритетные задачи, внутренние политические моменты, личные взаимоотношения и фазы луны 😁). В данном случае по совокупности факторов нам было проще предоставить урезанный топик и посмотреть, что будет. Даже если в этом флоу это не поможет, в любом случае хорошо иметь возможность быстро фильтровать топики в будущем.

Дальше я буду писать о создании урезанных топиков (п. 1 решения), а мониторинг в этой истории опустим.

Итак, ситуация, проблема и решение определены. Теперь можно уже делать? Нет. Ещё подумать ☝️ 😁

Продолжение следует...
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Маленькая инженерная задача. Часть 2. Решение

Дальше рассуждения о том, как именно реализовать решение. 🤔

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

Вот некоторые из рассмотренных подходов:
©️ топик под требования консьюмера, то есть консьюмер приходит и говорит "меня интересуют конкретно события А, B, C" и создаем соответствующий топик именно под него. Отмели сразу, потому что на ровном месте вносит зависимость разработчиков консьюмера от команды поддержки инфраструктуры. К тому же задач может быть множество, и каждый раз создавать топик — перебор.
©️ топики под каждый тип события. Многовато получится топиков. У нас более 100 сейчас разных событий и постоянно добавляются еще.
©️ топики по группам событий. У нас события могут быть разделены по контекстам. Их около 20. А консьюмеры подписываются на контекст и получают сабсет событий и чувствуют себя лучше. Выбрали этот вариант.✔️

Идем дальше: создавать топики динамически или предварительно? Динамически звучит лучше: появился новый контекст, автоматически создался топик. Так участие инженеров нужно только один раз при запуске, а потом все работает само - красота. 🤤

Теперь детали: инструменты, языки и тд. Тут тоже варианты.
🔵 внешние saas инструменты. Отмели сразу, что я даже не искал такие. Kafka у нас в AWS EKS кластере (Kubernetes), поэтому подключение внешнего инструмента потребует "открыть" инфраструктуру в мир. Плюс такие тулы не могут дать 99% гарантию, что все события попадут в нужные топики, по крайней мере банально из-за добавления общения по сети, не говоря уже о внутренних делах того сервиса. Ну и конечно saas стоит денег 💰
🔵 расширить функции уже имеющегося http proxy микросервиса, чтобы обрабатывая событие, он сразу записывал его в два топика: общий и специальный. Тоже отклонили по архитектурной причине: из простого "деревянного" прокси он превратится в сервис с логикой. Сломается принцип единой ответственности (SOLID). Сейчас его простота даёт гарантию доставки событий, а добавление логики внесёт риск. И это потребует вмешательства в то, что уже работает.
🔵 готовый open-source инструмент, развёрнутый внутри того же кластера Kubernetes и того же namespace, где и Kafka. Цельная инфраструктура работает слаженно. Исключаются любые внешние "помехи", а вся работа происходит в одном и том же изолированном namespace. Вот это нам понравилось. 👍
🔵 кастомный микросервис внутри кластера. Очевидный минус: нужна разработка, а потом поддержка.

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

Вот теперь можно делать. 😁 Спойлер: такого инструмента нет

Продолжение следует...
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
Маленькая инженерная задача. Часть 3. Реализация

Из предыдущего поста:

подобрать и внедрить инструмент, который будет из общего топика динамически генерировать топик для каждой группы событий (или типу событий) так, чтобы при появлении нового типа автоматически создавался отдельный топик без вмешательства инженеров.
Звучит несложно, подумал я, с учётом огромной популярности Kafka, с учётом всех этих разговоров о modern data stack, где на каждую идею уже придуман off-the-shelf (прямо с полки), plug-and-play инструмент. По крайней мере такое сложилось у меня впечатление, когда я последнее время читал разные статьи, посты и тд. (пост про modern data stack)

Оказалось, что не существует готового инструмента, закрывающего данный вопрос, чтобы разработка не нужна была вообще, а только конфигурация (например тераформ, хелм и всё). 😳🫣😞

Вот что есть:
🟣Ksql – популярный и не требующий разработки open source инструмент. Есть официальный helm. Удобно создавать топик по условиям, но динамически он не умеет. 🤬

🟣Kafka Streams – библиотека, которая позволяет накодить что угодно на python или java, но ключевое слово накодить, то есть это будет кастомная разработка, которую надо поддерживать. 💔

🟣Apache Flink – стриминг инструмент с широкими возможностями и, конечно, умеет динамически, но тяжелый и требует сложной конфигурации – для данной простой задачи это перебор. 🤯

Есть еще парочка вариантов, которые накидал gpt, но все они примерно о том же. 🤨

©️В итоге пошли на компромисс. Отказались от идеи динамической генерации с необходимостью разработки в пользу предварительно настроенных топиков с использованием готового инструмента – ksql. Новые контексты добавляются относительно редко (может, раз в несколько месяцев), и да, придётся зайти в конфиг ksql и добавить ещё один стрим, но это на данный момент показалось проще, чем делать разработку.

Ksql развернули через helm внутри существующего неймспейса в кубернетес рядышком с kafka и proxy сервисом. Прямо там же, через helm, на языке SQL описали новые стримы в интуитивно понятном формате select запроса типа: выбрать из топика A, где контекст равен B, и отправить в топик C. 🙌

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

〰️〰️〰️〰️〰️

Часть 4. Рефлексия

Завершу я эту историю 3 финальными мыслями.

1️⃣ Описание относительно маленькой задачи растянулось аж на 3 поста. Да, я мог бы просто написать: нам нужны были топики в kafka и мы внедрили kqsl. Уложился бы в один пост. Но упустил бы самое главное: в реальной работе редко бывает так, что решение очевидно и однозначно. Любую проблему можно решить множеством способов. Более того, ещё и саму проблему нужно правильно определить.

2️⃣Минусы есть всегда. Наш архитектор сказал такую мысль:

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

3️⃣"Накликать" не получилось. В последнее время я много читал про modern data stack, off-the-shelf инструменты, и создалось впечатление, что на любой каприз уже есть проверенное готовое решение с открытым кодом. А тут вдруг облом с супер популярной кафкой: отсутствие возможности создавать топики динамически без кастомного кода. Получается, еще далеко до того, чтобы инженер только сидел и "накликивал" себе решение на готовых инструментах.

©️Может быть вы заметили, что в той истории я упоминал разные термины и концепты: брокер сообщений, at least once доставка, принципы SOLID, асинхронный API и другие. Ставьте ❤️ если хотите, чтобы я кратко объяснил их в одном из следующих постов. Хотя я все равно опишу, потому что хочу😁
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
Почисти свою архитектуру

Всё перечисленное на картинке — только ingestion layer: извлечь/принять данные из какого-либо источника и сохранить как есть в raw storage.

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

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

В прошлом году видел твит Роберта Мартина – автора книг Clean architecture, Clean code и других.

“Clean Code!” is a command, not a noun. We don’t write Clean Code — we Clean Code.


Тут фишка в игре слов на английском: clean можно перевести как "чистый" и как "чисти". Обычно "clean" в его книгах переводят как "чистый/чистая". А в том твите он писал, что словосочетание так же хорошо звучит и как команда, то есть "Чисти архитектуру" и "Чисти код", подчеркивая что это постоянный процесс, а не однократное решение.

Что ж, пойду чистить. 🧹
👏7🔥3💯1
Обнаружил для себя, что Ask AI на официальном сайте Clickhouse отлично помогает. По-моему, лучше, чем просто ChatGPT или Claude в вопросах, связанных с Clickhouse. Наверное, там под капотом тот же ChatGPT, но обучен он на официальной документации.👍

В ClickHouse огромное количество специфических настроек, особого синтаксиса, фич, которые ещё тестируются, но уже доступны при включении флагов. 😵‍💫 Другие "чаты" путаются во всём этом и часто предлагают то, что не работает. 🤬 Я слишком часто писал в chatgpt что-то типа "doesn't work, unknown setting, unknown system table" и тд, пока не открыл для себя этого официального помощника. И ответит и ссылочку на документацию прикрепит. 🙌

В общем, мне нравится! Последние пару месяцев с вопросом по Clickhouse в первую очередь иду туда, и обычно этого достаточно. Попробуйте! Может кому-то тоже зайдет. 😊
👍17