【最佳实践】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
相关文章
|
3月前
|
存储 NoSQL Redis
Redis系列学习文章分享---第九篇(Redis快速入门之好友关注--关注和取关 -共同关注 -Feed流实现方案分析 -推送到粉丝收件箱 -滚动分页查询)
Redis系列学习文章分享---第九篇(Redis快速入门之好友关注--关注和取关 -共同关注 -Feed流实现方案分析 -推送到粉丝收件箱 -滚动分页查询)
36 0
|
25天前
|
缓存 NoSQL 网络协议
【Azure Redis 缓存】Azure Redis Cluster 在增加分片数时失败分析
【Azure Redis 缓存】Azure Redis Cluster 在增加分片数时失败分析
|
25天前
|
存储 缓存 NoSQL
【Azure Redis 缓存】当使用Azure Redis 集群服务时候,发生了Moved的几点分析
【Azure Redis 缓存】当使用Azure Redis 集群服务时候,发生了Moved的几点分析
|
26天前
|
网络协议 NoSQL 网络安全
【Azure 应用服务】由Web App“无法连接数据库”而逐步分析到解析内网地址的办法(SQL和Redis开启private endpoint,只能通过内网访问,无法从公网访问的情况下)
【Azure 应用服务】由Web App“无法连接数据库”而逐步分析到解析内网地址的办法(SQL和Redis开启private endpoint,只能通过内网访问,无法从公网访问的情况下)
|
26天前
|
缓存 NoSQL Redis
【Azure Redis 缓存】Azure Reids是否可以开启慢日志(slowlog)和执行config指令
【Azure Redis 缓存】Azure Reids是否可以开启慢日志(slowlog)和执行config指令
|
3月前
|
存储 NoSQL 安全
Redis系列学习文章分享---第十五篇(Redis最佳实践--设计优雅的key+合适的数据结构+持久化如何配置+慢查询问题解决)
Redis系列学习文章分享---第十五篇(Redis最佳实践--设计优雅的key+合适的数据结构+持久化如何配置+慢查询问题解决)
61 1
|
2月前
|
缓存 NoSQL Java
Spring Boot整合Redis缓存的最佳实践
Spring Boot整合Redis缓存的最佳实践
|
3月前
|
存储 NoSQL Redis
大事件后端项目33_登录优化-redis_思路分析
大事件后端项目33_登录优化-redis_思路分析
|
5天前
|
canal 缓存 NoSQL
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
根据对一致性的要求程度,提出多种解决方案:同步删除、同步删除+可靠消息、延时双删、异步监听+可靠消息、多重保障方案
Redis缓存与数据库如何保证一致性?同步删除+延时双删+异步监听+多重保障方案
|
21天前
|
缓存 NoSQL Java
Redis深度解析:解锁高性能缓存的终极武器,让你的应用飞起来
【8月更文挑战第29天】本文从基本概念入手,通过实战示例、原理解析和高级使用技巧,全面讲解Redis这一高性能键值对数据库。Redis基于内存存储,支持多种数据结构,如字符串、列表和哈希表等,常用于数据库、缓存及消息队列。文中详细介绍了如何在Spring Boot项目中集成Redis,并展示了其工作原理、缓存实现方法及高级特性,如事务、发布/订阅、Lua脚本和集群等,帮助读者从入门到精通Redis,大幅提升应用性能与可扩展性。
45 0