当前位置: 首页 > news >正文

redis模糊查询key前缀_Redis内存数据监控实战

众所周知Redis是基于内存的数据库,其所有的数据都在内存中,而内存又是属于成本较高且容量有上限的硬件资源,因此需要时刻关注Redis内存的情况。特别是在生产环境,Redis内存占用过高会带来很多风险,甚至是灾难性的后果:

  • 庞大的数据导致持久化时间冗长,期间大量消耗主机资源,服务器压力陡升

  • Redis启动过程变慢,主从全量同步耗时增加,需要较长时间才能达到可用状态

  • 一旦达到Redis内存上限,轻则无法写入数据,重则直接宕机,且宕机后无法立即恢复,除非丢弃所有数据。

  为了避免这种情况的发生,需要增加Redis内存数据分布的监控,如果发现内存异常持续升高,可以通过监控来排查是谁占用了内存并及时处理。特来电云平台为此做了两种监控方案:

  1.  内存数据分布准实时监控

  2. 数据写入流量实时监控

一、内存数据分布准实时监控

Redis为了避免进程退出导致内存数据的永久丢失,可以定期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现数据恢复。Redis持久化分为RDB持久化和AOF持久化:

  • RDB(Redis DataBase)持久化:将当前内存中的Redis完整数据保存到硬盘

  • AOF(AppendOnly File)持久化:将写操作命令追加的保存到硬盘

数据分析可以选择使用RDB持久化生成的数据镜像文件。由于特来电云平台采用多数据中心多服务单元的部署架构,每个数据中心的服务单元都有一个或多个Redis集群,因此需要将各个集群的Redis数据镜像文件进行归集,然后进行统一分析,并将分析结果上报至特来电监控预警平台。这种做法还有一个好处是可以把归集的镜像文件当作数据备份,以备不时之需。

 d3fa4e2d8db63a05901e2ae1a36ea79d.png

分析工具选择使用redis-rdb-tools + sqlite + 自研工具。redis-rdb-tools是一款开源的以python语言开发的解析redis的rdb文件的工具,它可以生成内存报告、转储文件到JSON以及对两个rdb文件进行比较。这里主要用它生成csv格式的内存报告,执行命令:

/redis-rdb-tools-rdbtools-0.1.14/build/lib/rdbtools/cli/rdb.py-c memory /redis/rdb/dump-main1.rdb > /redis/rdb/report-main1.csv

生成的报告内容如下:

fd0b27f96728bfdcad8c85cf48cd01ef.png

其中:

Database :key所在的数据库编号 Type :key的数据结构 key :key的名称 size_in_bytes :value的大小 encoding :底层存储的编码类型 num_elements :包含的元素数量,例如string里有多少字符、hash里面有多少项、set里面有多少元素 len_largest_element :包含的所有元素中的最大长度 expiry :key的过期时间

接下来可以对这份报告进行统计,由于csv文件不方便进行各类统计查询,可以将其导入数据库。这里选择最轻量级的sqlite:

sqlite3/redis/sqlite/main1-memory.dbcreatetable memory(database int,type varchar(128),key varchar(128),size_in_bytesint,encoding varchar(128),num_elements int,len_largest_elementvarchar(128),expiry varchar(128));.modecsv memory.import/redis/rdb/report-main1.csv memory

      之后就可以进行下一步操作:统计数据并上报监控预警平台。在开发设计阶段对redis的key命名时,都会增加一个业务缩写前缀,例如:User:xxxxxx、Bill:xxxx,这样可以方便进行统计查询,能够快速得知每一块业务的key的数量和大小。因为所有的操作均在linux上,所以需要开发一个.netcore的统计上报工具部署在服务器上,进行统计和上报每一块业务的数据量。工具核心统计代码如下:

7821e8c592826ba2cc7e5d1808781650.png

在服务器上执行一下该工具,便能够完成一次统计和上报了。可以把整个过程做成一个脚本,用定时任务每隔1小时跑一次,就基本实现了准实时的内存数据分布的监控,效果图如下:

f3b756475f3049b59201b2cb6b7dcbf2.png

195b38523a87aa1414edb6f730d7cd59.png

由图可见,一旦出现某块业务的数据持续上涨的情况,可以很快发现并及时处理。

二、数据写入流量实时监控

内存数据分布准实时监控可以做到小时级的数据监控,可以分析监控较慢增长的数据,但无法及时监控导短时间内数据量突增的情况。针对这种情况,采用服务端实时网络抓包、分析报文、统计上报的方案来实现数据写入流量实时监控。

网络抓包工具有很多,这里采用最常用wireshark。wireshark不仅可以快速抓包,还拥有强大的过滤器引擎,可以使用过滤器筛选出redis的数据包,排除无关信息的干扰。在redis服务器上执行以下命令:

/usr/sbin/tshark-i eth0 -n -f 'tcp port 6379' -a duration:10 -t ad -lT fields -Eseparator="," -E quote=n -e ip.src -e tcp.srcport -e ip.dst -etcp.dstport -e data.data -e data.len > /rdis-networkflow-reporter/data.txt

此命令是抓取Redis服务的6379端口的报文,持续10秒,将报文中过滤出来源ip、来源端口、目标ip、目标端口、数据内容、报文长度等字段,并输出至一个文本文件。为什么只抓取10s?因为wireshark在抓取包并导出文本文件的过程会显著提高cpu,特别是在流量很高的情况,会对服务器性能产生影响。因此,可以根据服务器的实际情况进行持续时间的调整。需要注意的是,数据内容被转换成了十六进制,后面做统计的时候需要转换成字符串。

