如何在Ubuntu18.04上使用ElasticStack分析托管Redis数据库统计信息
作为 Write for DOnations 计划的一部分,作者选择了 Free and Open Source Fund 来接受捐赠。
介绍
数据库监控是系统地跟踪各种指标的持续过程,这些指标显示了数据库的执行情况。 通过观察性能数据,您可以获得有价值的见解并识别可能的瓶颈,并找到提高数据库性能的其他方法。 此类系统通常会实施警报,在出现问题时通知管理员。 收集的统计信息不仅可以用来改进数据库的配置和工作流程,还可以用来改进客户端应用程序的配置和工作流程。
使用 Elastic Stack(ELK 堆栈)监控托管数据库的好处是它对搜索的出色支持和快速获取新数据的能力。 它不擅长更新数据,但这种权衡对于监控和记录目的是可以接受的,因为过去的数据几乎从不改变。 Elasticsearch 提供了一种强大的数据查询方式,您可以通过 Kibana 使用它来更好地了解数据库在不同时间段的运行情况。 这将允许您将数据库负载与现实事件相关联,以深入了解数据库的使用方式。
在本教程中,您将通过 Logstash 将 Redis INFO 命令生成的数据库指标导入 Elasticsearch。 这需要将 Logstash 配置为定期运行命令、解析其输出,然后立即将其发送到 Elasticsearch 进行索引。 导入的数据稍后可以在 Kibana 中进行分析和可视化。 在本教程结束时,您将拥有一个自动系统提取 Redis 统计信息以供以后分析。
先决条件
- 具有至少 8 GB RAM、root 权限和辅助非 root 帐户的 Ubuntu 18.04 服务器。 您可以按照 这个初始服务器设置指南 进行设置。 对于本教程,非 root 用户是
sammy
。 - 您的服务器上安装了 Java 8。 有关安装说明,请访问 How To Install Java with apt on Ubuntu 18.04 并按照第一步中列出的命令进行操作。 您不需要安装 Java 开发工具包 (JDK)。
- Nginx 安装在您的服务器上。 有关如何执行此操作的指南,请参阅 如何在 Ubuntu 18.04 上安装 Nginx 教程。
- 您的服务器上安装了 Elasticsearch 和 Kibana。 完成 如何在 Ubuntu 18.04 上安装 Elasticsearch、Logstash 和 Kibana (Elastic Stack) 教程的前两个步骤。
- 从 DigitalOcean 提供的 Redis 托管数据库,其中包含可用的连接信息。 确保您的服务器的 IP 地址在白名单中。 有关使用 DigitalOcean 控制面板创建 Redis 数据库的指南,请访问 Redis 快速入门指南 。
- Redli 根据 How To Connect to a Managed Database on Ubuntu 18.04 教程安装在您的服务器上。
第 1 步 — 安装和配置 Logstash
在本节中,您将安装 Logstash 并将其配置为从 Redis 数据库集群中提取统计信息,然后解析它们以发送到 Elasticsearch 进行索引。
首先使用以下命令安装 Logstash:
sudo apt install logstash -y
安装 Logstash 后,启用该服务以在启动时自动启动:
sudo systemctl enable logstash
在配置 Logstash 拉取统计数据之前,我们先来看看数据本身是什么样子的。 要连接到 Redis 数据库,请转到 Managed Database Control Panel,然后在 Connection details 面板下,从下拉列表中选择 Flags:
您将看到 Redli 客户端的预配置命令,您将使用该命令连接到数据库。 单击 Copy 并在您的服务器上运行以下命令,将 redli_flags_command
替换为您刚刚复制的命令:
redli_flags_command info
由于这个命令的输出很长,我们将把它分解成不同的部分来解释。
在 Redis info
命令的输出中,节标记为 #
,表示注释。 这些值以 key:value
的形式填充,这使得它们相对容易解析。
Server
部分包含有关 Redis 构建的技术信息,例如其版本和它所基于的 Git 提交,而 Clients
部分提供当前打开的连接数。
Output# Server redis_version:6.2.6 redis_git_sha1:4f4e829a redis_git_dirty:1 redis_build_id:5861572cb79aebf3 redis_mode:standalone os:Linux 5.11.12-300.fc34.x86_64 x86_64 arch_bits:64 multiplexing_api:epoll atomicvar_api:atomic-builtin gcc_version:11.2.1 process_id:79 process_supervised:systemd run_id:b8a0aa25d8f49a879112a04a817ac2acd92e0c75 tcp_port:25060 server_time_usec:1640878632737564 uptime_in_seconds:1679 uptime_in_days:0 hz:10 configured_hz:10 lru_clock:13488680 executable:/usr/bin/redis-server config_file:/etc/redis.conf io_threads_active:0 # Clients connected_clients:4 cluster_connections:0 maxclients:10032 client_recent_max_input_buffer:24 client_recent_max_output_buffer:0 ...
Memory
确认 Redis 为自己分配了多少 RAM,以及它可能使用的最大内存量。 如果它开始耗尽内存,它将使用您在控制面板中指定的策略释放密钥(显示在此输出中的 maxmemory_policy
字段中)。
Output... # Memory used_memory:977696 used_memory_human:954.78K used_memory_rss:9977856 used_memory_rss_human:9.52M used_memory_peak:977696 used_memory_peak_human:954.78K used_memory_peak_perc:100.00% used_memory_overhead:871632 used_memory_startup:810128 used_memory_dataset:106064 used_memory_dataset_perc:63.30% allocator_allocated:947216 allocator_active:1273856 allocator_resident:3510272 total_system_memory:1017667584 total_system_memory_human:970.52M 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:455081984 maxmemory_human:434.00M maxmemory_policy:noeviction allocator_frag_ratio:1.34 allocator_frag_bytes:326640 allocator_rss_ratio:2.76 allocator_rss_bytes:2236416 rss_overhead_ratio:2.84 rss_overhead_bytes:6467584 mem_fragmentation_ratio:11.43 mem_fragmentation_bytes:9104832 mem_not_counted_for_evict:0 mem_replication_backlog:0 mem_clients_slaves:0 mem_clients_normal:61504 mem_aof_buffer:0 mem_allocator:jemalloc-5.1.0 active_defrag_running:0 lazyfree_pending_objects:0 ...
在 Persistence
部分,您可以看到 Redis 上次将其存储的密钥保存到磁盘的时间,以及是否成功。 Stats
部分提供与客户端和集群内连接相关的数字、找到(或未找到)请求的密钥的次数等等。
Output... # Persistence loading:0 current_cow_size:0 current_cow_size_age:0 current_fork_perc:0.00 current_save_keys_processed:0 current_save_keys_total:0 rdb_changes_since_last_save:0 rdb_bgsave_in_progress:0 rdb_last_save_time:1640876954 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:1 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 module_fork_in_progress:0 module_fork_last_cow_size:0 # Stats total_connections_received:202 total_commands_processed:2290 instantaneous_ops_per_sec:0 total_net_input_bytes:38034 total_net_output_bytes:1103968 instantaneous_input_kbps:0.01 instantaneous_output_kbps:0.00 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 expire_cycle_cpu_milliseconds:29 evicted_keys:0 keyspace_hits:0 keyspace_misses:0 pubsub_channels:0 pubsub_patterns:0 latest_fork_usec:452 total_forks:1 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 tracking_total_keys:0 tracking_total_items:0 tracking_total_prefixes:0 unexpected_error_replies:0 total_error_replies:0 dump_payload_sanitizations:0 total_reads_processed:2489 total_writes_processed:2290 io_threaded_reads_processed:0 io_threaded_writes_processed:0 ...
通过查看 Replication
下的 role
,您将知道您是连接到主节点还是副本节点。 本节的其余部分提供了当前连接的副本的数量以及副本相对于主副本缺少的数据量。 如果您连接的实例是副本,则可能会有其他字段。
注意: Redis 项目在其文档和各种命令中使用术语“主”和“从”。 DigitalOcean 通常更喜欢替代术语“主要”和“副本”。 本指南将尽可能默认使用术语“主”和“副本”,但请注意在某些情况下不可避免地会出现术语“主”和“从”。
Output... # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:f727fad3691f2a8d8e593b087c468bbb83703af3 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:45088768 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 ...
在 CPU
下,您将看到 Redis 目前消耗的系统 (used_cpu_sys
) 和用户 (used_cpu_user
) CPU 功率量。 Cluster
部分仅包含一个唯一字段 cluster_enabled
,用于指示 Redis 集群正在运行。
Output... # CPU used_cpu_sys:1.617986 used_cpu_user:1.248422 used_cpu_sys_children:0.000000 used_cpu_user_children:0.001459 used_cpu_sys_main_thread:1.567638 used_cpu_user_main_thread:1.218768 # Modules # Errorstats # Cluster cluster_enabled:0 # Keyspace
Logstash 的任务是定期在您的 Redis 数据库上运行 info
命令(类似于您刚才所做的),解析结果并将它们发送到 Elasticsearch。 然后,您以后就可以从 Kibana 访问它们。
您将在 Elasticsearch 中将用于索引 Redis 统计信息的配置存储在 /etc/logstash/conf.d
目录下名为 redis.conf
的文件中,Logstash 存储配置文件的位置。 当作为服务启动时,它将自动在后台运行它们。
使用您喜欢的编辑器(例如 nano)创建 redis.conf
:
sudo nano /etc/logstash/conf.d/redis.conf
添加以下行:
/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
,它是一组将在收集的数据上运行的过滤器,以及一个将过滤后的数据发送到 Elasticsearch 的输出。 输入由 exec
命令组成,该命令将在设置时间 interval
(以秒表示)后定期在服务器上运行 command
。 它还指定了一个 type
参数,用于定义在 Elasticsearch 中被索引时的文档类型。 exec
块传递一个包含两个字段的对象,command
和 message
字符串。 command
字段将包含已运行的命令,而 message
将包含其输出。
有两个过滤器将对从输入收集的数据按顺序运行。 kv
过滤器代表键值过滤器,内置于 Logstash。 它用于解析 keyvalue_separatorvalue
的一般形式的数据,并提供用于指定被视为值和字段分隔符的参数。 字段分隔符与将一般格式格式化的数据彼此分开的字符串有关。 在 Redis INFO 命令输出的情况下,字段分隔符 (field_split
) 是换行符,值分隔符 (value_split
) 是 :
。 不遵循定义形式的行将被丢弃,包括注释。
要配置 kv
过滤器,请将 :
传递给 value_split
参数,并将 \r\n
(表示新行)传递给 field_split
范围。 您还命令它从当前数据对象中删除 command
和 message
字段,方法是将它们作为数组元素传递给 remove_field
,因为它们包含现在无用的数据.
kv
过滤器将其按设计解析为字符串(文本)类型的值表示。 这引发了一个问题,因为 Kibana 无法轻松处理字符串类型,即使它实际上是一个数字。 为了解决这个问题,您将尽可能使用自定义 Ruby 代码将纯数字字符串转换为数字。 第二个过滤器是一个 ruby
块,它提供一个 code
参数,接受包含要运行的代码的字符串。
event
是 Logstash 为您的代码提供的变量,包含过滤器管道中的当前数据。 如前所述,过滤器一个接一个地运行,这意味着 Ruby 过滤器将接收来自 kv
过滤器的解析数据。 Ruby 代码本身将 event
转换为 Hash 并遍历键,然后检查与键关联的值是否可以表示为整数或浮点数(带小数的数字)。 如果可以,则将字符串值替换为解析后的数字。 当循环结束时,它会打印出一条消息 (Ruby filter finished
) 来报告进度。
输出将处理后的数据发送到 Elasticsearch 进行索引。 结果文档将存储在 redis_info
索引中,在输入中定义并作为参数传递给输出块。
保存并关闭文件。
您已经使用 apt
安装了 Logstash,并将其配置为定期从 Redis 请求统计信息、处理它们并将它们发送到您的 Elasticsearch 实例。
第 2 步 — 测试 Logstash 配置
现在,您将通过运行 Logstash 来测试配置,以验证它是否能够正确提取数据。
Logstash 支持通过将其文件路径传递给 -f
参数来运行特定配置。 运行以下命令以测试上一步的新配置:
sudo /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/redis.conf
显示输出可能需要一些时间,但您很快就会看到类似于以下内容的内容:
OutputUsing bundled JDK: /usr/share/logstash/jdk OpenJDK 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release. 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 [INFO ] 2021-12-30 15:42:08.887 [main] runner - Starting Logstash {"logstash.version"=>"7.16.2", "jruby.version"=>"jruby 9.2.20.1 (2.5.8) 2021-11-30 2a2962fbd1 OpenJDK 64-Bit Server VM 11.0.13+8 on 11.0.13+8 +indy +jit [linux-x86_64]"} [INFO ] 2021-12-30 15:42:08.932 [main] settings - Creating directory {:setting=>"path.queue", :path=>"/usr/share/logstash/data/queue"} [INFO ] 2021-12-30 15:42:08.939 [main] settings - Creating directory {:setting=>"path.dead_letter_queue", :path=>"/usr/share/logstash/data/dead_letter_queue"} [WARN ] 2021-12-30 15:42:09.406 [LogStash::Runner] multilocal - Ignoring the 'pipelines.yml' file because modules or command line options are specified [INFO ] 2021-12-30 15:42:09.449 [LogStash::Runner] agent - No persistent UUID file found. Generating new UUID {:uuid=>"acc4c891-936b-4271-95de-7d41f4a41166", :path=>"/usr/share/logstash/data/uuid"} [INFO ] 2021-12-30 15:42:10.985 [Api Webserver] agent - Successfully started Logstash API endpoint {:port=>9600, :ssl_enabled=>false} [INFO ] 2021-12-30 15:42:11.601 [Converge PipelineAction::Create<main>] Reflections - Reflections took 77 ms to scan 1 urls, producing 119 keys and 417 values [WARN ] 2021-12-30 15:42:12.215 [Converge PipelineAction::Create<main>] plain - Relying on default value of `pipeline.ecs_compatibility`, which may change in a future major release of Logstash. To avoid unexpected changes when upgrading Logstash, please explicitly declare your desired ECS Compatibility mode. [WARN ] 2021-12-30 15:42:12.366 [Converge PipelineAction::Create<main>] plain - Relying on default value of `pipeline.ecs_compatibility`, which may change in a future major release of Logstash. To avoid unexpected changes when upgrading Logstash, please explicitly declare your desired ECS Compatibility mode. [WARN ] 2021-12-30 15:42:12.431 [Converge PipelineAction::Create<main>] elasticsearch - Relying on default value of `pipeline.ecs_compatibility`, which may change in a future major release of Logstash. To avoid unexpected changes when upgrading Logstash, please explicitly declare your desired ECS Compatibility mode. [INFO ] 2021-12-30 15:42:12.494 [[main]-pipeline-manager] elasticsearch - New Elasticsearch output {:class=>"LogStash::Outputs::ElasticSearch", :hosts=>["http://localhost:9200"]} [INFO ] 2021-12-30 15:42:12.755 [[main]-pipeline-manager] elasticsearch - Elasticsearch pool URLs updated {:changes=>{:removed=>[], :added=>[http://localhost:9200/]}} [WARN ] 2021-12-30 15:42:12.955 [[main]-pipeline-manager] elasticsearch - Restored connection to ES instance {:url=>"http://localhost:9200/"} [INFO ] 2021-12-30 15:42:12.967 [[main]-pipeline-manager] elasticsearch - Elasticsearch version determined (7.16.2) {:es_version=>7} [WARN ] 2021-12-30 15:42:12.968 [[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=>7} [WARN ] 2021-12-30 15:42:13.065 [[main]-pipeline-manager] kv - Relying on default value of `pipeline.ecs_compatibility`, which may change in a future major release of Logstash. To avoid unexpected changes when upgrading Logstash, please explicitly declare your desired ECS Compatibility mode. [INFO ] 2021-12-30 15:42:13.090 [Ruby-0-Thread-10: :1] elasticsearch - Using a default mapping template {:es_version=>7, :ecs_compatibility=>:disabled} [INFO ] 2021-12-30 15:42:13.147 [Ruby-0-Thread-10: :1] elasticsearch - Installing Elasticsearch template {:name=>"logstash"} [INFO ] 2021-12-30 15:42:13.192 [[main]-pipeline-manager] javapipeline - Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>2, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>50, "pipeline.max_inflight"=>250, "pipeline.sources"=>["/etc/logstash/conf.d/redis.conf"], :thread=>"#<Thread:0x5104e975 run>"} [INFO ] 2021-12-30 15:42:13.973 [[main]-pipeline-manager] javapipeline - Pipeline Java execution initialization time {"seconds"=>0.78} [INFO ] 2021-12-30 15:42:13.983 [[main]-pipeline-manager] exec - Registering Exec Input {:type=>"redis_info", :command=>"redli --tls -h db-redis-fra1-68603-do-user-1446234-0.b.db.ondigitalocean.com -a hnpJxAgoH3Om3UwM -p 25061 info", :interval=>10, :schedule=>nil} [INFO ] 2021-12-30 15:42:13.994 [[main]-pipeline-manager] javapipeline - Pipeline started {"pipeline.id"=>"main"} [INFO ] 2021-12-30 15:42:14.034 [Agent thread] agent - Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]} Ruby filter finished Ruby filter finished Ruby filter finished ...
您将看到定期打印 Ruby filter finished
消息(在上一步中设置为 10 秒),这意味着统计信息正在发送到 Elasticsearch。
您可以通过单击键盘上的 CTRL + C
退出 Logstash。 如前所述,当作为服务启动时,Logstash 将在后台自动运行在 /etc/logstash/conf.d
下找到的所有配置文件。 运行以下命令来启动它:
sudo systemctl start logstash
您已运行 Logstash 以检查它是否可以连接到您的 Redis 集群并收集数据。 接下来,您将探索 Kibana 中的一些统计数据。
第 3 步 — 在 Kibana 中探索导入的数据
在本节中,您将探索和可视化描述您的数据库在 Kibana 中的性能的统计数据。
在您的 Web 浏览器中,导航到您在其中公开 Kibana 作为先决条件的一部分的域。 您将看到默认的欢迎页面:
在探索 Logstash 发送到 Elasticsearch 的数据之前,您首先需要将 redis_info
索引添加到 Kibana。 为此,首先从欢迎页面中选择我自己探索,然后打开左上角的汉堡菜单。 在 Analytics 下,单击 Discover。
Kibana 将提示您创建一个新的索引模式:
按创建索引模式。 您将看到一个用于创建新的 Index Pattern 的表单。 Kibana 中的索引模式提供了一种同时从多个 Elasticsearch 索引中提取数据的方法,并且可用于仅探索一个索引。
在右侧,Kibana 列出了您已配置 Logstash 使用的所有可用索引,例如 redis_info
。 在 Name 文本字段中键入它,然后从下拉列表中选择 @timestamp
作为 Timestamp 字段。 完成后,按下下方的 创建索引图案 按钮。
要创建和查看现有可视化,请打开汉堡菜单。 在 Analytics 下,选择 Dashboard。 加载后,按创建可视化开始创建一个新的:
左侧面板提供了 Kibana 可用于绘制可视化的值列表,这些值将显示在屏幕的中央部分。 屏幕右上角是日期范围选择器。 如果在可视化中使用了 @timestamp
字段,Kibana 将仅显示属于范围选择器中指定的时间间隔的数据。
从页面主要部分的下拉菜单中,选择 线和区域 部分下的 线。 然后,从左侧列表中找到 used_memory
字段并将其拖到中间部分。 您很快就会看到随时间变化的已用内存中位数的可视化线:
在右侧,您可以配置如何处理水平轴和垂直轴。 在那里,您可以通过按下显示的轴来设置垂直轴以显示平均值而不是中位数:
您可以选择不同的功能,或提供您自己的功能:
图表将立即使用更新的值刷新。
在这一步中,您已经使用 Kibana 可视化了托管 Redis 数据库的内存使用情况。 这将使您能够更好地了解您的数据库是如何使用的,这将帮助您优化客户端应用程序以及您的数据库本身。
结论
您现在已在服务器上安装了 Elastic 堆栈,并配置为定期从托管的 Redis 数据库中提取统计数据。 您可以使用 Kibana 或其他一些合适的软件来分析和可视化数据,这将帮助您收集有价值的见解以及有关数据库性能的实际相关性。
有关您可以使用 Redis 托管数据库执行哪些操作的更多信息,请访问 产品文档 。 如果您想使用其他可视化类型呈现数据库统计信息,请查看 Kibana 文档 以获取更多说明。