Анализ статистики управляемой базы данных Redis с помощью стека Elastic в Ubuntu 18.04

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

Преимущества Elastic Stack (стека ELK) в мониторинге управляемой базы данных – это его хорошая поддержка поиска и возможность очень быстро добавить новые данные. Стек ELK не лучший в обновлении данных, но это приемлемо при мониторинге и логировании, где старые данные почти никогда не меняются. Elasticsearch предлагает мощные средства запроса данных, которые вы можете визуализировать через Kibana, чтобы лучше понять, как работает база данных в разные периоды времени. Это позволит вам соотнести нагрузку на БД с реальными событиями и получить полное представление о процессе.

В этом мануале вы научитесь импортировать метрики базы данных Redis, сгенерированные командой INFO, в Elasticsearch через Logstash. Мы настроим Logstash для периодического запуска команды, анализа ее выходных данных и отправки их в Elasticsearch для дальнейшей индексации. Импортированные данные позже можно проанализировать и визуализировать с помощью Kibana. К концу мануала у вас будет автоматизированная система сбора статистики Redis для последующего анализа.

Требования

1: Установка и настройка Logstash

Сначала мы установим и настроим Logstash, а затем настроим его для загрузки статистики из кластера Redis, обработки и отправки ее в Elasticsearch на индексацию.

Чтобы установить Logstash, введите команду:

sudo apt install logstash -y

После установки Logstash включите сервис, чтобы инструмент автоматически запускался при загрузке сервера:

sudo systemctl enable logstash

Прежде чем настраивать Logstash для получения статистики, давайте посмотрим, как выглядят сами данные.

В дальнейшей работе вам понадобится такая команда:

redli --tls -h database_name –a show-password –p 25061

Некоторые провайдеры настраивают клиент Redli предварительно. Эту команду нужно использовать для подключения к своей БД, указав в ней свои данные. Выполните следующую команду на своем сервере, заменив redli_flags_command предыдущей командой с вашими данными:

redli_flags_command info

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

В выходных данных команды Redis info разделы отмечены символом #, который означает комментарий. Значения заполняются в формате «ключ:значение», что позволяет относительно легко их анализировать.

# Server
redis_version:5.0.4
redis_git_sha1:ab60b2b1
redis_git_dirty:1
redis_build_id:7909f4de3561dc50
redis_mode:standalone
os:Linux 5.2.14-200.fc30.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:9.1.1
process_id:72
run_id:ddb7b96c93bbd0c369c6d06ce1c02c78902e13cc
tcp_port:25060
uptime_in_seconds:1733
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:8687593
executable:/usr/bin/redis-server
config_file:/etc/redis.conf
# Clients
connected_clients:3
client_recent_max_input_buffer:2
client_recent_max_output_buffer:0
blocked_clients:0
. . .

Раздел Server содержит техническую информацию о сборке Redis: ее версию, коммит Git, на котором она основана и т.д. Раздел Clients содержит данные о текущих открытых соединениях.

. . .
# Memory
used_memory:941560
used_memory_human:919.49K
used_memory_rss:4931584
used_memory_rss_human:4.70M
used_memory_peak:941560
used_memory_peak_human:919.49K
used_memory_peak_perc:100.00%
used_memory_overhead:912190
used_memory_startup:795880
used_memory_dataset:29370
used_memory_dataset_perc:20.16%
allocator_allocated:949568
allocator_active:1269760
allocator_resident:3592192
total_system_memory:1030356992
total_system_memory_human:982.62M
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:463470592
maxmemory_human:442.00M
maxmemory_policy:allkeys-lru
allocator_frag_ratio:1.34
allocator_frag_bytes:320192
allocator_rss_ratio:2.83
allocator_rss_bytes:2322432
rss_overhead_ratio:1.37
rss_overhead_bytes:1339392
mem_fragmentation_ratio:5.89
mem_fragmentation_bytes:4093872
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:116310
mem_aof_buffer:0
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
lazyfree_pending_objects:0
. . .

Размер Memory подтверждает объем ОЗУ, выделенный Redis, а также максимальный объем памяти, который он может использовать. Если Redis начинает исчерпывать память, он освобождает ключи, согласно стратегии, указанной в поле maxmemory_policy в этом выводе.

