golang 编写的在线redis 内存分析工具 rma4go

redis 内存分析工具 rma4go

redis是一个很有名的内存型数据库,这里不做详细介绍。而rma4go (redis memory analyzer for golang) 是一个redis的内存分析工具,这个工具的主要作用是针对运行时期的redis进行内存的分析,统计redis中key的分布情况, 各种数据类型的使用情况,key的size,大key的数量及分布, key的过期状况分布等一些有助于定位redis使用问题的工具,希望这能够给应用开发者提供便利排查生产中所遇到的实际问题。

rma4go的应用场景

redis是目前很流行的一个内存型数据库,很多企业都在使用。 但由于业界并没有很多对于redis使用上的规范,或者是有一些规范并没有被很好的遵循, 存在很多redis使用上的问题,我这边就列举一些例子:

  1. redis 存用满了, 不知道key的分布情况,不知道来源于那个应用
  2. redis 被block了,不知道什么原因导致的block,是哪个应用里的什么key的操作导致的
  3. 想迁移redis数据,或者调整一些设置,但不知道要不要对redis里的数据进行保留,以及不知道什么业务在使用等
  4. redis的key的过期情况不明朗, 不知道哪些东西可以删除或者调整

其实上面的一些问题是我随便列举出来的一些,并不是所有的存在的问题,相信也有很多其他场景同样会用到这样的一个redis内存分析工具rma4go

rma4go的具体功能

数据维度

对于key的分析我们这个工具会提供如下几个维度的数据:

  • key的数量分布维度
  • key的过期分布维度
  • key的类型分布维度
  • key对应的的数据的大小分布维度
  • key的前缀分布维度
  • 慢key与大key的维度

当然以后如果发现有更好的纬度也会添加进去,目前先以这几个纬度为主

数据类型设计

type RedisStat struct {All     KeyStat `json:"all"`String  KeyStat `json:"string"`Hash    KeyStat `json:"hash"`Set     KeyStat `json:"set"`List    KeyStat `json:"list"`ZSet    KeyStat `json:"zset"`Other   KeyStat `json:"other"`BigKeys KeyStat `json:"bigKeys"`
}// distributions of keys of all prefixes
type Distribution struct {KeyPattern string `json:"pattern"`Metrics
}// basic metrics of a group of key
type Metrics struct {KeyCount       int64 `json:"keyCount"`KeySize        int64 `json:"keySize"`DataSize       int64 `json:"dataSize"`KeyNeverExpire int64 `json:"neverExpire"`ExpireInHour   int64 `json:"expireInHour"`  // >= 0h < 1hExpireInDay    int64 `json:"expireInDay"`   // >= 1h < 24hExpireInWeek   int64 `json:"expireInWeek"`  // >= 1d < 7dExpireOutWeek  int64 `json:"expireOutWeek"` // >= 7d
}

实现细节

key元信息

type KeyMeta struct {Key      stringKeySize  int64DataSize int64Ttl      int64Type     string
}

众所周知, redis里的所有的数据基本都是由key的, 也是根据key进行操作的,那么对redis里的key进行分析我们必须要记录下来这个key的信息才可以做到, 我们能记录的信息正如以上结构中的一样, key本身, key的大小, 数据的大小, 过期时间以及key的类型。这些信息是我们对key进行分析的一个基础信息,都可以通过一些简单的redis命令就可以取到。

遍历redis所有key

要对一个redis进行完整的key分析, 我们就需要有办法能够访问到所有key的源信息, 所幸redis提供了 scan这么一种方式可以比较轻量的遍历所有的key,访问到相应的key的元信息。
这样对于redis而言, 进行在线key分析的时候造成的压力也不会非常大,当然key分析不能再QPS高峰期进行, 需要在redis资源余量允许的情况下进行分析。

另外由于redis本身的一个内存清理机制,有25%的过期占用可以在分析key的时候被清理掉, 因此这个分析工具同时兼具了清理一部分内存的作用, 如果redis里面存在过期的而且存在于内存里面的key的话。

对记录的信息进行分析与汇总

