我为什么用 ES 做 Redis 监控,不用 Prometheus 或 Zabbix?

阅读数:3 2020 年 5 月 14 日 10:00

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

本文由 dbaplus 社群授权转载。

序言

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:Redis 热度排名

Redis 当下很流行,也很好用,无论是在业务应用系统,还是在大数据领域都有重要的地位;但 Redis 也很脆弱,用不好,问题多多。2012 年以前都是以 memcached 为主,之后转到 Redis 阵营,经历过单实例模式、主从模式、哨兵模式、代理模式,集群模式,真正公司层面用得好的很少,对于 Redis 掌控都很片面,导致实际项目中问题不少。

Redis 要想用得好,需要整体掌握 3 个层面:

  • 开发层面
  • 架构层面
  • 运维层面

其中架构与运维至关重要,多数中小型企业仅在开发层面满足常用功能,数据规模稍微大些,业务复杂度高些,就容易出现各种架构与运维问题。本文主旨是探讨 Redis 监控体系,目前业界当然也有很多成熟的产品,但个人觉得都很常规,只做到一些粗粒度的监控, 没有依据业务需求特点因地制宜去细化,从而反向的提供架构开发优化方案。

本文内容将围绕如下几个问题展开讨论:

  • Redis 监控体系有哪些方面?
  • 构建 Redis 监控体系我们做了哪些工作?
  • Redis 监控体系应该细化到什么程度?
  • 为什么使用 ELK 构建监控体系?

需求背景

项目描述

公司业务范围属于车联网行业,有上百万级的真实车主用户,业务项目围绕车主生活服务展开,为了提高系统性能,引入了 Redis 作为缓存中间件,具体描述如下:

  • 部署架构采用 Redis-Cluster 模式;
  • 后台应用系统有几十个,应用实例数超过二百个;
  • 所有应用系统共用一套缓存集群;
  • 集群节点数几十个,加上容灾备用环境,节点数量翻倍;
  • 集群节点内存配置较高。

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:Redis 集群架构与应用架构示意图

问题描述

系统刚开始关于 Redis 的一切都很正常,随着应用系统接入越来越多,应用系统子模块接入也越来越多,开始出现一些问题,应用系统有感知,集群服务端也有感知,如下描述:

  • 集群节点崩溃;
  • 集群节点假死;
  • 某些后端应用访问集群响应特别慢。

其实问题的根源都是架构运维层面的欠缺,对于 Redis 集群服务端的运行监控其实很好做,本身也提供了很多直接的命令方式,但只能看到服务端的一些常用指标信息,无法深入分析,治标不治本,对于 Redis 的内部运行一无所知,特别是对于业务应用如何使用 Redis 集群一无所知:

  • Redis 集群使用的热度问题?
  • 哪些应用占用的 Redis 内存资源多?
  • 哪些应用占用 Redis 访问数最高?
  • 哪些应用使用 Redis 类型不合理?
  • 应用系统模块使用 Redis 资源分布怎么样?
  • 应用使用 Redis 集群的热点问题?

监控体系

监控的目的不仅仅是监控 Redis 本身,而是为了更好的使用 Redis。传统的监控一般比较单一化,没有系统化,但对于 Redis 来说,个人认为至少包括:一是服务端,二是应用端,三是服务端与应用端联合分析。

服务端

  • 服务端首先是操作系统层面,常用的 CPU、内存、网络 IO,磁盘 IO,服务端运行的进程信息等;
  • Redis 运行进程信息,包括服务端运行信息、客户端连接数、内存消耗、持久化信息 、键值数量、主从同步、命令统计、集群信息等;
  • Redis 运行日志,日志中会记录一些重要的操作进程,如运行持久化时,可以有效帮助分析崩溃假死的程序。

应用端

应用端、获取应用端使用 Redis 的一些行为,具体哪些应用哪些模块最占用 Redis 资源、哪些应用哪些模块最消耗 Redis 资源、哪些应用哪些模块用法有误等。

联合分析

联合分析结合服务端的运行与应用端使用的行为,如:一些造成服务端突然阻塞的原因,可能是应用端设置了一个很大的缓存键值,或者使用的键值列表,数据量超大造成阻塞。

解决方案

为什么会选择 Elastic-Stack 技术栈呢?

多数的第三方只监控一些指标,对于明细日志还是采用 ELK(Elasticsearch、Logstash、Kibana),也就是说用第三方监控指标之后,还得再搭建一个 ELK 集群看明细日志。

再就是说 Elastic-Stack 技术栈整合的优势,指标也可以、日志文件也可以,从采集开始到存储、到最终报表面板都整合得非常好,门槛很低。

下面详细聊聊我们具体怎么做的,做了哪些工作?

服务端系统

Elastic-Stack 家族有 Metricbeat 产品,支持系统层面的信息收集,简单的配置下 Elastic 集群地址和系统指标模块即可上线,并且会在 Kibana 中创建已有的系统监控面板,非常简单快速,一般运维就可以搞定。

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:metrcibeat 示意图

系统指标信息收集配置样例如下:

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

服务端集群

收集 Redis 集群运行信息,业界通常做法都是采用 Redis 提供的 info 命令,定期收集。

info 获取的信息包括如下:

  • server:Redis 服务器的一般信息
  • clients:客户端的连接部分
  • memory:内存消耗相关信息
  • persistence:RDB 和 AOF 相关信息
  • stats:一般统计
  • replication:主 / 从复制信息
  • cpu:统计 CPU 的消耗 command
  • stats:Redis 命令
  • 统计 cluster:Redis 集群信息
  • keyspace:数据库的相关统计

Elastic-Stack 家族的 Metricbeat 产品也支持 Redis 模块,也是采用 info 命令获取的,但是有一些实现的局限性,如下描述:

  • Redis 集群的主从关系信息,Metricbeats 表达不出来;
  • Redis 集群的一些统计信息,永远是累计增加的,如命令数,如果要获取命令数的波峰值,则无法得到;
  • Redis 集群状态信息变化,Metricbeats 是无法动态的,如集群新增节点、下线节点等。

所以这里参考了 CacheCloud 产品(搜狐团队开源),我们自定义设计开发了 Agent,定时从 Redis 集群采集信息,并在内部做一些统计数值的简单计算,转换成 Json,写入到本地文件,通过 Logstash 采集发送到 Elasticsearch。

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:Redis 服务端运行信息采集架构示意图

服务端日志

Redis 服务端运行日志采集很简单,直接通过 Elastic-Stack 家族的 Filebeat 产品,其中有 Redis 模块,配置一下 Elastic 服务端,日志文件地址即可。

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:服务端日志采集过程

Redis 运行日志采集配置:

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

应用端

应用端信息采集是整个 Redis 监控体系最重要的部分,也是实现最麻烦、链路最长的。首先是修改 jedis(技术栈 Java)源码,增加埋点代码,重新编译并引用到应用项目中,应用端对于 Redis 集群的任何命令操作,都会被捕捉,并记录下关键信息,之后写入到本地文件。

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:Redis 应用端行为采集架构图

应用端采集的数据格式如下:

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:应用端采集的数据案例

jedis 修改

jedis 改造记录的信息如下:

  • r_host:访问 Redis 集群的服务器地址与端口,其中某一台 ip:port;
  • r_cmd:执行命令类型、如 get、set、hget、hset 等各种;
  • r_start:执行命令开始时间;
  • r_cost:时间消耗;
  • r_size:获取键值大小或者设置键值大小;
  • r_key:获取键值名称;
  • r_keys:键值的二级拆分,数组的长度不限制。这里有必要强调一下,所有应用系统共用的是一套集群,所以应用系统的键值都是有规范的,按照特殊符号分割,如:" 应用名称 _ 系统模块 _ 动态变量 _xxx“,主要便于我们区分。

在 jedis 改造有几处地方,如下:

  • 类 Connection.java 文件,统计开始,记录命令执行开始时间;统计结束,记录命令结束时间、时间消耗等,并写入到日志流中;
  • 类 JedisClusterCommand 文件,获取键的地方 key,方便之后分析应用键的行为。

在类 Connection.java 文件中有 2 处:

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:类 Connection.java 文件埋点代码的地方

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:类 Connection.java 文件埋点代码的地方

类 JedisClusterCommand 文件埋点代码.java 文件中有 1 处:

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:类 JedisClusterCommand 文件埋点代码

logback 修改

应用端都会使用 logback 写入日志文件,同时为了更加精准,应用端写入日志时还需要获取应用端的一些信息,如下:

  • app_ip:应用端部署在服务器上的 IP 地址;
  • app_host:应用端部署在服务器上的服务器名称。

自定义一个 Layout,自动获取应用端的 IP 地址与服务器名称:

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:自定义 Logback 的 Layout

app 配置

app 配置属于最后收尾工作,主要是输出埋点的日志数据,配置日志 logback.xml 文件即可:

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:配置应用端日志文件 logback.xml

日志采集

应用端日志采集采用 Logstash,配置日志目录,指向 Elastic 集群,这样整体的监控日志采集部分就结束了。

日志分析

Redis 服务端的日志分析比较简单,常规的一些指标而已,创建好关键的图表,容易看出问题。重点讨论应用端的日志分析。

我为什么用ES做Redis监控,不用Prometheus或Zabbix?

图示:应用端使用 Redis 一些行为图表

ELK 监控体系上线之后,我们连续观察分析两周,获得了一些监控成果,如:

  • 应用端部分键值太大,居然超过 1MB,这种键值访问一次消耗时间很大,会严重造成阻塞;
  • 部分应用居然使用 Redis 当成数据库使用;
  • 有将 List 类型当成消息队列使用,一次存取几十万的数据;
  • 某些应用对于集群的操作频次特别高,几乎占用了一半以上;
  • 还有很多,就不一一描述了。

后续方案

监控体系相当于架构师的眼睛,有了这个,Redis 方面的优化改造方案就很好制定了:

  • 应用端、误用的使用全部要改掉;
  • 服务端,按照应用的数据,进行一些拆分,拆分出一些专用的集群,特定为一些应用使用或者场景;
  • 开发者,后续有新业务模块需要接入 Redis 需要告知架构师们评审。

结语

监控体系项目前后经历过几个月,服务端部分短期内就完成的,应用端是随着应用发布逐步完成的。上线完成之后又经历几周的跟踪分析,才确定下来整体的优化方案。

监控体系本身并不是为了监控,而是发现问题、预见问题,最终提前解决问题,监控做得好,下班下得早。

Redis 集群是个好东西,完全掌握还是需要很长的时间,特别是架构、运维层面,如果没有,请做好监控。

Q&A

Q1:请问单台机器一般部署几个 Redis 实例呢?

A: 依据服务器资源设置:

1、CPU 核数,Redis 是单线程工作模型,实际运行并非进程只有一个线程,这个要搞清楚;

2、内存,一个 Redis 进程配置部分内存,需要至少对等的内存闲置,fork 子进程使用, 所以配置多实例要简单计算下;

3、网络,网络 IO 超过网卡限制,会出问题。

Q2:直播中讲到的大 key,hash 要改成什么?分片吗?

A: 1、比如,一个车子的基本信息,包括很多区块部分,用 hash 确实非常好理解,但是过期之后整个 hash 都删除了,其实很多信息是固定的,不用定时过期的;2、拆分成小的 string 更合适。

Q3:在客户端打印 key 和 value,如果是 bigkey 的话,qps 有个 1000,打印日志就占用很高的机器负载了吧?

A: 1、打印的 key,不包括 value 值内容,只有 key 以及 value 的大小;2、logback 这些框架其实支持的性能相当不错的,可以配置成异步的方式,如果还不够,可以直接输出到 Kafka 队列等。

Q4:请问 ES 怎么部署 MongoDB 慢查询报表平台呢?

A: 1、没有深度使用过 MongoDB;2、基于 Elastic-Stack 做慢查询报表平台思路与 Redis 一样的,不管什么指标 + 日志全部都采集到 ES 完事。

Q5:info all 执行频繁,会经常阻塞服务器,怎么平衡它的性能呢?

A: 1、因为采集的是服务端运行的快照信息,定时采集,可以设定时间间隔大一些,比如 5s;2、执行 info all,是在 java 客户端,可以修改 jedis,在其中捕获 info 命令,采集数据,观察分析一段时间。

Q6:请问应用端 jedis 要怎么埋点呢?

A: 1、原有 jedis 版本基于 2.9,在 2 个类中修改埋点,参考了 CacheCloud 产品。最新版本的程序最近没有关注,思路一样;2、详细见本文中贴出的代码。

Q7:监控的话,个人觉得放在 K8S 里面,不是最优方案,您对这个怎么看?

A: 1、本人未使用过 K8S 部署产品;2、Redis 监控体系,整体服务端,应用端,在 Docker 中也仅服务端可以,将 metrcibeats 这些集成在一起,但也有一些服务端监指标计算,需要自己编写 Agent 来完成,也是可以到 Docker 中去。应用端的就没有办法了,这个属于前端的行为统计。

Q8:请问您的 ES 有多少节点?要用 ssd 盘吗?

A: 1、标准集群,起步 3 个实例节点;2、固态硬盘应用看场景,业务系统用用可以,日志系统一般不需要,即使需要也可以做冷热隔离,少量的数据使用 ssd,历史的数据全部 hdd 足矣。

Q9:如果公司缺乏足够的人力物力,是用 ES、Prometheus 还是 Zabbix 做监控比较适合呢?能分别说一下它们各自最适用的情况吗?

A: 1、ES,Elastic-Stack,首选考虑,ES 擅长的领域很多,应用系统查询加速、大数据领域、监控领域;2、其它两个产品主要是做指标型的监控,但实际项目中,仅仅指标监控是不够的,需要一个整体型的监控体系,便于联合分析。ES 其实很多方面比时序数据库做得更好,腾讯有资深专家做过详细的 ES 与 TSDB 对比的测试,性能与功能都完全超过专门的时序数据库。

作者介绍

李猛,数据技术专家

  • Elastic-Stack 产品深度用户,ES 认证工程师,对 Elastic-Stack 开发、架构、运维有深入体验;
  • 实践过多种 ES 项目,最暴力的大数据分析应用,最复杂的业务系统应用。

原文链接

https://mp.weixin.qq.com/s?__biz=MzI4NTA1MDEwNg==&mid=2650788187&idx=1&sn=9363cc47966b4464e82f84904ac0b4b8&chksm=f3f964cec48eedd840c922263bfe39f31a8223d530cfac3a6bebd8b7bb0c0569712f087a65eb&scene=27#wechat_redirect

评论

发布
暂无评论