. . .
# Persistence
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1568966978
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:0
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:217088
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0
# Stats
total_connections_received:213
total_commands_processed:2340
instantaneous_ops_per_sec:1
total_net_input_bytes:39205
total_net_output_bytes:776988
instantaneous_input_kbps:0.02
instantaneous_output_kbps:2.01
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:353
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0
. . .

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

. . .
# Replication
role:master
connected_slaves:0
master_replid:9c1d345a46d29d08537981c4fc44e312a21a160b
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:46137344
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
. . .

Посмотрев role в разделе Replication, вы узнаете, к какой ноде вы подключены: к первичной или к реплике. В оставшейся части раздела приводится количество подключенных в данный момент реплик и объем данных, которые есть на первичной ноде, но еще нет на реплике. Здесь могут быть дополнительные поля, если экземпляр, к которому вы подключены, является репликой.

. . .
# CPU
used_cpu_sys:1.972003
used_cpu_user:1.765318
used_cpu_sys_children:0.000000
used_cpu_user_children:0.001707
# Cluster
cluster_enabled:0
# Keyspace

В разделе CPU вы увидите объем системного (used_cpu_sys) и пользовательского (used_cpu_user) процессора, который Redis потребляет в данный момент. Раздел Cluster содержит только одно уникальное поле cluster_enabled, которое показывает, что кластер Redis работает.

Задача Logstash будет периодически запускать команду info в базе данных Redis (так же, как это сделали вы), анализировать результаты и отправлять их в Elasticsearch. Затем вы сможете получить к ним доступ из Kibana.

Хранить конфигурацию для индексации статистики Redis в Elasticsearch мы будем в файле redis.conf в каталоге /etc/logstash/conf.d, где Logstash хранит другие файлы конфигурации. При запуске в качестве сервиса он будет автоматически запускаться в фоновом режиме.

Создайте redis.conf:

sudo nano /etc/logstash/conf.d/redis.conf

Вставьте в файл такие строки:

input {
exec {
command => "redis_flags_command info"
interval => 10
type => "redis_info"
}
}
filter {
kv {
value_split => ":"
field_split => "\r\n"
remove_field => [ "command", "message" ]
}
ruby {
code =>
"
event.to_hash.keys.each { |k|
if event.get(k).to_i.to_s == event.get(k) # is integer?
event.set(k, event.get(k).to_i) # convert to integer
end
if event.get(k).to_f.to_s == event.get(k) # is float?
event.set(k, event.get(k).to_f) # convert to float
end
}
puts 'Ruby filter finished'
"
}
}
output {
elasticsearch {
hosts => "http://localhost:9200"
index => "%{type}"
}
}

Не забудьте заменить redis_flags_command командой, которую вы использовали ранее.

В файле мы определяем input (это набор фильтров, которые будут работать с собранными данными) и output (который будет отправлять отфильтрованные данные в Elasticsearch). Входные данные включают в себя команду exec, которая будет периодически запускать command на сервере через заданный interval (интервал времени, выраженный в секундах). Input также указывает параметр type, который определяет тип документа при индексации в Elasticsearch. Блок exec передает объект, содержащий два поля, строки command и message. Поле command будет содержать команду, которую нужно выполнить, а поле message будет содержать ее вывод.

В файле есть два фильтра, которые будут последовательно работать с данными, полученными из input. Фильтр kv – это фильтр key-value, встроенный в Logstash. Он используется для анализа данных в общем виде key(разделитель)value и предоставляет параметры для определения разделителей полей. Разделитель полей – это строка, которая отделяет друг от друга данные, отформатированные в общем виде. В случае вывода команды Redis INFO разделителем полей (field_split) является новая строка, а разделителем значений (value_split) является двоеточие. Строки, которые не соответствуют определенному формату, будут удалены, включая комментарии.

Чтобы настроить фильтр kv, нужно передать двоеточие параметру value_split, и \r\n (что обозначает новую строку) параметру field_split. Также он должен удалять поля команд и сообщений из текущего объекта данных, передав их в remove_field как элементы массива, поскольку они содержат данные, которые теперь бесполезны.

Фильтр kv представляет значение, которое он анализировал как изначально строковый (текстовый) тип. Здесь возникает проблема: Kibana с трудом обрабатывает строковые типы, даже если на самом деле в строке содержится число. Чтобы решить эту проблему, нужно использовать пользовательский код Ruby для преобразования строк, состоящих только из цифр, в числа (где это возможно). Второй фильтр – это блок ruby, который предоставляет параметр code; он принимает строку, содержащую код, который нужно запустить.

event – это переменная Logstash, которая содержит текущие данные в конвейере фильтра. Как было отмечено ранее, фильтры запускаются один за другим, а это означает, что фильтр Ruby будет получать данные, проанализированные фильтром kv. Сам код Ruby преобразует event в хэш и перебирает ключи, а затем проверяет, может ли значение, связанное с ключом, быть представлено как целое число или как число с плавающей точкой. Если это возможно, строковое значение заменяется обработанным числом. Когда цикл завершается, он выводит сообщение (Ruby filter finished), чтобы рассказать о прогрессе.

output отправляет обработанные данные для индексации в Elasticsearch. Полученный документ будет сохранен в индексе redis_info, определен в input и передан в качестве параметра в блок output.

Сохраните и закройте файл.

Вы установили Logstash с помощью пакетного менеджера apt и настроили его для периодического запроса статистики Redis, ее обработки и отправки в Elasticsearch.

2: Тестирование конфигурации Logstash

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

Logstash поддерживает запуск определенной конфигурации, передавая путь к файлу через параметр -f. Выполните следующую команду, чтобы протестировать новую конфигурацию:

sudo /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/redis.conf

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

WARNING: Could not find logstash.yml which is typically located in $LS_HOME/config or /etc/logstash. You can specify the path using --path.settings. Continuing using the defaults
Could not find log4j2 configuration at path /usr/share/logstash/config/log4j2.properties. Using default config which logs errors to the console
[WARN ] 2019-09-20 11:59:53.440 [LogStash::Runner] multilocal - Ignoring the 'pipelines.yml' file because modules or command line options are specified

[INFO ] 2019-09-20 11:59:53.459 [LogStash::Runner] runner - Starting Logstash {"logstash.version"=>"6.8.3"}


[INFO ] 2019-09-20 12:00:02.543 [Converge PipelineAction::Create<main>] pipeline - Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>2, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>50}


[INFO ] 2019-09-20 12:00:03.331 [[main]-pipeline-manager] elasticsearch - Elasticsearch pool URLs updated {:changes=>{:removed=>[], :added=>[http://localhost:9200/]}}


[WARN ] 2019-09-20 12:00:03.727 [[main]-pipeline-manager] elasticsearch - Restored connection to ES instance {:url=>"http://localhost:9200/"}


[INFO ] 2019-09-20 12:00:04.015 [[main]-pipeline-manager] elasticsearch - ES Output version determined {:es_version=>6}


[WARN ] 2019-09-20 12:00:04.020 [[main]-pipeline-manager] elasticsearch - Detected a 6.x and above cluster: the `type` event field won't be used to determine the document _type {:es_version=>6}


[INFO ] 2019-09-20 12:00:04.071 [[main]-pipeline-manager] elasticsearch - New Elasticsearch output {:class=>"LogStash::Outputs::ElasticSearch", :hosts=>["http://localhost:9200"]}


[INFO ] 2019-09-20 12:00:04.100 [Ruby-0-Thread-5: :1] elasticsearch - Using default mapping template


[INFO ] 2019-09-20 12:00:04.146 [Ruby-0-Thread-5: :1] elasticsearch - Attempting to install template {:manage_template=>{"template"=>"logstash-*", "version"=>60001, "settings"=>{"index.refresh_interval"=>"5s"}, "mappings"=>{"_default_"=>{"dynamic_templates"=>[{"message_field"=>{"path_match"=>"message", "match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false}}}, {"string_fields"=>{"match"=>"*", "match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false, "fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}}}}], "properties"=>{"@timestamp"=>{"type"=>"date"}, "@version"=>{"type"=>"keyword"}, "geoip"=>{"dynamic"=>true, "properties"=>{"ip"=>{"type"=>"ip"}, "location"=>{"type"=>"geo_point"}, "latitude"=>{"type"=>"half_float"}, "longitude"=>{"type"=>"half_float"}}}}}}}}


[INFO ] 2019-09-20 12:00:04.295 [[main]-pipeline-manager] exec - Registering Exec Input {:type=>"redis_info", :command=>"...", :interval=>10, :schedule=>nil}


[INFO ] 2019-09-20 12:00:04.315 [Converge PipelineAction::Create<main>] pipeline - Pipeline started successfully {:pipeline_id=>"main", :thread=>"#<Thread:0x73adceba run>"}


[INFO ] 2019-09-20 12:00:04.483 [Ruby-0-Thread-1: /usr/share/logstash/lib/bootstrap/environment.rb:6] agent - Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}


[INFO ] 2019-09-20 12:00:05.318 [Api Webserver] agent - Successfully started Logstash API endpoint {:port=>9600}

Ruby filter finished
Ruby filter finished
Ruby filter finished
...

Вы увидите, что сообщение Ruby filter finished отображается регулярно, с определенным промежутком времени (ранее мы установили интервал в 10 секунд), что означает, что статистика отправляется в Elasticsearch.

Вы можете выйти из Logstash, нажав CTRL+C. Как упоминалось ранее, Logstash автоматически запускает все конфигурации, находящиеся в /etc/logstash/conf.d, в фоновом режиме при запуске в качестве сервиса. Используйте следующую команду, чтобы запустить сервис:

sudo systemctl start logstash

Вы запустили Logstash, и убедились, что он может подключаться к кластеру Redis и собрать данные. Далее мы покажем, как обрабатывать статистические данные в Kibana.

3: Визуализация данных в Kibana

В этом разделе мы изучим и визуализируем статистические данные, описывающие производительность БД, в Kibana.

В веб-браузере перейдите к своему домену, по которому работает Kibana. Вы увидите стандартную приветственную страницу.

Прежде чем исследовать данные, которые Logstash отправляет в Elasticsearch, вам нужно добавить в Kibana индекс redis_info. Для этого нажмите Management в левой вертикальной боковой панели, а затем Index Patterns в разделе Kibana.

Вы увидите форму для создания нового шаблона индекса, Index Pattern. Шаблоны индексов в Kibana определяют способ извлечения данных из нескольких индексов Elasticsearch одновременно и могут использоваться для изучения одного индекса.

Под текстовым полем Index pattern вы увидите запись redis_info. Введите его в текстовое поле и нажмите кнопку Next step.

Затем вам будет предложено выбрать поле для метки времени, чтобы позже вы могли сузить область поиска по временному диапазону. Logstash автоматически добавляет одну метку, @timestamp. Выберите ее из выпадающего списка и нажмите Create index pattern, чтобы завершить добавление индекса в Kibana.

Чтобы создать и просмотреть существующие визуализации, кликните Visualize в левом меню.

Чтобы создать новую визуализацию, нажмите кнопку Create a visualization, затем выберите Line в списке всплывающих типов. Затем выберите в качестве источника данных шаблон индекса redis_info *, который вы только что создали. Вы увидите пустую визуализацию.

Левая панель предоставляет форму для редактирования параметров, которые Kibana будет использовать для рисования визуализации. Визуализация отобразится в центральной части экрана. В правом верхнем углу экрана находится указатель диапазона дат. Если в визуализации используется поле @timestamp, Kibana будет отображать только данные, относящиеся к временному интервалу, указанному в диапазоне.

Теперь вы сможете визуализировать среднее использование памяти Redis за указанный промежуток времени. Нажмите Y-Axis в разделе Metrics в панели слева, чтобы развернуть ее, затем выберите Average в качестве Aggregation и used_memory в качестве Field. Это заполнит ось Y графика средними значениями.

Затем нажмите X-Axis в Buckets. Для Aggregation выберите Date Histogram. Метка времени @timestamp должна быть автоматически выбрана в качестве Field. Затем отобразите визуализацию, нажав синюю кнопку Play в верхней части панели. Если ваша база данных является новой и в ней мало данных, строка будет короткой. Однако в любом случае вы увидите точное представление о среднем использовании памяти.

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

Заключение

Теперь на вашем сервере установлен стек Elastic. Он будет регулярно собирать статистические данные из управляемой БД Redis. Вы можете анализировать и визуализировать данные с помощью Kibana или другого похожего программного обеспечения, которое отобразит реальные корреляции в работе вашей БД.

Если вы хотите представить статистику БД, используя другой тип визуализации, обратитесь к документации Kibana для получения дальнейших инструкций.

Tags: , , , , , , ,