有了遍历所有key的方法, 又有了元数据, 剩下的事情就是把这些数据进行聚合汇总, 这个主要是一个算法上的工作,
最难的部分要数这个key聚合的部分了, 这里面有很多取舍, 由于作者我本人不是专攻算法的, 而且没有找到合适的库, 因此只能动手自己想了一种方式。 基本的思路是:

压缩的算法
  1. 对于每个新的key的元信息, 添加到老的key分析对象里去
  2. 对这个key从后往前缩短, 去除尾部,看是否已经包含这个key的统计信息,如果包含, 则把key的信息累加上去, 如果不包含则创建一个新的纪录。
  3. 当记录的个数添加到一定数量的时候, 对对象的个数进行一次压缩

    • 压缩的算法也是从字符串的末尾往字符串首部进行压缩
    • 当压缩不能增加这个pattern 的key的个数的时候使用原来的key(压缩前的key)
    • 当压缩可以增加这个pattern的key的个数的时候,进行key的合并,把pattern设置成压缩后的pattern
    • 当记录的条数超过指定的条数就循环往复,直到压缩到小于指定的条数为止
    • 如果对于key的最小长度(就算再压缩也要保留一两位)有要求, 有一些压缩到字符串的最小长度的参数可以进行调整与设置, 进行一定的取舍。
  4. 直到scan完毕
