【最佳实践】Elastic stack 实时分析下你的Redis slowlog

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: Redis 是目前最流行的 NoSQL 内存数据库,然而如果在使用过程中出现滥用、乱用的情况,很容易发生性能问题,此时我们就要去关注慢查询日志,本文尝试给大家介绍一种通过 elastic stack 来快速分析 Redis 慢查询日志的方法,希望能给大家提供帮助。

作者介绍

魏彬,普翔科技 CTO,开源软件爱好者,中国第一位 Elastic 认证工程师,《Elastic日报》和 《ElasticTalk》社区项目发起人,被 elastic 中国公司授予 2019 年度合作伙伴架构师特别贡献奖。对 Elasticsearch、Kibana、Beats、Logstash、Grafana 等开源软件有丰富的实践经验,为零售、金融、保险、证券、科技等众多行业的客户提供过咨询和培训服务,帮助客户在实际业务中找准开源软件的定位,实现从 0 到 1 的落地、从 1 到 N 的拓展,产生实际的业务价值。

Redis slowlog简介

Redis 是目前最流行的缓存系统,因其丰富的数据结构和良好的性能表现,被各大公司广泛使用。尽管 redis 性能极佳,但若不注意使用方法,极容易出现慢查询,慢查询多了或者一个 20s 的慢查询会导致操作队列( redis 是单进程)堵塞,最终引起雪崩甚至整个服务不可用。对于慢查询语句,redis 提供了相关的配置和命令。

配置有两个:slowlog-log-slower-than 和 slowlog-max-len。slowlog-log-slower-than 是指当命令执行时间(不包括排队时间)超过该时间时会被记录下来,单位为微秒,比如通过下面的命令,就可以记录执行时长超过 20ms 的命令了。

config set slowlog-log-slower-than 20000

slowlog-max-len 是指 redis 可以记录的慢查询命令的总数,比如通过下面的命令,就可以记录最近 100 条慢查询命令了。

config set slowlog-max-len 100

操作慢查询的命令有两个:slowlog get [len] 和 slowlog reset。slowlog get [len]命令获取指定长度的慢查询列表。

redis 127.0.0.1:6379> slowlog get 2
1) 1) (integer) 14
   2) (integer) 1309448221
   3) (integer) 15
   4) 1) "ping"
2) 1) (integer) 13
   2) (integer) 1309448128
   3) (integer) 30
   4) 1) "slowlog"
      2) "get"
      3) "100"

上面返回了两个慢查询命令,其中每行的含义如下:

1、第一行是一个慢查询id。该 id 是自增的,只有在 redis server 重启时该id才会重置。
2、第二行是慢查询命令执行的时间戳
3、第三行是慢查询命令执行耗时,单位为微秒
4、第四行是慢查询命令的具体内容。

slowlog reset 命令是清空慢日志队列。

Elastic Stack

Elastic Stack 是 Elastic 公司 的一系列开源软件产品,包括 Elasticsearch、Kibana、Logstash、Beats 等,当然你也可以选择阿里云 Elasticsearch,不仅100%兼容开源,同时拥有完整云上Elastic Stack生态,并提供免费 X-Pack(价值6000美金);在本次分析过程中,我们会用到 elasticsearch、kibana 和 beats 三款产品。elasticsearch用来存储解析后的 redis slowlog,kibana 用于图形化分析,beats 用于收集 redis slowlog。

这里着重讲一下 beats,它是一系列轻量级的数据收集产品统称,目前官方提供了 filebeat、packetbeat、heartbeat、metricbeat 等,可以用来收集日志文件、网络包、心跳包、各类指标数据等。像我们这次要收集的redis slowlog,官方还没有提供相关工具,需要我们自己实现,但借助beats的一系列脚手架工具,我们可以方便快速的创建自己的 rsbeat---redis slowlog beat。

rsbeat原理简介

接下来我们先讲解一下 rsbeat 的实现原理,一图胜千言,我们先来看下它的工作流。

image.png


rsbeat工作流

我们由下往上分析:

1、最下面是我们要分析的 redis server 列表
2、再往上便是 rsbeat,它会与这些redis server建立连接并定期去拉取 slowlog。
3、在启动时,rsbeat 会发送下面的命令到每一台 redis server,来完成 slowlog 的配置,这里设置记录最近执行时长超过 20ms 的 500 条命令。

config set slowlog-log-slower-than 20000
config set slowlog-max-len 500
slowlog reset

4、然后 rsbeat 会定时去拉取每台 redis server 的慢查询命令

slowlog get 500
slowlog reset

注意之类 slowlog reset 是因为此次已经将所有的慢日志都取出了,下次获取时取最新生成的,防止重复计算。