接下来对报文数据内容的解析,解析之前先要简单了解一下Redis的通信协议。Redis客户端使用RESP(Redis的序列化协议)协议与Redis的服务器端进行通信,在RESP协议中,数据类型取决于第一个字节:

  • 对于简单字符串,第一个字节是“+”

  • 对于错误,第一个字节是“ - ”

  • 对于整数,第一个字节是“:”

  • 对于批量字符串,第一个字节是“$”

  • 对于数组,第一个字节是“*”

  • 协议的不同部分始终以“ ”(CRLF)结尾

因为主要提取报文中的写入命令,而写入命令通常都是至少包含三部分:命令、key、value。对于协议来讲,这属于一个数组,因此会以*开头,后面跟着一个十进制的数字,该数字是数组中元素的个数。例如:字符串写入指令set hey helloworld,报文的前缀则是*3。接下来的命令本身作为一个字符串,报文则以“$”字节开始,后面是组成字符串的字节数(前缀长度),然后是命令本身。所以set对应的报文就是$3 set。同理hey helloworld也是字符串,因此,整个命令的报文便是*3 $3 set $3 hey $10 helloworld 。

下一步需要整理出哪些命令是要关注的,因为并不是所有的写入操作都值得去统计,比如DEL、INCR等操作就不会增加内存。这里在统计工具中进行了判断:

4efa7ab92fa0310cd681b0a600435556.png

最后,在统计工具中对整个文本文件进行逐行解析,统计写入操作的来源ip、来源端口、key的前缀以及写入数据的大小,并上报至监控预警平台。把整个过程做成脚本,配上定时任务,即可实现数据写入流量实时监控,效果图如下:

81dbc93042cc5218b7965dd74c4e8ee8.png

一旦出现写入流量突增,既可以立即定位到key的前缀,方便清理数据,还可以根据来源ip和端口定位到具体的应用进程,从根源上阻止异常流量。

三、总结

实时监控Redis流量的方式有很多,特来电在大规模使用的过程中也尝试了很多,例如引入第三方厂商的专业监控工具、引入专业的网卡层面的流量监控工具等。但无论从部署复杂度、维护成本以及投入资源成本来看,目前使用的这两套方案是最符合当下的实际情况并较好的解决了痛点问题的。后续随着云平台的不断发展,也将根据实际需求继续探索新的监控方案。逐步实现Redis内存监控的实时监控和自动化运维处理,让Redis的运维更智能、更简单。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • completablefuture 线程池_线程池ForkJoinPool简介
  • 判断多个数据是否是两个素数相乘_循环结构程序举例2素数的判断
  • chrome 验证码识别 扩展_chrome插件市场国内无法打开,我来教你如何安装插件
  • python深度神经网络_PyTorch进阶:深度神经网络中的前馈过程(图解分析)
  • python判断能否组成三角形_如何用PYTHON判断三角形的类型 需要技巧
  • 查看python安装成功的命令_Python sqlite3模块 安装查询命令等使用讲解
  • python输入半径计算公式_python练习:取输入半径的周长和面积
  • python重命名文件或目录_命令和Python重命名文件
  • python 列表_Python 算法 09 -- 散列表
  • python粘性拓展_拓展Python Markdown
  • ping不通服务器_服务器远程桌面不上不要急,这就告诉你原因
  • 钢笔墨水能否代替打印机墨水_喷墨打印机该用染料墨水还是颜料墨水,区别在哪里?...
  • 零基础学python靠谱吗_零基础学python的我(开篇扯淡)
  • linux安装ssh_如何为Ubuntu服务器建立无密码SSH认证
  • responseentity 返回异常_Spring Boot异常处理
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • Docker 1.12实践:Docker Service、Stack与分布式应用捆绑包
  • spring-boot List转Page
  • 百度小程序遇到的问题
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 软件开发学习的5大技巧,你知道吗?
  • 小程序 setData 学问多
  • 一道闭包题引发的思考
  • 用mpvue开发微信小程序
  • 容器镜像
  • ‌前端列表展示1000条大量数据时,后端通常需要进行一定的处理。‌
  • # 20155222 2016-2017-2 《Java程序设计》第5周学习总结
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • #我与Java虚拟机的故事#连载12:一本书带我深入Java领域
  • $.ajax()方法详解
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (2024)docker-compose实战 (8)部署LAMP项目(最终版)
  • (3)(3.2) MAVLink2数据包签名(安全)
  • (55)MOS管专题--->(10)MOS管的封装
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (附源码)计算机毕业设计ssm电影分享网站
  • (回溯) LeetCode 40. 组合总和II
  • (三)docker:Dockerfile构建容器运行jar包
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (一) storm的集群安装与配置
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET Core 网络数据采集 -- 使用AngleSharp做html解析
  • .NET Standard 的管理策略
  • .NET 动态调用WebService + WSE + UsernameToken
  • .net中应用SQL缓存(实例使用)
  • /etc/fstab和/etc/mtab的区别
  • @RequestMapping-占位符映射
  • [ Linux Audio 篇 ] 音频开发入门基础知识
  • [240527] 谷歌 CEO 承认 AI 编造虚假信息问题难解(此文使用 @gemini 命令二次创作)| ICQ 停止运作
  • [240812] X-CMD 发布 v0.4.5:更新 gtb、cd、chat、hashdir 模块功能
  • [Android] 240204批量生成联系人,短信,通话记录的APK