代码如下
const (defaultSize = 128compactNum  = 30maxLeftNum =  150minKeyLenLower = 2minKeyLen   = 5
)func (stat *KeyStat) compact() {distMap := stat.DistributiontmpMap := make(map[string][]string, defaultSize)shrinkTo := compactNumfor k := range distMap {compactedKey := kif orgks, ok := tmpMap[compactedKey]; ok {orgks = append(orgks, k)tmpMap[compactedKey] = orgks} else {ks := make([]string, 0, defaultSize)ks = append(ks, k)tmpMap[compactedKey] = ks}}shrinkTo--for (len(tmpMap) > compactNum && shrinkTo >= minKeyLen) || (len(tmpMap) > maxLeftNum && shrinkTo >= minKeyLenLower) {tnMap := make(map[string][]string, defaultSize)for k := range tmpMap {// shrinkif len(k) > shrinkTo {compactedKey := k[0:shrinkTo]if oik, ok := tnMap[compactedKey]; ok {oik = append(oik, tmpMap[k]...)tnMap[compactedKey] = oik} else {ks := make([]string, 0, defaultSize)ks = append(ks, tmpMap[k]...)tnMap[compactedKey] = ks}} else {tnMap[k] = tmpMap[k]}}// 如果此次shrink 没有使得这个集合的元素数量增加, 就使用原来的keyfor k := range tmpMap {if len(k) > shrinkTo {ck := k[0:shrinkTo]if len(tnMap[ck]) == len(tmpMap[k]) && len(tnMap[ck]) > 1 {x := make([]string, 0, defaultSize)tnMap[k] = append(x, tnMap[ck]...)delete(tnMap, ck)}}}tmpMap = tnMapshrinkTo --}dists := make(map[string]Distribution, defaultSize)for k, v := range tmpMap {if len(v) > 1 {var nd Distributionfor _, dk := range v {d := distMap[dk]nd.KeyPattern = k + "*"nd.KeyCount += d.KeyCountnd.KeySize += d.KeySizend.DataSize += d.DataSizend.ExpireInHour += d.ExpireInHournd.ExpireInWeek += d.ExpireInWeeknd.ExpireInDay += d.ExpireInDaynd.ExpireOutWeek += d.ExpireOutWeeknd.KeyNeverExpire += d.KeyNeverExpire}dists[k] = nd} else {for _, dk := range v {nd := distMap[dk]nd.KeyPattern = dk + "*"dists[dk] = nd}}}stat.Distribution = dists
}

在线key分析的github项目

rma4go
这是一个我已经写好的项目, 它使用起来非常简单

构建方法

  1. 构建之前请确保golang sdk 已经安装, 并且版本 >=1.11.0
  2. 请确保已经具备翻墙的环境, 因为它要下载一些依赖,可能来自墙外

翻墙方法如下

// linux/osx
export http_proxy=somehost:port
export https_proxy=somehost:port
// windows
set http_proxy=somehost:port
set https_proxy=somehost:port
  1. 构建
git clone git@github.com:winjeg/rma4go.git
cd rma4go
go build .

使用方法

用法如下:rma4go -h

rma4go usage:
rma4go -r some_host -p 6379 -a password -d 0
======================================================-H stringaddress of a redis (default "localhost")-a stringpassword/auth of the redis-d intdb of the redis to analyze-h    help content-p intport of the redis (default 6379)-r stringaddress of a redis (default "localhost")

示例输出

all keys statistics| PATTERN | KEY NUM | KEY SIZE | DATA SIZE | EXPIRE IN HOUR | EXPIRE IN DAY | EXPIRE IN WEEK | EXPIRE OUT WEEK | NEVER EXPIRE |
|---------|---------|----------|-----------|----------------|---------------|----------------|-----------------|--------------|
| total   |       0 |        0 |         0 |              0 |             0 |              0 |               0 |            0 |
string keys statistics| PATTERN | KEY NUM | KEY SIZE | DATA SIZE | EXPIRE IN HOUR | EXPIRE IN DAY | EXPIRE IN WEEK | EXPIRE OUT WEEK | NEVER EXPIRE |
|---------|---------|----------|-----------|----------------|---------------|----------------|-----------------|--------------|
| total   |       0 |        0 |         0 |              0 |             0 |              0 |               0 |            0 |
list keys statistics| PATTERN | KEY NUM | KEY SIZE | DATA SIZE | EXPIRE IN HOUR | EXPIRE IN DAY | EXPIRE IN WEEK | EXPIRE OUT WEEK | NEVER EXPIRE |
|---------|---------|----------|-----------|----------------|---------------|----------------|-----------------|--------------|
| total   |       0 |        0 |         0 |              0 |             0 |              0 |               0 |            0 |
hash keys statistics| PATTERN | KEY NUM | KEY SIZE | DATA SIZE | EXPIRE IN HOUR | EXPIRE IN DAY | EXPIRE IN WEEK | EXPIRE OUT WEEK | NEVER EXPIRE |
|---------|---------|----------|-----------|----------------|---------------|----------------|-----------------|--------------|
| total   |       0 |        0 |         0 |              0 |             0 |              0 |               0 |            0 |
set keys statistics| PATTERN | KEY NUM | KEY SIZE | DATA SIZE | EXPIRE IN HOUR | EXPIRE IN DAY | EXPIRE IN WEEK | EXPIRE OUT WEEK | NEVER EXPIRE |
|---------|---------|----------|-----------|----------------|---------------|----------------|-----------------|--------------|
| total   |       0 |        0 |         0 |              0 |             0 |              0 |               0 |            0 |
zset keys statistics| PATTERN | KEY NUM | KEY SIZE | DATA SIZE | EXPIRE IN HOUR | EXPIRE IN DAY | EXPIRE IN WEEK | EXPIRE OUT WEEK | NEVER EXPIRE |
|---------|---------|----------|-----------|----------------|---------------|----------------|-----------------|--------------|
| total   |       0 |        0 |         0 |              0 |             0 |              0 |               0 |            0 |
other keys statistics| PATTERN | KEY NUM | KEY SIZE | DATA SIZE | EXPIRE IN HOUR | EXPIRE IN DAY | EXPIRE IN WEEK | EXPIRE OUT WEEK | NEVER EXPIRE |
|---------|---------|----------|-----------|----------------|---------------|----------------|-----------------|--------------|
| total   |       0 |        0 |         0 |              0 |             0 |              0 |               0 |            0 |
big keys statistics| PATTERN | KEY NUM | KEY SIZE | DATA SIZE | EXPIRE IN HOUR | EXPIRE IN DAY | EXPIRE IN WEEK | EXPIRE OUT WEEK | NEVER EXPIRE |
|---------|---------|----------|-----------|----------------|---------------|----------------|-----------------|--------------|
| total   |       0 |        0 |         0 |              0 |             0 |              0 |               0 |            0 |

rendered by markdown
total count 4004

all keys statistics

PATTERNKEY NUMKEY SIZEDATA SIZEEXPIRE IN HOUREXPIRE IN DAYEXPIRE IN WEEKEXPIRE OUT WEEKNEVER EXPIRE
TOP_TEN_NEW_XXXXXXXX*120152900001
XXXXXXXXXXXXXX_STATISTICS_MIGRATION_LIST*140769283200001
time-root:*23272299000023
DS_AXXXXXXXX_CORRECT*2454600002
time-2*761752898930000761
time-level:*537846169810000537
time-9*10290113260000102
time-7*153137219890000153
DS_MAGIC_SUCC_2017-06-22*12441500001
tersssss*5124000005
appoint_abcdefg_msgid*121000001
BUSSINESSXXXXXXX_STATISTICS_NEED_CALC_RECENT*144100001
switch_abcd_abcde*369300003
abcdeferCounter_201*378000003
diy1234567flag*114100001
DS_PRXXBCD_LIST*1151720800001
time-4*133119417290000133
datastatistics_switch_version0*130100001
register_count_2_201*592159846400000592
canVisitNewabcdef1234PageLevels*131000001
YOUR_WEEK_VITALITY_INFO*1237578200001
time-8*10189413130000101
EXPERTS_APPOINT_INFO_MAP*124000001
time-3*130121516900000130
time-1*9439456122590000943
time-64*877811131000087
time-5*168151621840000168
total400453422783249000004004

string keys statistics

PATTERNKEY NUMKEY SIZEDATA SIZEEXPIRE IN HOUREXPIRE IN DAYEXPIRE IN WEEKEXPIRE OUT WEEKNEVER EXPIRE
BUSSINESSXXXXXXX_STATISTICS_NEED_CALC_RECENT*144100001
time-5*130117416900000130
datastatistics_switch_version0*130100001
time-7*39348507000039
time-level:*567893973710000567
diy1234567flag*114100001
switch_abcd_abcde*369300003
time-2*598591877740000598
time-6*125111816250000125
time-4*136122517680000136
time-8*72636936000072
time-1*1176118141528800001176
time-9*10088013000000100
time-root:*23272299000023
register_count_2_201*592159846400000592
DS_AXXXXXXXX_CORRECT*1202000001
TOP_TEN_NEW_tersssss*120152900001
time-3*202192526260000202
total3989530424625300003989

list keys statistics

PATTERNKEY NUMKEY SIZEDATA SIZEEXPIRE IN HOUREXPIRE IN DAYEXPIRE IN WEEKEXPIRE OUT WEEKNEVER EXPIRE
XXXXXXXXXXXXXX_STATISTICS_MIGRATION_LIST*140769283200001
DS_MAGIC_SUCC_2017-06-22*12441500001
DS_PRXXBCD_LIST*1151720800001
total379771045500003

hash keys statistics

PATTERNKEY NUMKEY SIZEDATA SIZEEXPIRE IN HOUREXPIRE IN DAYEXPIRE IN WEEKEXPIRE OUT WEEKNEVER EXPIRE
tersssss_action_prepage_new*127000001
YOUR_WEEK_VITALITY_INFO*1237578200001
EXPERTS_APPOINT_INFO_MAP*124000001
abcdeferCounter_2017-06-11*126000001
tersssssHardTaskCounter*123000001
abcdeferCounter_2018-04-27*126000001
abcdeferCounter_2017-09-01*126000001
tersssssEasyTaskCounter*123000001
total81987578200008

set keys statistics

PATTERNKEY NUMKEY SIZEDATA SIZEEXPIRE IN HOUREXPIRE IN DAYEXPIRE IN WEEKEXPIRE OUT WEEKNEVER EXPIRE
tersssss_bind_phone_phone*125000001
appoint_abcdefg_msgid*121000001
canVisitNewabcdef1234PageLevels*131000001
tersssss_bind_phone_userid*126000001
total4103000004

zset keys statistics

PATTERNKEY NUMKEY SIZEDATA SIZEEXPIRE IN HOUREXPIRE IN DAYEXPIRE IN WEEKEXPIRE OUT WEEKNEVER EXPIRE
total00000000

other keys statistics

PATTERNKEY NUMKEY SIZEDATA SIZEEXPIRE IN HOUREXPIRE IN DAYEXPIRE IN WEEKEXPIRE OUT WEEKNEVER EXPIRE
total00000000

big keys statistics

PATTERNKEY NUMKEY SIZEDATA SIZEEXPIRE IN HOUREXPIRE IN DAYEXPIRE IN WEEKEXPIRE OUT WEEKNEVER EXPIRE
XXXXXXXXXXXXXX_STATISTICS_MIGRATION_LIST*140769283200001
total140769283200001

作为依赖使用

获取方法如下:

go get github.com/winjeg/rma4go

使用方法如下:

func testFunc() {h := "localhost"a := ""p := 6379cli := client.BuildRedisClient(client.ConnInfo{Host: h,Auth: a,Port: p,}, cmder.GetDb())stat := analyzer.ScanAllKeys(cli)// print in command linestat.Print()// the object is ready to use
}

github 维护(主要阵地)

  1. 欢迎其他开发者加入
  2. 欢迎提issue 反馈问题
  3. 欢迎任何有意义的建议
  4. 另外欢迎star,不建议fork,建议直接提交PR ; )

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/388878.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从Jupyter Notebook到脚本

16 Aug: My second article: From Scripts To Prediction API8月16日&#xff1a;我的第二篇文章&#xff1a; 从脚本到预测API As advanced beginners, we know quite a lot: EDA, ML concepts, model architectures etc…… We can write a big Jupyter Notebook, click “Re…

加勒比海兔_加勒比海海洋物种趋势

加勒比海兔Ok, here’s a million dollar question: is the Caribbean really dying? Or, more specifically, are marine species found on Caribbean reefs becoming less abundant?好吧&#xff0c;这是一个百万美元的问题&#xff1a;加勒比海真的死了吗&#xff1f; 或者…

tornado 简易教程

引言 回想Django的部署方式 以Django为代表的python web应用部署时采用wsgi协议与服务器对接&#xff08;被服务器托管&#xff09;&#xff0c;而这类服务器通常都是基于多线程的&#xff0c;也就是说每一个网络请求服务器都会有一个对应的线程来用web应用&#xff08;如Djang…

人口密度可视化_使用GeoPandas可视化菲律宾的人口密度

人口密度可视化GeoVisualization /菲律宾。 (GeoVisualization /Philippines.) Population density is a crucial concept in urban planning. Theories on how it affects economic growth are divided. Some claim, as Rappaport does, that an economy is a form of “spati…

Unity - Humanoid设置Bip骨骼导入报错

报错如下&#xff1a; 解决&#xff1a; 原因是biped骨骼必须按照Unity humanoid的要求设置&#xff0c;在max中设置如下&#xff1a; 转载于:https://www.cnblogs.com/CloudLiu/p/10746052.html

Kubernetes - - k8s - v1.12.3 OpenLDAP统一认证

1&#xff0c;基本概念 为了方便管理和集成jenkins&#xff0c;k8s、harbor、jenkins均使用openLDAP统一认证。2&#xff0c;部署openLDAP 根据之前的文档&#xff0c;openLDAP使用GFS进行数据持久化。下载对应的openLDAP文件git clone https://github.com/xiaoqshuo/k8s-clust…

srpg 胜利条件设定_英雄联盟获胜条件

srpg 胜利条件设定介绍 (Introduction) The e-sports community has been growing rapidly in the past few years, and what used to be a casual pastime has morphed into an industry projected to generate $1.8 B in revenue by 2022. While there are many video games …

机器学习 综合评价_PyCaret:机器学习综合

机器学习 综合评价Any Machine Learning project journey starts with loading the dataset and ends (continues ?!) with the finalization of the optimum model or ensemble of models for predictions on unseen data and production deployment.任何机器学习项目的旅程都…

silverlight 3D 游戏开发

http://www.postvision.net/SilverMotion/DemoTech.aspx silverlight 3D 游戏开发 时间:2010-10-22 06:33来源:开心银光 作者:黎东海 点击: 562次意外发现一个silverlight的实时3D渲染引擎。性能比开源那些强很多。 而且支持直接加载maya,3Dmax等主流3D模型文件。 附件附上它的…

皮尔逊相关系数 相似系数_皮尔逊相关系数

皮尔逊相关系数 相似系数数据科学和机器学习统计 (STATISTICS FOR DATA SCIENCE AND MACHINE LEARNING) In the last post, we analyzed the relationship between categorical variables and categorical and continuous variables. In this case, we will analyze the relati…

Kubernetes持续交付-Jenkins X的Helm部署

Jenkins X 是一个集成化的 CI / CD 平台&#xff0c;可用于 部署在Kubernetes集群或云计算中心。支持在云计算环境下简单地开发和部署应用。本项目是在Kubernetes上的安装支持工具集。 本工具集中包含&#xff1a; Jenkins - 定制好的流水线和运行环境&#xff0c;完全整合CI/C…

中国石油大学(华东)暑期集训--二进制(BZOJ5294)【线段树】

问题 C: 二进制 时间限制: 1 Sec 内存限制: 128 MB提交: 8 解决: 2[提交] [状态] [讨论版] [命题人:]题目描述 pupil发现对于一个十进制数&#xff0c;无论怎么将其的数字重新排列&#xff0c;均不影响其是不是3的倍数。他想研究对于二进制&#xff0c;是否也有类似的性质。于…

Java 8 新特性之Stream API

1. 概述 1.1 简介 Java 8 中有两大最为重要的改革&#xff0c;第一个是 Lambda 表达式&#xff0c;另外一个则是 Stream API&#xff08;java.util.stream.*&#xff09;。 Stream 是 Java 8 中处理集合的关键抽象概念&#xff0c;它可以指定你希望对集合进行的操作&#xff0c…

Ubuntu中NS2安装详细教程

前言&#xff1a; NS2是指 Network Simulator version 2&#xff0c;NS&#xff08;Network Simulator&#xff09; 是一种针对网络技术的源代码公开的、免费的软件模拟平台&#xff0c;研究人员使用它可以很容易的进行网络技术的开发&#xff0c;而且发展到今天&#xff0c;它…

14.vue路由脚手架

一.vue路由&#xff1a;https://router.vuejs.org/zh/ 1、定义 let router new VueRouter({mode:"history/hash",base:"基本路径" 加一些前缀 必须在history模式下有效linkActiveClass:"active", 范围选择linkExactActiveClass:"exact&qu…

linux-buff/cache过大导致内存不足-程序异常

2019独角兽企业重金招聘Python工程师标准>>> 问题描述 Linux内存使用量超过阈值&#xff0c;使得Java应用程序无可用内存&#xff0c;最终导致程序崩溃。即使在程序没有挂掉时把程序停掉&#xff0c;系统内存也不会被释放。 找原因的过程 这个问题已经困扰我好几个月…

Android 适配(一)

一、Android适配基础参数1.常见分辨率&#xff08;px&#xff09;oppx 2340x1080oppR15 2280x1080oppor11sp 2160*10801080*1920 (主流屏幕16&#xff1a;9)1080*216018:9 手机主流分辨率&#xff1a; 1080*2160高端 16:9 手机主流分辨率&#xff1a; 1080P (1080*1920) 或 2K …

Source Insight 创建工程(linux-2.6.22.6内核源码)

1. 软件设置 安装完Source Insight&#xff0c;需要对其进行设置添加对“.S”汇编文件的支持&#xff1a; 2. 新建linux-2.6.22.6工程 1&#xff09;选择工程存放的路径&#xff1a; 2&#xff09;下载linux-2.6.22.6内核源码&#xff0c;并解压。在Source Insight中 指定源码的…

课时20:内嵌函数和闭包

目录&#xff1a; 一、global关键字 二、内嵌函数 三、闭包 四、课时20课后习题及答案 ******************** 一、global关键字 ******************** 全局变量的作用域是整个模块&#xff08;整个代码段&#xff09;&#xff0c;也就是代码段内所有的函数内部都可以访问到全局…

盛严谨,严谨,再严谨。_评估员工调查的统计严谨性

盛严谨,严谨,再严谨。The human resources industry relies heavily on a wide range of assessments to support its functions. In fact, to ensure unbiased and fair hiring practices the US department of labor maintains a set of guidelines (Uniform Guidelines) to …