5、rsbeat 将解析的慢日志发布到 elasticsearch 中进行存储
6、通过kibana 进行 slowlog 的图形化分析

rsbeat 的整个工作流到这里已经介绍完毕了,是不是很简单呢?下面我们来简单看一下 rsbeat 的核心代码实现。

sbeat核心代码讲解

rsbeat 已经在 github 上开源了,感兴趣的同学可以自己去下下来使用。下面我们分析的代码位于beater/rsbeat.go,这也是 rsbeat 的核心文件。

func poolInit(server string, slowerThan int) *redis.Pool {
    return &redis.Pool{
        MaxIdle:     3,
        MaxActive:   3,
        IdleTimeout: 240 * time.Second,
        Dial: func() (redis.Conn, error) {
            c, err := redis.Dial("tcp", server, redis.DialConnectTimeout(3*time.Second), redis.DialReadTimeout(3*time.Second))
            if err != nil {
                logp.Err("redis: error occurs when connect %v", err.Error())
                return nil, err
            }
            c.Send("MULTI")
            c.Send("CONFIG", "SET", "slowlog-log-slower-than", slowerThan)
            c.Send("CONFIG", "SET", "slowlog-max-len", 500)
            c.Send("SLOWLOG", "RESET")
            r, err := c.Do("EXEC")
            if err != nil {
                logp.Err("redis: error occurs when send config set %v", err.Error())
                return nil, err
            }
            logp.Info("redis: config set %v", r)
            return c, err
        },
        TestOnBorrow: func(c redis.Conn, t time.Time) error {
            _, err := c.Do("PING")
            logp.Info("redis: PING")
            return err
        },
    }
}

poolInit 方法是 rsbeat 初始化时进行的操作,这里也就是发送 slowlog 配置的地方,代码很简单,就不展开解释了。

func (bt *Rsbeat) redisc(beatname string, init bool, c redis.Conn, ipPort string) {
    defer c.Close()
    logp.Info("conn:%v", c)
    c.Send("SLOWLOG", "GET")
    c.Send("SLOWLOG", "RESET")
    logp.Info("redis: slowlog get. slowlog reset")
    c.Flush()
    reply, err := redis.Values(c.Receive()) // reply from GET
    c.Receive()                             // reply from RESET
    logp.Info("reply len: %d", len(reply))
    for _, i := range reply {
        rp, _ := redis.Values(i, err)
        var itemLog itemLog
        var args []string
        redis.Scan(rp, &itemLog.slowId, &itemLog.timestamp, &itemLog.duration, &args)
        argsLen := len(args)
        if argsLen >= 1 {
            itemLog.cmd = args[0]
        }
        if argsLen >= 2 {
            itemLog.key = args[1]
        }
        if argsLen >= 3 {
            itemLog.args = args[2:]
        }
        logp.Info("timestamp is: %d", itemLog.timestamp)
        t := time.Unix(itemLog.timestamp, 0).UTC()
        event := common.MapStr{
            "type":           beatname,
            "@timestamp":     common.Time(time.Now()),
            "@log_timestamp": common.Time(t),
            "slow_id":        itemLog.slowId,
            "cmd":            itemLog.cmd,
            "key":            itemLog.key,
            "args":           itemLog.args,
            "duration":       itemLog.duration,
            "ip_port":        ipPort,
        }
        bt.client.PublishEvent(event)
    }
}

redisc 方法实现了定时从 redis server 拉取最新的 slowlog 列表,并将它们转化为 elasticsearch 中可以存储的数据后,发布到 elasticsearch 中。这里重点说下每一个字段的含义:

1、@timestamp 是指当前时间戳。
2、@log_timestamp 是指慢日志命令执行的时间戳。
3、slow_id 是该慢日志的id。
4、cmd 是指执行的 redis 命令,比如sadd、scard等等。
5、key 是指 redis key 的名称
6、args 是指 redis 命令的其他参数,通过 cmd、key、args我们可以完整还原执行的 redis 命令。
7、duration 是指 redis 命令执行的具体时长,单位是微秒。
8、ip_port 是指发生命令的 redis server 地址。

有了这些字段,我们就可以用 kibana 来愉快的进行可视化数据分析了。

Kibana 图形化分析 slowlog

Kibana 提供了非常方便的数据分析操作,这里不展开解释了,感兴趣的可以自行去学习,这里直接上图,看下最终的分析结果。

image.png


列表详情页

image.png


时间段自由指定

image.png


查看慢日志按照时间的分布情况

上图可以看到最近有一个很明显的数量减少,原因是我们解决了相关的慢查询。

image.png


按慢查询数目来查看cmd分布和key分布

image.png


按慢查询时长来查看cmd分布和key分布

image.png


表格呈现慢查询的具体命令

看完上面的截图,有没有心动,想亲自操刀试一下?Kibana 操作起来非常简单,尤其对于程序员来讲,使用起来得心应手。赶紧下载 rsbeat 下来自己试一下吧!

总结

随着 elastic stack 的发展,其使用门槛越来越低,我认为目前所有的有志于做数据分析的工程师都应该了解和掌握它的用法。有了它的帮助,你可以以极快的速度搭建起自己的一套免费强大的数据分析软件,它的优点包括但不限于下面提到的:

1、数据源任意且自定制。只要你能将数据读取出来并存储到 elasticsearch 中即可分析。
2、支持海量数据分析。得益于 elastic 多年的迅猛发展,其产品已经非常成熟,上TB的数据都可以轻松应对存储与分析。有了它,你就可以舍弃数据一多就卡顿的 excel 了。
3、强大的开源社区支持。elastic 产品的迅猛发展离不开开源社区的支持,你只要在社区中提出自己的问题或者需求,总会有人即时给你答复和建议。如果你有一定的开发能力,那么完全可以按照自己的想法来折腾。

别再看了,赶紧去自己动手实践下吧!

声明:本文由原文《用 elastic stack 来分析下你的 redis slowlog》作者“魏彬”授权转载,对未经许可擅自使用者,保留追究其法律责任的权利。


image.png

阿里云Elastic Stack】100%兼容开源ES,独有9大能力,提供免费X-pack服务(单节点价值$6000)

相关活动


更多折扣活动,请访问阿里云 Elasticsearch 官网

阿里云 Elasticsearch 商业通用版,1核2G ,SSD 20G首月免费
阿里云 Logstash 2核4G首月免费


image.png

image.png

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
存储 NoSQL Redis
Redis 新版本引入多线程的利弊分析
【10月更文挑战第16天】Redis 新版本引入多线程是一个具有挑战性和机遇的改变。虽然多线程带来了一些潜在的问题和挑战,但也为 Redis 提供了进一步提升性能和扩展能力的可能性。在实际应用中,我们需要根据具体的需求和场景,综合评估多线程的利弊,谨慎地选择和使用 Redis 的新版本。同时,Redis 开发者也需要不断努力,优化和完善多线程机制,以提供更加稳定、高效和可靠的 Redis 服务。
60 1
|
1月前
|
缓存 监控 NoSQL
Redis 缓存穿透的检测方法与分析
【10月更文挑战第23天】通过以上对 Redis 缓存穿透检测方法的深入探讨,我们对如何及时发现和处理这一问题有了更全面的认识。在实际应用中,我们需要综合运用多种检测手段,并结合业务场景和实际情况进行分析,以确保能够准确、及时地检测到缓存穿透现象,并采取有效的措施加以解决。同时,要不断优化和改进检测方法,提高检测的准确性和效率,为系统的稳定运行提供有力保障。
55 5
|
3月前
|
Oracle NoSQL 关系型数据库
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
620 2
|
3月前
|
存储 Prometheus NoSQL
Redis 内存突增时,如何定量分析其内存使用情况
【9月更文挑战第21天】当Redis内存突增时,可采用多种方法分析内存使用情况:1)使用`INFO memory`命令查看详细内存信息;2)借助`redis-cli --bigkeys`和RMA工具定位大键;3)利用Prometheus和Grafana监控内存变化;4)优化数据类型和存储结构;5)检查并调整内存碎片率。通过这些方法,可有效定位并解决内存问题,保障Redis稳定运行。
167 3
|
4月前
|
缓存 NoSQL 网络协议
【Azure Redis 缓存】Azure Redis Cluster 在增加分片数时失败分析
【Azure Redis 缓存】Azure Redis Cluster 在增加分片数时失败分析
|
4月前
|
存储 缓存 NoSQL
【Azure Redis 缓存】当使用Azure Redis 集群服务时候,发生了Moved的几点分析
【Azure Redis 缓存】当使用Azure Redis 集群服务时候,发生了Moved的几点分析
|
4月前
|
网络协议 NoSQL 网络安全
【Azure 应用服务】由Web App“无法连接数据库”而逐步分析到解析内网地址的办法(SQL和Redis开启private endpoint,只能通过内网访问,无法从公网访问的情况下)
【Azure 应用服务】由Web App“无法连接数据库”而逐步分析到解析内网地址的办法(SQL和Redis开启private endpoint,只能通过内网访问,无法从公网访问的情况下)
|
2天前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
115 85
|
2月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
79 6