Forwarded from Академия цифрового развития
🚀 Завершилась наша встреча с Евгением Надточеевым — специалистом в области фриланса
Евгений Надточеев, опытный middle-fullstack-разработчик выступил перед начинающими IT-специалистами и фрилансерами в рамках проекта «Мастер.хаб».
Спикер рассказал:
✔️ каким критериям должна соответствовать платформа для успешного сотрудничества с заказчиками;
✔️ как правильно оценить проект и установить цену;
✔️ почему важно иметь портфолио из успешных самостоятельных проектов;
✔️ как развивать личный бренд;
✔️ как выбирать заказчиков и справляться с форс-мажорами;
✔️ об умении доверять работу другим специалистам и инструментам, чтобы сосредоточиться на важных задачах;
✔️ о важности грамотного планирования и контроля сроков.
👋 После выступления эксперта участники смогли задать интересующие вопросы и обменяться мнениями.
🖥 Следите за анонсами нашего проекта «Мастер.хаб», чтобы не пропустить новые интересные встречи.
Евгений Надточеев, опытный middle-fullstack-разработчик выступил перед начинающими IT-специалистами и фрилансерами в рамках проекта «Мастер.хаб».
Спикер рассказал:
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
SQL-запрос с SELECT FOR UPDATE: что это и зачем нужно
Привет! Сегодня разберем одну из самых полезных, но часто непонятных фишек SQL — оператор SELECT FOR UPDATE. Если вы работаете с базами данных и многопоточными приложениями, то наверняка сталкивались с данным механизмом🔒
Что вообще такое SELECT FOR UPDATE?
SELECT FOR UPDATE — это специальный вид SQL-запроса, который не только выбирает данные, но и блокирует выбранные строки до завершения транзакции. Проще говоря, это как табличка "Не трогать, работаю!" на выбранных данных.
Зачем это нужно?
Представьте классическую проблему: два пользователя одновременно снимают деньги с одного банковского счета.
Без блокировки:
1. Пользователь A читает баланс: 1000₽
2. Пользователь B читает баланс: 1000₽
3. Пользователь A снимает 500₽, записывает 500₽
4. Пользователь B снимает 700₽, записывает 300₽
5. Итог: на счете 300₽ вместо правильных 1000-500-700=-200₽ 😱
С SELECT FOR UPDATE:
1. Пользователь A блокирует строку и читает баланс: 1000₽
2. Пользователь B пытается заблокировать строку, но ждет
3. Пользователь A снимает 500₽, записывает 500₽ и завершает транзакцию
4. Пользователь B получает доступ, читает обновленный баланс: 500₽
5. Пользователь B снимает 700₽, записывает -200₽
6. Итог: на счете -200₽, как и должно быть ✅
Как это работает в разных СУБД
PostgreSQL:
Важные нюансы
1. Блокировка работает только внутри транзакции
Если вы выполните SELECT FOR UPDATE без BEGIN/START TRANSACTION, это бесполезно!
2. Есть разные виды блокировок
- FOR UPDATE — строгая блокировка, никто не может изменять данные
- FOR SHARE — другие могут читать, но не могут изменять
- NOWAIT — не ждать, если строка заблокирована (вызовет ошибку)
- SKIP LOCKED — пропустить заблокированные строки
3. Опасность дедлоков
Если две транзакции блокируют ресурсы и ждут освобождения ресурсов друг друга — возникает дедлок. СУБД обычно обнаруживает это и прерывает одну из транзакций.
Реальные примеры использования
1) Обработка заказов в интернет-магазине
2) Распределение задач между воркерами
Когда НЕ использовать SELECT FOR UPDATE
- Когда достаточно уникальных ограничений или других механизмов целостности
- При очень высокой нагрузке (блокировки создают очереди)
- Когда транзакции длительные (блокировки держатся дольше)
- Когда можно применить оптимистичную блокировку (версионирование)
Альтернативы
1. Оптимистичная блокировка.
2. Атомарные операции.
SELECT FOR UPDATE — мощный инструмент для обеспечения целостности данных в конкурентной среде. Используйте его, когда:
- Нужна гарантия, что данные не изменятся между чтением и обновлением
- Обрабатываете критически важные операции (финансы, бронирование)
- Транзакции короткие и быстрые
Но помните про производительность — каждая блокировка создает очередь из других транзакций!
А вы используете SELECT FOR UPDATE в своих проектах? Делитесь опытом в комментариях! 👇
#sql #database #transactions #postgresql #mysql
Привет! Сегодня разберем одну из самых полезных, но часто непонятных фишек SQL — оператор SELECT FOR UPDATE. Если вы работаете с базами данных и многопоточными приложениями, то наверняка сталкивались с данным механизмом🔒
Что вообще такое SELECT FOR UPDATE?
SELECT FOR UPDATE — это специальный вид SQL-запроса, который не только выбирает данные, но и блокирует выбранные строки до завершения транзакции. Проще говоря, это как табличка "Не трогать, работаю!" на выбранных данных.
BEGIN;
SELECT * FROM accounts WHERE id = 123 FOR UPDATE;
-- ... другие операции ...
COMMIT;
Зачем это нужно?
Представьте классическую проблему: два пользователя одновременно снимают деньги с одного банковского счета.
Без блокировки:
1. Пользователь A читает баланс: 1000₽
2. Пользователь B читает баланс: 1000₽
3. Пользователь A снимает 500₽, записывает 500₽
4. Пользователь B снимает 700₽, записывает 300₽
5. Итог: на счете 300₽ вместо правильных 1000-500-700=-200₽ 😱
С SELECT FOR UPDATE:
1. Пользователь A блокирует строку и читает баланс: 1000₽
2. Пользователь B пытается заблокировать строку, но ждет
3. Пользователь A снимает 500₽, записывает 500₽ и завершает транзакцию
4. Пользователь B получает доступ, читает обновленный баланс: 500₽
5. Пользователь B снимает 700₽, записывает -200₽
6. Итог: на счете -200₽, как и должно быть ✅
Как это работает в разных СУБД
PostgreSQL:
BEGIN;
SELECT * FROM products WHERE id = 10 FOR UPDATE;
UPDATE products SET stock = stock - 1 WHERE id = 10;
COMMIT;
Важные нюансы
1. Блокировка работает только внутри транзакции
Если вы выполните SELECT FOR UPDATE без BEGIN/START TRANSACTION, это бесполезно!
2. Есть разные виды блокировок
- FOR UPDATE — строгая блокировка, никто не может изменять данные
- FOR SHARE — другие могут читать, но не могут изменять
- NOWAIT — не ждать, если строка заблокирована (вызовет ошибку)
- SKIP LOCKED — пропустить заблокированные строки
-- Не ждать, если строка заблокирована
SELECT * FROM accounts WHERE id = 123 FOR UPDATE NOWAIT;
-- Пропустить заблокированные строки
SELECT * FROM accounts WHERE balance > 1000 FOR UPDATE SKIP LOCKED;
3. Опасность дедлоков
Если две транзакции блокируют ресурсы и ждут освобождения ресурсов друг друга — возникает дедлок. СУБД обычно обнаруживает это и прерывает одну из транзакций.
Транзакция A: блокирует строку 1, ждет строку 2
Транзакция B: блокирует строку 2, ждет строку 1
Реальные примеры использования
1) Обработка заказов в интернет-магазине
BEGIN;
-- Проверяем и блокируем товар
SELECT * FROM products WHERE id = 101 AND stock >= 1 FOR UPDATE;
-- Проверяем и блокируем баланс
SELECT * FROM users WHERE id = 42 AND balance >= 999 FOR UPDATE;
-- Если мы здесь, значит оба условия выполнены и строки заблокированы
UPDATE products SET stock = stock - 1 WHERE id = 101;
UPDATE users SET balance = balance - 999 WHERE id = 42;
INSERT INTO orders (user_id, product_id, amount) VALUES (42, 101, 999);
COMMIT;
2) Распределение задач между воркерами
BEGIN;
SELECT id FROM tasks
WHERE status = 'pending'
ORDER BY priority DESC
LIMIT 1
FOR UPDATE SKIP LOCKED;
UPDATE tasks SET status = 'processing', worker_id = 123 WHERE id = ?;
COMMIT;
Когда НЕ использовать SELECT FOR UPDATE
- Когда достаточно уникальных ограничений или других механизмов целостности
- При очень высокой нагрузке (блокировки создают очереди)
- Когда транзакции длительные (блокировки держатся дольше)
- Когда можно применить оптимистичную блокировку (версионирование)
Альтернативы
1. Оптимистичная блокировка.
2. Атомарные операции.
SELECT FOR UPDATE — мощный инструмент для обеспечения целостности данных в конкурентной среде. Используйте его, когда:
- Нужна гарантия, что данные не изменятся между чтением и обновлением
- Обрабатываете критически важные операции (финансы, бронирование)
- Транзакции короткие и быстрые
Но помните про производительность — каждая блокировка создает очередь из других транзакций!
А вы используете SELECT FOR UPDATE в своих проектах? Делитесь опытом в комментариях! 👇
#sql #database #transactions #postgresql #mysql
Сегодня провёл для ребят на интенсиве в Школе21 от Сбера полуторачасовую лекцию на тему "Fullstack-разработка на JavaScript. Современная архитектура приложений, эволюция технологий, примеры из реальной жизни".
Было очень живо, много обратной связи и вопросов от ребят. Это и есть главная задача любого выступления на мой взгляд. Не хочется проводить мероприятие, где люди "спят" или сидят в телефонах, а потом быстро расходятся. В данном случае было точно не так - еще полчаса после доклада ребята спрашивали про развитие и эволюцию архитектуры, уточняли нюансы по фуллстэк-разработке и хотели узнать про мой личный опыт. На все старался дать развернутые ответы, но простым языком, много рисовал на доске, показывал примеры из своего стартапа и даже провели небольшой "system design interview", в ходе которого верхнеуровнево спроектировали Youtube (по ходу решали вопросы реальной разработки - масштабирование, отказоустойчивость, безопасность).
От этого, конечно, сильно заряжаешься и получаешь кайф, только такие выступления дают энергию и силы для дальнейших шагов. Уверен, что это не последнее мое выступление не только в рамках Школы21, но и вообще на конференциях. Спасибо, ребята!
Было очень живо, много обратной связи и вопросов от ребят. Это и есть главная задача любого выступления на мой взгляд. Не хочется проводить мероприятие, где люди "спят" или сидят в телефонах, а потом быстро расходятся. В данном случае было точно не так - еще полчаса после доклада ребята спрашивали про развитие и эволюцию архитектуры, уточняли нюансы по фуллстэк-разработке и хотели узнать про мой личный опыт. На все старался дать развернутые ответы, но простым языком, много рисовал на доске, показывал примеры из своего стартапа и даже провели небольшой "system design interview", в ходе которого верхнеуровнево спроектировали Youtube (по ходу решали вопросы реальной разработки - масштабирование, отказоустойчивость, безопасность).
От этого, конечно, сильно заряжаешься и получаешь кайф, только такие выступления дают энергию и силы для дальнейших шагов. Уверен, что это не последнее мое выступление не только в рамках Школы21, но и вообще на конференциях. Спасибо, ребята!
👍1
Часть 2. Теория
Теория.
Задержка цикла событий — это время, которое задача проводит в очереди, ожидая своего выполнения в однопоточном цикле событий. Проще говоря, это метрика, показывающая, насколько "заторможено" JavaScript-приложение.
Это специальный механизм в Node.js, который позволяет отложить выполнение функции до следующей итерации цикла событий, но до обработки других асинхронных операций.
Почему nextTick() имеет высший приоритет
1. Исторические причины: nextTick() появился до промисов и других механизмов асинхронности
2. Внутренние потребности Node.js: используется для обеспечения согласованного поведения API
3. Предсказуемость: гарантирует выполнение до любых операций ввода/вывода
4. Производительность: позволяет выполнять критически важные операции без полного цикла Event Loop
1. Динамические модули с помощью
2. Динамическая загрузка модулей в провайдерах const pluginModule = await import(
Преимущества динамических импортов в NestJS
1. Улучшение производительности запуска: загрузка только необходимых модулей при старте
2. Снижение потребления памяти: модули загружаются только при необходимости
3. Гибкость: возможность адаптации приложения в зависимости от конфигурации
4. Расширяемость: создание систем плагинов и расширений
Хранят данные по колонкам, а не по строкам, как традиционные реляционные СУБД.
1. Экстремальная скорость аналитических запросов.
Колоночное хранение позволяет читать только нужные колонки, а не все строки целиком:
2. Высокая степень сжатия данных
Данные одного типа в колонке лучше сжимаются
ClickHouse может достигать 10:1 сжатия по сравнению с традиционными СУБД
Экономия дискового пространства до 90%
3. Масштабируемость и параллельная обработка
Линейное масштабирование с добавлением узлов
Автоматическое распределение данных и запросов
Параллельное выполнение запросов на всех доступных ядрах CPU
4. Специализированные движки таблиц
ClickHouse предлагает множество движков для разных сценариев:
MergeTree — основной движок для аналитических данных
ReplacingMergeTree — для устранения дубликатов
AggregatingMergeTree — для предварительной агрегации
Distributed — для распределенных таблиц
5. Эффективная агрегация данных
6. Встроенные аналитические функции
Несмотря на все преимущества, ClickHouse не универсален:
1) Нет полноценной поддержки UPDATE/DELETE — ориентирован на добавление данных
2) Высокая латентность вставки единичных записей — оптимизирован для пакетной вставки
ClickHouse обязателен к использованию, когда традиционные СУБД не справляются с:
- Аналитикой в реальном времени на больших объемах данных
- Хранением и обработкой логов и метрик в промышленных масштабах
- Системами телеметрии с миллионами устройств
- Высоконагруженными OLAP-системами
- Анализом временных рядов с высокой кардинальностью
#теория #sql
Теория.
1) Что такое Event Loop Lag.
Задержка цикла событий — это время, которое задача проводит в очереди, ожидая своего выполнения в однопоточном цикле событий. Проще говоря, это метрика, показывающая, насколько "заторможено" JavaScript-приложение.
2) Что такое process.nextTick() в Event Loop и почему он приоритетнее в Event Loop Queue.
Это специальный механизм в Node.js, который позволяет отложить выполнение функции до следующей итерации цикла событий, но до обработки других асинхронных операций.
Почему nextTick() имеет высший приоритет
1. Исторические причины: nextTick() появился до промисов и других механизмов асинхронности
2. Внутренние потребности Node.js: используется для обеспечения согласованного поведения API
3. Предсказуемость: гарантирует выполнение до любых операций ввода/вывода
4. Производительность: позволяет выполнять критически важные операции без полного цикла Event Loop
3) Динамические импорты в Nest.js.
// Статический импорт (загружается при старте приложения)
import { SomeService } from './some.service';
// Динамический импорт (загружается по требованию)
async function loadModule() {
const { SomeService } = await import('./some.service');
return new SomeService();
}
1. Динамические модули с помощью
forRoot() и register().2. Динамическая загрузка модулей в провайдерах const pluginModule = await import(
./plugins/${name}).Преимущества динамических импортов в NestJS
1. Улучшение производительности запуска: загрузка только необходимых модулей при старте
2. Снижение потребления памяти: модули загружаются только при необходимости
3. Гибкость: возможность адаптации приложения в зависимости от конфигурации
4. Расширяемость: создание систем плагинов и расширений
4) Преимущества колоночной СУБД (Clickhouse) и когда ее нужно использовать обязательно.
Хранят данные по колонкам, а не по строкам, как традиционные реляционные СУБД.
1. Экстремальная скорость аналитических запросов.
Колоночное хранение позволяет читать только нужные колонки, а не все строки целиком:
-- В ClickHouse такой запрос выполняется в десятки раз быстрее, чем в PostgreSQL
SELECT AVG(revenue)
FROM orders
WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31'
GROUP BY customer_segment;
2. Высокая степень сжатия данных
Данные одного типа в колонке лучше сжимаются
ClickHouse может достигать 10:1 сжатия по сравнению с традиционными СУБД
Экономия дискового пространства до 90%
3. Масштабируемость и параллельная обработка
Линейное масштабирование с добавлением узлов
Автоматическое распределение данных и запросов
Параллельное выполнение запросов на всех доступных ядрах CPU
4. Специализированные движки таблиц
ClickHouse предлагает множество движков для разных сценариев:
MergeTree — основной движок для аналитических данных
ReplacingMergeTree — для устранения дубликатов
AggregatingMergeTree — для предварительной агрегации
Distributed — для распределенных таблиц
5. Эффективная агрегация данных
6. Встроенные аналитические функции
Несмотря на все преимущества, ClickHouse не универсален:
1) Нет полноценной поддержки UPDATE/DELETE — ориентирован на добавление данных
2) Высокая латентность вставки единичных записей — оптимизирован для пакетной вставки
ClickHouse обязателен к использованию, когда традиционные СУБД не справляются с:
- Аналитикой в реальном времени на больших объемах данных
- Хранением и обработкой логов и метрик в промышленных масштабах
- Системами телеметрии с миллионами устройств
- Высоконагруженными OLAP-системами
- Анализом временных рядов с высокой кардинальностью
#теория #sql
5) DDD - расскажите, как использовали.
1. Структурировал приложение согласно слоям DDD:
src/
├── domain/ # Доменный слой
│ ├── entities/ # Доменные сущности
│ ├── value-objects/ # Объекты-значения
│ ├── aggregates/ # Агрегаты
│ ├── repositories/ # Интерфейсы репозиториев
│ ├── events/ # Доменные события
│ └── services/ # Доменные сервисы
│
├── application/ # Прикладной слой
│ ├── commands/ # Команды CQRS
│ ├── queries/ # Запросы CQRS
│ ├── dtos/ # DTO объекты
│ └── services/ # Сервисы приложения
│
├── infrastructure/ # Инфраструктурный слой
│ ├── database/ # Реализации репозиториев
│ ├── messaging/ # Реализация шины событий
│ ├── external/ # Интеграции с внешними сервисами
│ └── config/ # Конфигурация
│
└── presentation/ # Слой представления
├── controllers/ # REST контроллеры
├── middlewares/ # Middleware
└── filters/ # Exception фильтры
В доменном слое я создавал богатые сущности с инкапсулированной бизнес-логикой.
Объекты-значения для валидации и инкапсуляции правил.
Агрегаты для обеспечения согласованности.
Репозитории как интерфейсы в доменном слое.
Преимущества, которые я получил от применения DDD в NestJS:
1. Изоляция бизнес-логики — доменный слой не зависит от фреймворка и инфраструктуры
2. Улучшенная тестируемость — легко писать модульные тесты для доменной логики
3. Гибкость при смене технологий — можно заменить базу данных или API, не меняя бизнес-логику
4. Единый язык — разработчики и предметные эксперты используют одинаковые термины
5. Масштабируемость кодовой базы — четкое разделение ответственности упрощает расширение
6. Предсказуемость системы — инкапсуляция бизнес-правил внутри доменных объектов
NestJS отлично подходит для реализации DDD благодаря его модульной архитектуре, встроенной поддержке CQRS и инверсии зависимостей.
6) Физическое хранение данных в СУБД (SQL vs NoSQL). В каких случаях для проекта надо однозначно брать NoSQL СУБД MongoDB (когда НУЖНО использовать MongoDB).
MongoDB стоит выбирать, когда проект требует гибкой схемы, работы со сложными вложенными структурами, высокой производительности при работе с большими объемами данных переменной структуры.
1. Схема данных часто меняется или не определена заранее
- Разные объекты одной коллекции могут иметь разный набор полей
- Требуется быстро адаптироваться к изменениям бизнес-требований без миграций схемы
Пример: разрабатываем систему, где пользователи могут создавать собственные типы контента с произвольными наборами атрибутов. В SQL это потребовало бы сложной схемы с множеством таблиц или хранения JSON в специальных полях, а MongoDB позволяет просто сохранять разные структуры документов в одной коллекции.
2. Иерархические или вложенные структуры данных
- Требуется хранить и извлекать сложные иерархические структуры целиком
- Важно сохранять отношения "родитель-потомок" в одном документе
Пример: каталог товаров с множеством характеристик, вариаций, опций и вложенных категорий. В MongoDB можно хранить товар как единый документ со всеми его атрибутами и вложенными массивами, что упрощает запросы и повышает производительность.
3. Большие объемы неструктурированных или полуструктурированных данных
- Работаем с логами, событиями, сенсорными данными переменной структуры
- Храним документы, JSON-объекты из API или пользовательский контент
- Требуется эффективно индексировать и запрашивать данные без жесткой схемы
Пример: система аналитики, собирающая события с веб-сайтов, где структура событий может различаться в зависимости от источника и типа события.
YouTube
Владимир Хориков — Domain-driven design: Cамое важное
Подробнее о конференции DotNext: https://jrg.su/3WmFRE
— —
Владимиру хотелось бы показать самые важные на его взгляд части DDD с примерами на C#. Цель — дать обзор основных вещей из DDD, чтобы зритель смог быстро начать ориентироваться в них и применять на…
— —
Владимиру хотелось бы показать самые важные на его взгляд части DDD с примерами на C#. Цель — дать обзор основных вещей из DDD, чтобы зритель смог быстро начать ориентироваться в них и применять на…
🔥1
7) Жизненный цикл Nestjs и основные хуки.
У модуля есть 4 этапа жизненного цикла, которые можно использовать:
OnModuleInit - модуль инициализирован (Вызывается один раз после инициализации всех модулей).
OnApplicationBootstrap - модуль начал работу (Вызывается после того, как все модули инициализированы, но до того, как приложение начнет принимать запросы).
OnModuleDestroy - модуль уничтожается перед завершением приложения (Вызывается перед уничтожением модуля, например, при корректном завершении работы приложения).
beforeApplicationShutdown Вызывается после получения сигнала завершения (например, SIGTERM), но до вызова `onModuleDestroy()
OnApplicationShutdown - при поступлении внешнего сигнала о завершении (вызывается после всех onModuleDestroy()) и перед полной остановкой приложения
Порядок выполнения хуков в жизненном цикле:
1. Запуск приложения
2. Создание и регистрация модулей, провайдеров, контроллеров
3. Разрешение зависимостей
4. onModuleInit() - для всех провайдеров в каждом модуле
5. onApplicationBootstrap() - для всех провайдеров в каждом модуле
6. Приложение готово принимать запросы
7. При получении сигнала завершения:
- beforeApplicationShutdown()
- onModuleDestroy()
- onApplicationShutdown()
8. Приложение завершает работу
Особенности использования хуков жизненного цикла:
1. Все хуки могут быть асинхронными, что позволяет выполнять операции ввода-вывода.
2. Хуки можно использовать в провайдерах, контроллерах и модулях.
3. Необходимо корректно обрабатывать ошибки в хуках, особенно при инициализации.
4. Хуки выполняются последовательно для каждого модуля в порядке их регистрации.
8) Зачем нужен генератор и итератор в Javascript.
Итератор — это объект, предоставляющий стандартизированный способ последовательного доступа к элементам коллекции, скрывая детали внутренней структуры данных.
Итератор должен иметь метод
next(), который возвращает объект с двумя свойствами:- value — текущее значение
- done — флаг завершения итерации (true/false)
Генератор — это специальный тип функции, которая может приостанавливать своё выполнение, возвращать промежуточный результат и затем возобновлять работу с того места, где остановилась.
Генераторы определяются с помощью
function* и используют ключевое слово yield для возврата значений и приостановки выполнения.// Пример генератора
function* rangeGenerator(from, to) {
for (let i = from; i <= to; i++) {
yield i; // возвращает значение и приостанавливает выполнение
}
}
// Использование генератора
const iterator = rangeGenerator(1, 5);
console.log(iterator.next()); // { value: 1, done: false }
9) Может ли абстрактный класс инжектиться в Nest.js и почему. А интерфейс?
В NestJS абстрактные классы могут использоваться для инъекции зависимостей, а интерфейсы — нет. Это связано с особенностями работы TS и DI (Dependency Injection) в NestJS.
1. Стирание типов в TypeScript
TypeScript-интерфейсы существуют только на этапе компиляции и полностью удаляются в скомпилированном JavaScript-коде. Это называется "стиранием типов" (type erasure).
// TypeScript код с интерфейсом
interface UserService {
findById(id: string): Promise<User>;
}
То есть после компиляции в JavaScript интерфейса не существует и никакой информации об интерфейсе в runtime нет.
В отличие от интерфейсов, абстрактные классы транспилируются в обычные JavaScript-классы и сохраняются в рантайме.
2. Система DI в NestJS работает в рантайме
NestJS использует токены для идентификации провайдеров в своем контейнере DI. Эти токены должны существовать во время выполнения программы. Поскольку интерфейсы стираются, их нельзя использовать как токены, а абстрактные классы — можно.
11) Зачем нужны Worker Threads, как работают в js, отличия от Thread Pool.
1. Преодоление ограничений однопоточной модели
- JavaScript изначально однопоточный, что может вызывать проблемы при CPU-интенсивных задачах
- Блокировка основного потока приводит к "зависанию" UI в браузере или задержке обработки запросов в Node.js
2. Параллельное выполнение CPU-интенсивных задач
- Сложные вычисления (криптография, обработка изображений)
- Парсинг и обработка больших объемов данных
- Машинное обучение и анализ данных
3. Изоляция кода
- Выполнение потенциально нестабильного кода без риска для основного приложения
- Разделение ресурсоемких операций от основной логики
В Node.js Worker Threads доступны через встроенный модуль
worker_threads:// main.js
const { Worker, isMainThread, parentPort } = require('worker_threads');
if (isMainThread) {
// Код в основном потоке
const worker = new Worker(__filename);
worker.on('message', (result) => {
console.log('Результат из worker:', result);
});
worker.postMessage({ data: 'some data to process' });
} else {
// Код в worker потоке
parentPort.on('message', (message) => {
const result = performHeavyCalculation(message.data);
parentPort.postMessage(result);
});
}
Особенности Worker Threads:
1. Коммуникация через передачу сообщений
- Данные копируются между потоками (по умолчанию)
- Возможна передача по ссылке через
transferList или SharedArrayBuffer2. Изолированный контекст выполнения
- Каждый worker имеет собственный V8 контекст и event loop
- Нет доступа к глобальным переменным основного потока
3. Ограничения
- В браузере: ограниченный доступ к DOM, нет доступа к
window- В Node.js: ограниченный доступ к некоторым глобальным объектам
4. Накладные расходы
- Создание worker'а требует ресурсов
- Передача данных между потоками может быть затратной
Разница между Thread Pool и Worker Threads
Thread Pool | Worker Threads
--------------------------------|-------------------------
Управляется libuv | Управляется V8 и Node.js
Создается автоматически | Создаются вручную разработчиком
Используется для встроенных API | Используются для пользовательского кода
Ограниченный API | Полный доступ к Node.js API
Нельзя напрямую изменять | Полный контроль над кодом в потоке
12) Что такое Thread Pool в Node.js
Это набор потоков, управляемых библиотекой libuv, которые используются для выполнения асинхронных операций, блокирующих I/O и CPU-интенсивных задач.
1. Обработка блокирующих операций
- Файловые операции (fs модуль)
- Криптографические операции (crypto модуль)
- Сжатие/распаковка (zlib модуль)
- DNS-запросы (некоторые операции)
2. Поддержка асинхронности для блокирующих API
- Позволяет Node.js оставаться неблокирующим даже при работе с блокирующими операциями
Как работает Thread Pool:
1. Инициализация
- По умолчанию создается 4 потока (можно изменить через переменную среды UV_THREADPOOL_SIZE)
- Максимальное количество потоков: 1024
2. Жизненный цикл задачи
- Основной поток делегирует блокирующую операцию в Thread Pool
- Один из потоков пула выполняет операцию
- По завершении операции результат возвращается в основной поток через callback
3. Очередь задач
- Если все потоки заняты, задачи ставятся в очередь
- Задачи выполняются в порядке поступления (FIFO)
const fs = require('fs');
const crypto = require('crypto');
// Эти операции будут выполняться в Thread Pool
fs.readFile('/path/to/file', (err, data) => {
if (err) throw err;
console.log('Файл прочитан');
});
// Эта CPU-интенсивная операция также пойдет в Thread Pool
crypto.pbkdf2('password', 'salt', 100000, 512, 'sha512', (err, derivedKey) => {
if (err) throw err;
console.log('Пароль зашифрован');
});#теория #backend #nodejs
13) Батчинг в Кафке – как заставить ее не перегружать данными сервис.
Kafka может генерировать огромный поток сообщений, который потенциально может перегрузить сервисы-потребители. Это происходит по нескольким причинам:
1. Высокая пропускная способность Kafka (до миллионов сообщений в секунду)
2. Неравномерная нагрузка и пиковые всплески трафика
3. Ограниченные ресурсы сервисов-потребителей
4. Разная скорость обработки сообщений у продюсеров и консьюмеров
14) Как происходит чтение файла в Node.js
1. Синхронное чтение блокирующее (s.readFileSync).
2. Асинхронное чтение с колбэками (fs.readFile).
3. Асинхронное чтение с промисами (fs.promises). Все эти способы полностью загружают файл в память сервера.
4. Чтение с использованием потоков (Streams) (наиболее эффективный способ для больших файлов fs.createReadStream, чтение чанками).
5. Использование worker_threads для параллельной обработки.
6. Построчное чтение с readline (const readline = require('readline')).
Как можно оптимизировать и отследить работу запросов (на примере PostgreSQL)?
1) EXPLAIN и EXPLAIN ANALYZE
2) Системные представления статистики
3) pg_stat_statements
Расширение для отслеживания статистики выполнения запросов:
4) Внешние инструменты мониторинга
- pgAdmin - графический интерфейс с инструментами мониторинга
- Prometheus + Grafana - для сбора метрик и визуализации
- pg_stat_monitor - расширенная версия pg_stat_statements
- pgBadger - анализатор лог-файлов PostgreSQL
- pgHero - инструмент для мониторинга и анализа производительности
5) Оптимизация конфигурации сервера
shared_buffers = 1GB # 25% от RAM для выделенных серверов
work_mem = 32MB # Память для операций сортировки/хеширования
maintenance_work_mem = 256MB # Для VACUUM, CREATE INDEX и т.д.
effective_cache_size = 3GB # Доступный кэш
6) Оптимизация запросов
7) Идентификация медленных запросов
8) Мониторинг блокировок и взаимоблокировок
9) Мониторинг размера баз данных и таблиц
#теория #sql #postgresql #db
1) EXPLAIN и EXPLAIN ANALYZE
-- Базовый план выполнения
EXPLAIN SELECT * FROM users WHERE email LIKE '%@example.com';
-- План выполнения с реальными метриками
EXPLAIN ANALYZE SELECT * FROM users WHERE email LIKE '%@example.com';
2) Системные представления статистики
-- Активные запросы
SELECT pid, age(clock_timestamp(), query_start), usename, query
FROM pg_stat_activity
WHERE state != 'idle' AND query NOT ILIKE '%pg_stat_activity%'
ORDER BY query_start desc;
-- Статистика таблиц
SELECT schemaname, relname, seq_scan, seq_tup_read,
idx_scan, idx_tup_fetch, n_tup_ins, n_tup_upd, n_tup_del
FROM pg_stat_user_tables;
-- Статистика индексов
SELECT schemaname, relname, indexrelname, idx_scan,
idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes;
-- Блокировки
SELECT blocked_locks.pid AS blocked_pid,
blocking_locks.pid AS blocking_pid,
blocked_activity.usename AS blocked_user,
blocking_activity.usename AS blocking_user,
blocked_activity.query AS blocked_statement,
blocking_activity.query AS blocking_statement
FROM pg_catalog.pg_locks blocked_locks
JOIN pg_catalog.pg_locks blocking_locks
3) pg_stat_statements
Расширение для отслеживания статистики выполнения запросов:
-- Включение расширения
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- Просмотр статистики запросов
SELECT query, calls, total_exec_time, rows,
100.0 * shared_blks_hit / nullif(shared_blks_hit + shared_blks_read, 0) AS hit_percent
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
4) Внешние инструменты мониторинга
- pgAdmin - графический интерфейс с инструментами мониторинга
- Prometheus + Grafana - для сбора метрик и визуализации
- pg_stat_monitor - расширенная версия pg_stat_statements
- pgBadger - анализатор лог-файлов PostgreSQL
- pgHero - инструмент для мониторинга и анализа производительности
5) Оптимизация конфигурации сервера
shared_buffers = 1GB # 25% от RAM для выделенных серверов
work_mem = 32MB # Память для операций сортировки/хеширования
maintenance_work_mem = 256MB # Для VACUUM, CREATE INDEX и т.д.
effective_cache_size = 3GB # Доступный кэш
6) Оптимизация запросов
-- B-tree индекс (стандартный)
CREATE INDEX idx_users_email ON users(email);
-- Частичный индекс
CREATE INDEX idx_orders_status ON orders(status) WHERE status = 'active';
-- Многоколоночный индекс
CREATE INDEX idx_users_name_email ON users(last_name, first_name, email);
-- Индекс для полнотекстового поиска
CREATE INDEX idx_products_tsv ON products USING GIN (to_tsvector('english', description));
-- Индекс для операторов LIKE с префиксом
CREATE INDEX idx_users_email_pattern ON users(email varchar_pattern_ops);
7) Идентификация медленных запросов
# Настройки логирования в postgresql.conf
log_min_duration_statement = 200 # в миллисекундах (запросы длиннее 200мс)
log_statement = 'none' # 'none', 'ddl', 'mod', 'all'
log_line_prefix = '%t [%p]: [%l-1] user=%u,db=%d,app=%a,client=%h '
8) Мониторинг блокировок и взаимоблокировок
9) Мониторинг размера баз данных и таблиц
-- Размер баз данных
SELECT datname, pg_size_pretty(pg_database_size(datname)) AS size
FROM pg_database
ORDER BY pg_database_size(datname) DESC;
-- Размер таблиц
SELECT
relname AS table_name,
pg_size_pretty(pg_total_relation_size(relid)) AS total_size,
pg_size_pretty(pg_relation_size(relid)) AS data_size,
pg_size_pretty(pg_total_relation_size(relid) - pg_relation_size(relid)) AS external_size
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC;
-- Размер индексов
SELECT
relname AS table_name,
indexrelname AS index_name,
pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size
FROM pg_stat_user_indexes i
JOIN pg_class c ON i.indexrelid = c.oid
ORDER BY pg_relation_size(i.indexrelid) DESC;
#теория #sql #postgresql #db
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Forwarded from Академия цифрового развития
Кто такие фуллстак-разработчики и почему они нарасхват?
17 октября с Мастер.хаб разбираемся во всём:
Он покажет, как устроен реальный стартап в сфере недвижимости, и расскажет, с чего начать, если ты только присматриваешься к IT.
Приходи — будет просто, по делу и без лишней теории.
Регистрация по ссылке
Please open Telegram to view this post
VIEW IN TELEGRAM
Академия цифрового развития
Выступил в Школе21 с докладом на тему: "Fullstack-разработка на Javascript"
Хотя аудитория для выступления была небольшая и ребят было не очень много - мероприятие прошло отлично. Очень камерно пообщались, у студентов была отличная возможность задать интересующие вопросы, а у меня - дать как можно пользы для каждого на лекции. Немного затронули тему карьеры, развития разработчика и очень много рисовали примеров архитектуры на доске. Провожу данную лекцию в стенах Школы уже второй раз, поражает уровень технического оснащения, внешнего вида лекториев и комнат досуга - учиться здесь ребятам (при этом абсолютно бесплатно) одно удовольствие.
Спасибо всем большое, было очень круто!🥳
Хотя аудитория для выступления была небольшая и ребят было не очень много - мероприятие прошло отлично. Очень камерно пообщались, у студентов была отличная возможность задать интересующие вопросы, а у меня - дать как можно пользы для каждого на лекции. Немного затронули тему карьеры, развития разработчика и очень много рисовали примеров архитектуры на доске. Провожу данную лекцию в стенах Школы уже второй раз, поражает уровень технического оснащения, внешнего вида лекториев и комнат досуга - учиться здесь ребятам (при этом абсолютно бесплатно) одно удовольствие.
Спасибо всем большое, было очень круто!🥳
🔥3
Forwarded from Инженер и Менеджер
Ханойские крысиные метрики — урок всему ИТ
Посвещается всем менеджерам, которые сначала внедряют метрики, а потом думают. Давайте в Ханой, Въетнам — там тоже решили "чуток оптимизировать работу".
Французы захватили Вьетнам и чтобы грабить население с комфортом, построили в Ханое канализацию. Местные крысы обрадовались новой инфраструктуре и заселились туда всем селом. А крысы — это грязь, болезни и вообще некрасиво, так что французы начали думать.
Крыс надо было извести. Французы придумали отдать все на аутсорс и платить один цент за каждую убитую крысу. По плану, жители города будут сами охотиться на крыс и зарабатывать. Приносишь хвосты — получаешь деньги.
Один хвост — один цент. Идеальная метрика: проста, понятна, легко считается.
🐀 Чуете подвох?
Французы тоже не почуяли. Правда, через месяц крыс в городе стало даже больше. Французы платили и платили, а крыс становилось все больше и больше!
А потом зоркий французски глаз заметил странное.
Крыс много.
Хвостов у крыс нет.
Администрация прижала пару крысоловов, и они слили темку: оказалось, что крыс никто не убивал. Какой смысл? Если поймать крысу и убить ее, ты получишь один цент. Если отрезать хвост и отпустить крысу, ты получишь один цент и крысу, которая оставит после себя потомство!
Во всю силу заработали целые фермы по разведению крыс. Хвосты и центы текли рекой, а Ханой заполонили сотни тысяч крыс. Метрика росла, администрация может быть даже получила квартальный бонус.
💀 А потом в городе началась бубонная чума и стало как-то не до этого.
Мораль: если вы измеряете количество хвостов, вы получите много хвостов. И бонусом — бубонную чуму. А причем тут ИТ, каждый может додумать самостоятельно, я ни на что не намекал.
По возможности, не будьте как французы.
Посвещается всем менеджерам, которые сначала внедряют метрики, а потом думают. Давайте в Ханой, Въетнам — там тоже решили "чуток оптимизировать работу".
Французы захватили Вьетнам и чтобы грабить население с комфортом, построили в Ханое канализацию. Местные крысы обрадовались новой инфраструктуре и заселились туда всем селом. А крысы — это грязь, болезни и вообще некрасиво, так что французы начали думать.
Крыс надо было извести. Французы придумали отдать все на аутсорс и платить один цент за каждую убитую крысу. По плану, жители города будут сами охотиться на крыс и зарабатывать. Приносишь хвосты — получаешь деньги.
Один хвост — один цент. Идеальная метрика: проста, понятна, легко считается.
🐀 Чуете подвох?
Французы тоже не почуяли. Правда, через месяц крыс в городе стало даже больше. Французы платили и платили, а крыс становилось все больше и больше!
А потом зоркий французски глаз заметил странное.
Крыс много.
Хвостов у крыс нет.
Администрация прижала пару крысоловов, и они слили темку: оказалось, что крыс никто не убивал. Какой смысл? Если поймать крысу и убить ее, ты получишь один цент. Если отрезать хвост и отпустить крысу, ты получишь один цент и крысу, которая оставит после себя потомство!
Во всю силу заработали целые фермы по разведению крыс. Хвосты и центы текли рекой, а Ханой заполонили сотни тысяч крыс. Метрика росла, администрация может быть даже получила квартальный бонус.
💀 А потом в городе началась бубонная чума и стало как-то не до этого.
Мораль: если вы измеряете количество хвостов, вы получите много хвостов. И бонусом — бубонную чуму. А причем тут ИТ, каждый может додумать самостоятельно, я ни на что не намекал.
По возможности, не будьте как французы.
👌1
🎧 Подкасты, которые прокачают твой мозг
Собрал для вас огонь-подборку подкастов в Яндекс.Музыке. Слушай в дороге, на пробежке или пока готовишь ужин 👇
Собрал для вас огонь-подборку подкастов в Яндекс.Музыке. Слушай в дороге, на пробежке или пока готовишь ужин 👇
Привет, ребята! 😊
Хотел поделиться с вами крутым инструментом, который я нашёл для подготовки к собеседованиям. Это Preoffer — сервис, где собраны 20 000 реальных вопросов с собеседований по всем основным направлениям (Frontend, Backend, QA, Data Science и т.д.). Он помогает понять, что реально спрашивают на собеседованиях, и как к этому готовиться.
Я сам его протестировал и решил, что это будет полезно и вам!
Можно пользоваться бесплатно и смотреть материалы с Ютуба, а для более глубокого погружения можно взять премиум-подписку и прокачаться ещё сильнее!
🎉 Специально для таких случаев я договорился о скидке 500 рублей. Для этого нужно использовать промокод promo@eugene_nadtocheev при регистрации!
Заходите, пробуйте, и готовьтесь к собеседованиям с уверенностью! Вот ссылка: Preoffer
Хотел поделиться с вами крутым инструментом, который я нашёл для подготовки к собеседованиям. Это Preoffer — сервис, где собраны 20 000 реальных вопросов с собеседований по всем основным направлениям (Frontend, Backend, QA, Data Science и т.д.). Он помогает понять, что реально спрашивают на собеседованиях, и как к этому готовиться.
Я сам его протестировал и решил, что это будет полезно и вам!
Можно пользоваться бесплатно и смотреть материалы с Ютуба, а для более глубокого погружения можно взять премиум-подписку и прокачаться ещё сильнее!
🎉 Специально для таких случаев я договорился о скидке 500 рублей. Для этого нужно использовать промокод promo@eugene_nadtocheev при регистрации!
Заходите, пробуйте, и готовьтесь к собеседованиям с уверенностью! Вот ссылка: Preoffer
👍1