October 12

Легенда (сбор данных и аналитика метрик с промышленных датчиков)

Какие тебе вопросы могут прилететь?

1. Откуда берешь данные ?

данные отправляются через kafka в нашу базу данных в формате time series данные + структурированные данные в виде json

От одного датчика каждые 5 секунд 1кб данных. Например у нас 1157 датчиков. За сутки 1157кб*12*60*24=2160000/10^-6 = 20Гб в сутки.

Данные хранятся 15 дней, хранение определяется retention policy в timescaleDB.

Кратко о kafka connector для postgres

https://www.timescale.com/blog/create-a-data-pipeline-with-timescaledb-and-kafka/

2. Как считали производительность?

Распределение данных между партициями позволяет значительно увеличить производительность. Чем больше партиций, тем больше потребителей может одновременно обрабатывать данные. Рекомендуется стремиться к тому, чтобы каждая партиция не превышала 1-2 ГБ данных.

Для передачи 20 ГБ в сутки:

Если партиция будет иметь около 1–2 ГБ данных, то для этого нам потребовалиось примерно 10–20 партиций.

Подробнее про расчет количества сообщений

  • Объем данных в сутки: 20 ГБ = 20 * 1024 * 1024 КБ = 20,971,520 КБ.
  • Количество сообщений:
    • Если каждое сообщение имеет размер 1 КБ:
      • 20,971,520 сообщений в день (20,971,520 КБ / 1 КБ).

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

  • Время в сутках: 24 и 60 минут, 60 секунд = 86,400 секунд в сутки.
  • Если каждое сообщение 1 КБ:

Количество топиков партиций и потребителей

  • Использовали по в топику на каждый из вариантов типов данных принимаемых от датчика (температора, давление итд)
  • Чтобы обеспечить стабильную производительность, рекомендуется использовать большее количество партиций. Например, чтобы обрабатывать 243 сообщений в секунду, потребуются несколько потребителей. Если распределять нагрузку между 10 потребителями, каждый из них должен обрабатывать около 25 сообщений в секунду.
  • В идеале, 10-20 партиций помогут обеспечить необходимую производительность и параллелизм обработки.
  • + наш bottleneck в записи в базу, поэтому для самой лучшей производительности нужно установить количество консумеров равному кол-ву партиций, в нашем случае это зависит от кол-ва подключения к БД (max_connection_pool в postgres по дефолту это 100) у нас может быть например 15-20.
  • в итоге случае будет 20 партиций распределенных на 6 топиков с данными от датчиков + около 15-20 консумеров.

producer(датчик с метрикой) -> топик/партиция ( с id определяющим вид метрики) -> 2-3 партиции -> группа из двух консумеров.

ПС: посмотри вкратце как примерно выглядит код для подготовки producer:

3. Сколько у вас было инстансов приложения?

У нас работал сервер, где можно было развернуть резервную копию инстанса

если несколько инстансов -> у нас сервис дискавери (ip серваков с инстансами) -> определять какой инстанс работает будем по health чек паттерн

4. Как хранишь данные?

Использовал Postgres с расширением timescaleDB сбора данных с датчиков

Кратко о kafka connector для postgres

https://www.timescale.com/blog/create-a-data-pipeline-with-timescaledb-and-kafka/

В моих данных две колонки: TIMESTAMP поле “time” и JSON поле с данными датчиков “data” где собраны данные в с определенного сенсора. Данные слишком часто меняются и следить за динамикой проще, когда данные приходят в JSON и конкретном блоке данных синхронизированным по времени.

(Для data view данные с JSON можно распарсить и вытащить данные о конкретном датчике в отдельную колонку)

выглядит примерно так, колонка time + это плоский json со списком данных во float формате:

time: “YYYY-MM-DDZHH-mm-ssZ”

{

id: датчик_1

sensor_qvd: 234.23,

sensor_evl: 322.293,

sensor_fdo: 28.892,

}

FYC: создание и insert в нашу таблицу для сбора данных выглядит примерно так:

а запрос можно сделать так:

Можно даже индекс задать на колонке JSONB на конкретное поле:

если вдруг будет вопрос по железу: Кластер postgres на два сервера, один резервный сервер с двумя дисками процы xeon, 32 ГБ RAM, при объеме данных в 2Tb.

5. Почему Postgres + timescaleDB ?

Мы знали, что есть несколько подобных решений, например клик хаус, но это была бы отдельная база, только для чтения и сбора аналитики, для чего пришлось бы обучать или нанимать новых специалистов, но мы решили использовать TimescaleDB, чтобы работать с данными в одном стеке с Postgres. Основная база данных у нас — PostgreSQL, мы активно собираем данные с помощью нее, также используем эти же данные для чтения. Поэтому мы решили не создавать дополнительных слоев для передачи и складирования данных, а использовать timescaleDB, для ускорения работы с временными данными, а также создания data view слоя для выгрузки и трекинга аналитики. Мы решили, что правильнее будет не выходить за рамки экосистемы и не ошиблись. А также это решение оказалось быстрее остальных.

TimescaleDB показывает высокие результаты производительности, как в своем весе, так и среди колоночных СУБД. Кроме этого, решение может использовать экосистему PostgreSQL, что снижает порог входа и не вынуждает учить диалекты SQL. Область применения СУБД достаточно обширная.

К тому же есть множество кейсов где timescale используется для анализа Интернет вещей (IoT)

Сбор данных с датчиков: TimescaleDB отлично подходит для хранения и обработки данных, поступающих от множества IoT-устройств, таких как датчики температуры, давления и другие.

Анализ данных в реальном времени: Обработка и визуализация данных в реальном времени для принятия оперативных решений.

Дополнительная инфа:

краткий бенчмарк https://questdb.io/blog/2022/05/26/query-benchmark-questdb-versus-clickhouse-timescale/

На всякий случай: пример проекта с timescale

https://habr.com/en/companies/selectel/articles/756146/

6. А как читали данные и что там с аналитикой??

Мы использовали паттерн Data View для сбора данных, это денормализованное представление данных для отчетов и аналитиков, которое легко использовать потому что формат колонок уже будет подготовлен для них. Может использоваться для реализации механизмов, таких как кэширование и агрегация данных, чтобы обеспечить более быстрое извлечение информации.

  • Мы использовали представления (Views), которые агрегируют данные из одной или нескольких таблиц, чтобы предоставить более удобный формат для чтения. Это помогает упростить запросы и скрыть сложность схемы.
  • Также мы использовали материализованные представления по запросам, c использованием индексации по ним, на случай если нам нужны дополнительные агрегированные значения

7. Какие паттерны использовал в своем проекте?

В итоге у нас по сути готовый микросервисный паттерн CQRS. У нас есть модель(паттерн data view) для чтения. А для записи мы используем другую схему бд:

  • Схема для записи (Command Model): используется для обработки всех операций записи (создание, обновление, удаление) и хранит данные в модели, оптимизированной для изменения.
  • Схема для чтения (Query Model): ориентирована на операции чтения данных и имеет совершенно другую денормализованную структуру, которая оптимизирована для выполнения запросов и извлечения информации. (паттерн data view)

Для проверки инстансов используем stability pattern health check.

8. У вас микросервисный проект, как осуществлялась связь между сервисами?

Для синхронизированных запросов у нас применяется rest, + в качестве нотификации у нас рассылка email происходит с помощью планировщика cron с подготовленными python скриптами и темплейтами.

(Можно добавить, что при выявлении и загрузки объекта аномалии в таблицу аномалий, внутри БД срабатывал триггер, который постоянно мониторил эту таблицу, помогал формировать отчеты и запускал планировщик скриптов

триггеры на изменение данных:

https://postgrespro.ru/docs/postgresql/9.6/plpgsql-trigger#plpgsql-dml-trigger ).

Что тебя еще могут спросить

  • были графики и представления данныхс датчиков ?

Подключил прометеус, метрики собирал для интеграции с графаной, добавил источник данных("Data Sources") Prometheus в конфигурации Grafana.

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

  • Что такое Шардирование ? использовал на проекте?

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

Но на проекте не потребовалось и не использовалось ничего кроме репликации

Дополнительные материалы: