Запись данных в Clickhouse (и другие векторные базы) может достигать производительности в миллионы строк в секунду. Для этого важно писать данные крупными пакетами (сотни тысяч…миллионы строк в пакете).
Однако аналитические данные часто генерируются прямо на лету. Например, сбор данных о поведении пользователя на сайте. В [https://iotechnologies.com IO] – это один из ключевых источников данных, метрики приходят от миллиардов устройств. И тут крайне важно иметь минимальный путь от Web сервера до базы данных.
Идеальная схема будет включать только Web сервер и базу данных:
Событие -> Nginx -> Логи -> Clickhouse
## Событие будет логироваться Nginx’ом
Упростим нашу задачу до сбора и записи простых наборов метрик во времени:
В нашем случае таблица будет такой структуры:
CREATE TABLE metrics
( time DateTime, name String, value Int64)
ENGINE = MergeTree
PARTITION BY name
ORDER BY time
SETTINGS index_granularity = 8192
## Создание таблицы в Clickhouse
Трех колонок будет достаточно для решения нашей задачи. Обратите внимание, что мы даже не использовали дату для партиционирования.
Самая сложная задача – научить Nginx писать данные в нужном нам формате. Хотя с Nginx’ом она оказывается довольно простой. Собирать метрики будем обычным запросом в формате:
http://tracking.server/?n=metric_name&v=metric_value
## Два аргумента – для названия (n) и значения (v) метрики
Для того, чтобы вставлять данные в Clickhouse мы постараемся получить лог-файл в CSV-формате:
date_time,metric_name,metric_value
## Такой CSV формат можно сразу зафидить в Clickhouse
Например, при отправке пары запросов по адресу http://tracking.server/?n=pageviews&v=1, мы увидим:
2019-04-07 14:26:47,pageviews,1 2019-04-07 14:26:49,pageviews,1
Получить такой формат лога в Nginx’e оказалось довольно просто, но пришлось использовать [https://www.nginx.com/resources/wiki/modules/lua/ Lua] для получения времени в нужном формате:
map $host **$time** { # Определяем переменную $time
default ”;
}
log_format track ‘**$time,$arg_n,$arg_v**’; # Определяем нужный формат лога
server {
…
location / {
access_log /var/log/nginx/track.log track;
default_type text/plain;
content_by_lua ”
ngx.say(‘thanks’)
**ngx.var.time = os.date(‘!%Y-%m-%d %H:%M:%S’)** # Наполняем $time временем
“;
}
}
## Такая конфигурация позволит записать данные в /var/log/nginx/track.log в нужном формате
Чтобы записать данные из лога в Clickhouse, необходимо сначала сменить активный лог-файл (сделать rotate):
mv /var/log/nginx/track.log /tmp/db.log
kill -USR1 `cat /var/run/nginx.pid`
## Ротейтим лог перед записью в БД
Тепер можно записывать данные в Clickhouse:
cat /tmp/db.log | clickhouse-client --query "INSERT INTO metrics FORMAT CSV" && rm /tmp/db.log
## Обычный метод записи, ведь формат и данные уже готовы
Ну и объединить это в цикл с желаемым окном:
while :
do
mv /var/log/nginx/track.log /tmp/db.log
kill -USR1 `cat /var/run/nginx.pid`
cat /tmp/db.log | clickhouse-client –query “INSERT INTO metrics FORMAT CSV” && rm /tmp/db.log
**sleep 10**
done
## Ротейтим и записываем лог в базу каждые 10 секунд
Дополнительной оптимизацией может стать использование [https://clickhouse.yandex/docs/en/operations/table_engines/buffer/ буфера]. Если нагрузка на запись будет неравномерная (скажем, то 10 записей, то 10 тысяч записей), это имеет смысл. Работает все, как всегда, просто – достаточно создать специальную таблицу:
CREATE TABLE metrics_buffer
AS metrics
ENGINE = **Buffer**(default, metrics, 16, 10, 100, 1000, 10000, 10000, 100000)
## Создаем буфер для таблицы с метриками
Так Clickhouse создаст специальную таблицу, данные которой будут находиться только в памяти. Она будет повторять структуру нашей главной таблицы, и будет периодически сбрасывать в нее данные на основе указанных ограничений. Это повышает производительность вставки данных в основную таблицу, т.к. небольшие пакеты буферизируются и объединяются в более крупные.
Внимание, буферы чистятся при перезагрузке базы или сервера. Убедитесь, что у нее есть fail-over, если используете ее на продакшне.
Чтение данных также нужно делать из буфера вместо основной таблицы. Clickhouse сам замерджит данные из двух таблиц и выдаст правильный результат:
SELECT time, name, value FROM **metrics_buffer**
## Читать данные необходимо также из буфера
Мы тестировали решение на самом мелком [https://www.digitalocean.com/pricing/ дроплете на DigitalOcean]:
Если не учитывать задержки Интернета, то такое решение способно обслужить около 6…7 тыс. запросов в секунду (что и понятно, это же простой Nginx без оверхеда):
ab -n 100000 -c 16 "http://127.0.0.1/track?n=test&v=1" This is ApacheBench, Version 2.3 <$Revision: 1807734 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ ... Concurrency Level: 16 Time taken for tests: 15.553 seconds Complete requests: 100000 Failed requests: 0 Total transferred: 19000000 bytes HTML transferred: 700000 bytes **Requests per second: 6429.44 [#/sec] (mean)** Time per request: 2.489 [ms] (mean) Time per request: 0.156 [ms] (mean, across all concurrent requests) Transfer rate: 1192.96 [Kbytes/sec] received
## Тестирование пропускной способности
Собранный пример на этом же дроплете, который считает просмотры и количество пикселей, которые проехали мышки наших читателей можно [https://rt.onthe.io/?metric=5caa00c8e8260-distance&period=1%20hour найти тут]. Там же можно потестировать трекинг:
curl “rt.onthe.io/track?n=5caa00c8e8261-**[имя_метрики]**&v=1”
## Для трекинга
После отправки данных достаточно будет зайти по адресу:
https://rt.onthe.io/?metric=5caa00c8e8261-[имя_метрики]
## Для просмотра
Использование связки Nginx log + Clickhouse позволяет получить высокопроизводительное решение для сбора, хранения и аналитики временных рядов.
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…
Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…