Uber выложили в опенсорс свою платформу метрик M3, и пока я бегло смотрел, как она устроена, наткнулся на подход под названием LTTB downsampling. Вот о чём речь...
LTTB расшифровывается как Largest Triangle Three Buckets. Это алгоритм даунсэмплинга, который помогает эффективно запрашивать и визуализировать миллионы точек таймсерий. Идея в том, чтобы сохранить визуальную форму графика, но сильно сократить число точек, которые нужно рендерить.
За счёт этого фронтенду легче: меньше точек для отрисовки и меньше данных надо гонять по сети.
Работает так: временной ряд делится на “бакеты”, и из них выбираются точки, которые сохраняют максимальную “визуальную площадь”. То есть вместо случайной выборки или простого усреднения, LTTB оставляет точки так, чтобы на графике не потерялись пики, провалы и общий тренд.
Механика простая: берутся три точки за раз (предыдущая, текущая, следующая) и считается площадь треугольника, который они образуют. Выбирается та точка, которая даёт самый большой треугольник. В итоге важные визуальные особенности переживают даунсэмплинг.
С таким подходом можно ужать 10 000 точек до 500 и всё равно получить график, который выглядит почти так же, как исходный. Помимо M3, системы вроде Grafana, InfluxDB и Prometheus тоже взяли LTTB или похожие техники даунсэмплинга.
Забавно, что такая, казалось бы, простая штука как “какие точки оставить?” внезапно превращается в реально интересную задачу.
👉 @BackendPortal
LTTB расшифровывается как Largest Triangle Three Buckets. Это алгоритм даунсэмплинга, который помогает эффективно запрашивать и визуализировать миллионы точек таймсерий. Идея в том, чтобы сохранить визуальную форму графика, но сильно сократить число точек, которые нужно рендерить.
За счёт этого фронтенду легче: меньше точек для отрисовки и меньше данных надо гонять по сети.
Работает так: временной ряд делится на “бакеты”, и из них выбираются точки, которые сохраняют максимальную “визуальную площадь”. То есть вместо случайной выборки или простого усреднения, LTTB оставляет точки так, чтобы на графике не потерялись пики, провалы и общий тренд.
Механика простая: берутся три точки за раз (предыдущая, текущая, следующая) и считается площадь треугольника, который они образуют. Выбирается та точка, которая даёт самый большой треугольник. В итоге важные визуальные особенности переживают даунсэмплинг.
С таким подходом можно ужать 10 000 точек до 500 и всё равно получить график, который выглядит почти так же, как исходный. Помимо M3, системы вроде Grafana, InfluxDB и Prometheus тоже взяли LTTB или похожие техники даунсэмплинга.
Забавно, что такая, казалось бы, простая штука как “какие точки оставить?” внезапно превращается в реально интересную задачу.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍2🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
Познакомься с Devin Review: это переосмысленный интерфейс для понимания сложных PR.
Современные инструменты для код-ревью на деле не делают чтение кода проще. Devin Review прокачивает понимание и помогает перестать пропускать слоп.
Вместо алфавитного списка файлов он группирует связанные изменения и раскладывает их в логическом порядке, плюс дает короткое описание каждой группы. Отдельно умеет находить перемещенный и скопированный код, отделяя сигнал от шума.
Еще внутри есть агент, который ловит потенциальные баги и помечает их по уверенности и критичности. Причем он подсвечивает не только прямые баги, но и спорные решения/паттерны, которые потом превращаются в техдолг. Маркировка простая: красный срочно смотреть, оранжевый стоит глянуть, серый просто к сведению.
Плюс можно обсудить PR в чате с Devin, с контекстом всего репо.⌨️
Как зайти:
- прямо на devinreview.com (можно без аккаунта)
- или заменить
- или дернуть из репы:
👉 @BackendPortal
Современные инструменты для код-ревью на деле не делают чтение кода проще. Devin Review прокачивает понимание и помогает перестать пропускать слоп.
Вместо алфавитного списка файлов он группирует связанные изменения и раскладывает их в логическом порядке, плюс дает короткое описание каждой группы. Отдельно умеет находить перемещенный и скопированный код, отделяя сигнал от шума.
Еще внутри есть агент, который ловит потенциальные баги и помечает их по уверенности и критичности. Причем он подсвечивает не только прямые баги, но и спорные решения/паттерны, которые потом превращаются в техдолг. Маркировка простая: красный срочно смотреть, оранжевый стоит глянуть, серый просто к сведению.
Плюс можно обсудить PR в чате с Devin, с контекстом всего репо.
Как зайти:
- прямо на devinreview.com (можно без аккаунта)
- или заменить
github на devinreview в ссылке PR- или дернуть из репы:
npx devin-review {pr-link}Please open Telegram to view this post
VIEW IN TELEGRAM
Фан-факт: OpenAI тянет 800 млн пользователей в ChatGPT всего на одном primary PostgreSQL и 50 read-репликах 🤯
Сегодня OpenAI выкатили инженерный пост о том, как они масштабировали Postgres, чтобы обслуживать эти 800 млн пользователей: один primary и 50 мульти-региональных реплик.
Внутри разбирают свой подход к масштабированию, прокси PgBouncer, локи вокруг кэша и каскадные read-реплики. Реально выглядит аккуратно и впечатляюще.
ВОТ короткое видео на YouTube, где разбирают этот пост и раскладывают нюансы по полочкам.
Зацени, видос короткий
👉 @BackendPortal
Сегодня OpenAI выкатили инженерный пост о том, как они масштабировали Postgres, чтобы обслуживать эти 800 млн пользователей: один primary и 50 мульти-региональных реплик.
Внутри разбирают свой подход к масштабированию, прокси PgBouncer, локи вокруг кэша и каскадные read-реплики. Реально выглядит аккуратно и впечатляюще.
ВОТ короткое видео на YouTube, где разбирают этот пост и раскладывают нюансы по полочкам.
Зацени, видос короткий
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9
This media is not supported in your browser
VIEW IN TELEGRAM
Учись программированию, Cloud и DevOps через практику
Бесплатные серверы и реальные задания.
✓ Практикуй Git и Linux-серверы
✓ Создавай и тестируй ресурсы AWS без страха
✓ Kubernetes, Docker, Terraform и другое
Регистрация не нужна: вперёд
👉 @BackendPortal
Бесплатные серверы и реальные задания.
✓ Практикуй Git и Linux-серверы
✓ Создавай и тестируй ресурсы AWS без страха
✓ Kubernetes, Docker, Terraform и другое
Регистрация не нужна: вперёд
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
Если я говорю “горизонтальное масштабирование”, ты, скорее всего, автоматически думаешь про load balancer.
Вот 2 способа масштабироваться дальше, чем просто балансировщик.
При горизонтальном дублировании ты копируешь часть системы, чтобы переваривать больше нагрузки, и распределяешь работу между этими копиями.
Самый очевидный вариант горизонтального дублирования это как раз load balancer. Он:
• распределяет запросы
• видит, когда нода умерла, и убирает ее из пула
1. Competing Consumer Pattern
Суть паттерна в том, чтобы раскидать нагрузку и поднять throughput.
Идеально, когда у тебя есть обработчики задач. Например, система должна давать пользователям импортировать и обрабатывать большие файлы.
Ты кладешь каждый загруженный файл в очередь, и много консьюмеров “соревнуются” за то, кто заберет задачу и обработает ее.
2. Read Replicas для read-нагрузки
Чтобы разгрузить primary базу по чтениям, ты поднимаешь read replicas.
Работает отлично, если основная нагрузка на систему в основном чтение.
Пример: e-commerce. Primary база принимает все записи, а реплики обслуживают тяжелые чтения, типа карточек товара или истории заказов пользователя.
Горизонтальное дублирование обычно довольно прямолинейное.
Если вертикально масштабироваться уже нельзя, это обычно следующее, куда я бы смотрел.
Если ты можешь нормально “разрезать” работу между копиями, это очень элегантный способ разнести нагрузку и снизить конкуренцию за ресурсы.
Но есть нюанс: нужно больше инфраструктуры, и это, конечно, дороже.
Ты делал что-то из этого?
👉 @BackendPortal
Вот 2 способа масштабироваться дальше, чем просто балансировщик.
При горизонтальном дублировании ты копируешь часть системы, чтобы переваривать больше нагрузки, и распределяешь работу между этими копиями.
Самый очевидный вариант горизонтального дублирования это как раз load balancer. Он:
• распределяет запросы
• видит, когда нода умерла, и убирает ее из пула
1. Competing Consumer Pattern
Суть паттерна в том, чтобы раскидать нагрузку и поднять throughput.
Идеально, когда у тебя есть обработчики задач. Например, система должна давать пользователям импортировать и обрабатывать большие файлы.
Ты кладешь каждый загруженный файл в очередь, и много консьюмеров “соревнуются” за то, кто заберет задачу и обработает ее.
2. Read Replicas для read-нагрузки
Чтобы разгрузить primary базу по чтениям, ты поднимаешь read replicas.
Работает отлично, если основная нагрузка на систему в основном чтение.
Пример: e-commerce. Primary база принимает все записи, а реплики обслуживают тяжелые чтения, типа карточек товара или истории заказов пользователя.
Горизонтальное дублирование обычно довольно прямолинейное.
Если вертикально масштабироваться уже нельзя, это обычно следующее, куда я бы смотрел.
Если ты можешь нормально “разрезать” работу между копиями, это очень элегантный способ разнести нагрузку и снизить конкуренцию за ресурсы.
Но есть нюанс: нужно больше инфраструктуры, и это, конечно, дороже.
Ты делал что-то из этого?
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Колонарное хранилище vs построчное (row store) наглядно
Берем простую агрегацию и сравниваем, как она выполняется в row store и columnar store.
В row store данные лежат строками, поэтому движку приходится читать каждую строку целиком, чтобы из нее вытащить значение колонки age.
В columnar store данные лежат по колонкам, поэтому он читает сразу только значения колонки age, без трогания остальных полей и без лишнего I/O.
👉 @BackendPortal
Берем простую агрегацию и сравниваем, как она выполняется в row store и columnar store.
В row store данные лежат строками, поэтому движку приходится читать каждую строку целиком, чтобы из нее вытащить значение колонки age.
В columnar store данные лежат по колонкам, поэтому он читает сразу только значения колонки age, без трогания остальных полей и без лишнего I/O.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍2
This media is not supported in your browser
VIEW IN TELEGRAM
JavaScript, Ruby и Go используют сборщик мусора для управления памятью.
Но ты знал, что у SSD тоже есть свой GC?
SSD с большим количеством записей и удалений постоянно “перекладывает” данные, и этим занимается сборщик мусора, встроенный прямо в прошивку, которая крутится на контроллере SSD.
Из-за этого последовательная запись до сих пор предпочтительнее случайной, даже если у тебя не HDD.
👉 @BackendPortal
Но ты знал, что у SSD тоже есть свой GC?
SSD с большим количеством записей и удалений постоянно “перекладывает” данные, и этим занимается сборщик мусора, встроенный прямо в прошивку, которая крутится на контроллере SSD.
Из-за этого последовательная запись до сих пор предпочтительнее случайной, даже если у тебя не HDD.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
JSON и JSONB колонки удобны тем, что туда можно просто закинуть любые “безсхемные” данные, но иногда хочется хоть немного это зажать правилами.
Для этого можно использовать расширение
👉 @BackendPortal
Для этого можно использовать расширение
pg_jsonschema: задаешь JSON Schema и получаешь больше контроля над тем, какой формы данные вообще имеют в этих колонках.Please open Telegram to view this post
VIEW IN TELEGRAM
❤6
SYN Flood это одна из самых старых DoS-атак, и она до сих пор работает. Вот что происходит под капотом.
TCP-соединение поднимается через three-way handshake: клиент шлет SYN, сервер отвечает SYN-ACK, клиент завершает ACK.
Фишка в том, что на этом этапе сервер держит состояние для каждой “полуоткрытой” сессии в очереди backlog и под это выделяются ресурсы.
В SYN Flood атакующий шлет тысячи SYN-пакетов, но рукопожатие не завершает. Сервер продолжает ждать ACK, backlog забивается, и когда очередь переполнена, легитимные клиенты уже не могут подключиться. Получается DoS.
Почему атака такая живучая: из-за асимметрии. Нападающий кидает крошечные пакеты почти бесплатно, а серверу на каждый приходится тратить ресурсы. Даже слабая машина может уложить куда более мощный сервер.
Факт: SYN-флуды в прошлом валили GitHub, Cloudflare и разные базы. Защита обычно такая:
1. лимитить SYN от одного IP
2. дропать пакеты от известных плохих источников
3. и самое эффективное: SYN cookies
С SYN cookies сервер вообще ничего не хранит на этапе “полуоткрыто”. Он кодирует нужную инфу (IP клиента, порт, таймстамп и т.д.) в initial sequence number у SYN-ACK, который отправляет в ответ. Номер генерируется криптографически, подделать его сложно.
В итоге handshake становится по сути stateless со стороны сервера, пока клиент не докажет, что он реальный. Ресурсы резервируются только после верификации.
Кстати, в большинстве современных ОС поддержка SYN cookies уже встроена. В Linux это включается так:
Если хочется копнуть глубже, статьи в Wikipedia по теме реально норм, плюс можно добить деталями через любимую LLM.
👉 @BackendPortal
TCP-соединение поднимается через three-way handshake: клиент шлет SYN, сервер отвечает SYN-ACK, клиент завершает ACK.
Фишка в том, что на этом этапе сервер держит состояние для каждой “полуоткрытой” сессии в очереди backlog и под это выделяются ресурсы.
В SYN Flood атакующий шлет тысячи SYN-пакетов, но рукопожатие не завершает. Сервер продолжает ждать ACK, backlog забивается, и когда очередь переполнена, легитимные клиенты уже не могут подключиться. Получается DoS.
Почему атака такая живучая: из-за асимметрии. Нападающий кидает крошечные пакеты почти бесплатно, а серверу на каждый приходится тратить ресурсы. Даже слабая машина может уложить куда более мощный сервер.
Факт: SYN-флуды в прошлом валили GitHub, Cloudflare и разные базы. Защита обычно такая:
1. лимитить SYN от одного IP
2. дропать пакеты от известных плохих источников
3. и самое эффективное: SYN cookies
С SYN cookies сервер вообще ничего не хранит на этапе “полуоткрыто”. Он кодирует нужную инфу (IP клиента, порт, таймстамп и т.д.) в initial sequence number у SYN-ACK, который отправляет в ответ. Номер генерируется криптографически, подделать его сложно.
В итоге handshake становится по сути stateless со стороны сервера, пока клиент не докажет, что он реальный. Ресурсы резервируются только после верификации.
Кстати, в большинстве современных ОС поддержка SYN cookies уже встроена. В Linux это включается так:
net.ipv4.tcp_syncookies = 1.Если хочется копнуть глубже, статьи в Wikipedia по теме реально норм, плюс можно добить деталями через любимую LLM.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
А что если можно копировать гигабайты данных, вообще не копируя их?
Базы, рантаймы языков и ОС по сути так и делают через copy-on-write (COW).
Классический пример: fork процесса.
Когда ты форкаешь unix-процесс, формально создается полная копия памяти родителя. Но реально дублировать гигабайты RAM было бы адски медленно и тупо расточительно.
Поэтому сначала оба процесса просто указывают на одни и те же страницы памяти. А настоящая копия страницы делается только в момент записи, когда кто-то пытается ее поменять. В итоге копирование откладывается, и ты вообще не платишь за те данные, которые не меняются.
Языки программирования типа PHP и Ruby используют похожую идею. Когда ты присваиваешь уже существующее значение новой переменной, копия не создается сразу, она появляется только если значение потом модифицируют.
👉 @BackendPortal
Базы, рантаймы языков и ОС по сути так и делают через copy-on-write (COW).
Классический пример: fork процесса.
Когда ты форкаешь unix-процесс, формально создается полная копия памяти родителя. Но реально дублировать гигабайты RAM было бы адски медленно и тупо расточительно.
Поэтому сначала оба процесса просто указывают на одни и те же страницы памяти. А настоящая копия страницы делается только в момент записи, когда кто-то пытается ее поменять. В итоге копирование откладывается, и ты вообще не платишь за те данные, которые не меняются.
Языки программирования типа PHP и Ruby используют похожую идею. Когда ты присваиваешь уже существующее значение новой переменной, копия не создается сразу, она появляется только если значение потом модифицируют.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6🔥2
Каждый разработчик должен понимать: изоляция арендаторов это не проблема базы данных.
Это проблема масштаба последствий.
Я понял это на практике.
Один пропущенный фильтр по арендатору.
И обычный выклад превращается в инцидент безопасности.
Любая система с несколькими арендаторами рано или поздно выбирает один из трёх уровней изоляции.
У каждого свой баланс между безопасностью, ценой и операционной проблемой.
1. Отдельная база данных на арендатора
Самая сильная изоляция. У каждого арендатора своя база. Никаких общих таблиц. Никакого общего состояния.
Плюсы очевидны.
Баг в одном арендаторе не утечёт в данные другого. Проверки проще. Разговоры про соответствие требованиям короче. Если что-то ломается, масштаб последствий небольшой.
Минусы приходят позже.
Нагрузка на сопровождение растёт очень быстро. Сотни или тысячи баз. Миграции превращаются в оркестрацию. Стоимость растёт вместе с числом арендаторов, а не с реальным использованием.
Подходит, когда арендаторы крупные, сильно регулируемые или с высоким риском. Плохо работает, если бездумно применять к “длинному хвосту” мелких клиентов.
2. Отдельная схема на арендатора
Средний вариант, который многие недооценивают.
Одна база на всех, но у каждого арендатора отдельная схема. Таблицы изолированы, а инфраструктура остаётся более-менее управляемой.
Границы яснее, чем при изоляции по строкам. Нет взрыва количества баз. Проверки остаются разумными. Большинство случайных утечек просто исчезают.
Но сложность всё равно накапливается.
Миграции нужно прогонять по множеству схем. Отчёты по всем арендаторам сразу становятся неудобными. Автоматизация не опция, а необходимость. Без неё модель разваливается под собственным весом.
Хорошо подходит, когда арендаторы сильно отличаются по размеру и хочется изоляцию без полной физической раздельности.
3. Изоляция по строкам
Самый дешёвый и самый опасный вариант.
Все арендаторы сидят в одних таблицах. Изоляция держится на столбце
Риск жесткий.
Один пропущенный фильтр и утечка данных. Один рефакторинг и изоляция сломалась. Один спешный хотфикс и можно открыть доступ ко всему. Безопасность зависит от того, что каждый слой всегда всё делает правильно.
Это работает только если поставить мощные “перила”: жёсткое ограничение запросов по арендатору, политики на уровне базы, принудительная проверка на уровне сервисов, и тесты, которые специально пытаются выйти за границы арендатора.
Без этого ты ставишь компанию на дисциплину.
Изоляция арендаторов это не выбор способа хранения. Это решение про доверие.
Запомни: это классический вопрос на собеседованиях.
👉 @BackendPortal
Это проблема масштаба последствий.
Я понял это на практике.
Один пропущенный фильтр по арендатору.
И обычный выклад превращается в инцидент безопасности.
Любая система с несколькими арендаторами рано или поздно выбирает один из трёх уровней изоляции.
У каждого свой баланс между безопасностью, ценой и операционной проблемой.
1. Отдельная база данных на арендатора
Самая сильная изоляция. У каждого арендатора своя база. Никаких общих таблиц. Никакого общего состояния.
Плюсы очевидны.
Баг в одном арендаторе не утечёт в данные другого. Проверки проще. Разговоры про соответствие требованиям короче. Если что-то ломается, масштаб последствий небольшой.
Минусы приходят позже.
Нагрузка на сопровождение растёт очень быстро. Сотни или тысячи баз. Миграции превращаются в оркестрацию. Стоимость растёт вместе с числом арендаторов, а не с реальным использованием.
Подходит, когда арендаторы крупные, сильно регулируемые или с высоким риском. Плохо работает, если бездумно применять к “длинному хвосту” мелких клиентов.
2. Отдельная схема на арендатора
Средний вариант, который многие недооценивают.
Одна база на всех, но у каждого арендатора отдельная схема. Таблицы изолированы, а инфраструктура остаётся более-менее управляемой.
Границы яснее, чем при изоляции по строкам. Нет взрыва количества баз. Проверки остаются разумными. Большинство случайных утечек просто исчезают.
Но сложность всё равно накапливается.
Миграции нужно прогонять по множеству схем. Отчёты по всем арендаторам сразу становятся неудобными. Автоматизация не опция, а необходимость. Без неё модель разваливается под собственным весом.
Хорошо подходит, когда арендаторы сильно отличаются по размеру и хочется изоляцию без полной физической раздельности.
3. Изоляция по строкам
Самый дешёвый и самый опасный вариант.
Все арендаторы сидят в одних таблицах. Изоляция держится на столбце
tenant_id и на том, как ты пишешь запросы. Инфраструктура простая, цена низкая, масштабировать легко.Риск жесткий.
Один пропущенный фильтр и утечка данных. Один рефакторинг и изоляция сломалась. Один спешный хотфикс и можно открыть доступ ко всему. Безопасность зависит от того, что каждый слой всегда всё делает правильно.
Это работает только если поставить мощные “перила”: жёсткое ограничение запросов по арендатору, политики на уровне базы, принудительная проверка на уровне сервисов, и тесты, которые специально пытаются выйти за границы арендатора.
Без этого ты ставишь компанию на дисциплину.
Изоляция арендаторов это не выбор способа хранения. Это решение про доверие.
Запомни: это классический вопрос на собеседованиях.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍1