暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

如何统计redis中的key分布?

原创 Shawn 2022-07-12
1999

当我们想了解一个redis时,除了它的软硬件配置、架构,还想知道这个redis中到底存储了什么?占用了多少内存?是否存在bigkey?
下面我们就用rdbtools工具和SQL来统计生产环境中redis的key分布,步骤如下:

1. 生成rdb快照(从库执行)

#连接redis
redis-cli -p 6379

127.0.0.1:6379> config get dir
1) "dir"
2) "/data/redisdb/redis_6379"

127.0.0.1:6379> config get dbfilename
1) "dbfilename"
2) "dump.rdb"

#生成rdb快照
127.0.0.1:6379> bgsave
Background saving started

2. rdbtools工具解析rdb

#安装pip
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
yum -y install python-pip
pip list

#安装redis-rdb-tools
yum -y install python-devel
pip install python-lzf
pip install rdbtools

#解析rdb文件
nohup rdb -c memory /data/redisdb/redis_6379/dump.rdb > /data/redisdb/redis_6379/dump.csv &

3. 解析结果导入mysql

#创建redis内存分析表
use modb;

drop table if exists memory_6379;
CREATE TABLE `memory_6379` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `database` int(128) DEFAULT NULL,
  `type` varchar(128) DEFAULT NULL,
  `KEY` varchar(128) NOT NULL,
  `size_in_bytes` bigint(20) DEFAULT NULL,
  `encoding` varchar(128) DEFAULT NULL,
  `num_elements` bigint(20) DEFAULT NULL,
  `len_largest_element` varchar(128) DEFAULT NULL,
  `expiry` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

#导入csv至mysql表
Load DATA INFILE '/data/redisdb/redis_6379/dump.csv'
Into Table memory_6379
character set utf8
Fields Terminated By ','
Enclosed By '"'
Escaped By '"'
Lines Terminated By '\n'
ignore 1 lines
(`database`,type,`key`,size_in_bytes,encoding,num_elements,len_largest_element,expiry);

4. 自定义SQL统计key分布

#自定义统计SQL

#查看bigkey
use modb;
select * from memory_6379 order by size_in_bytes desc limit 20;

#按Key样式统计(截取开始至第一个数字或'/'之间的字符串)
SELECT
  LEFT(`key`, LENGTH(`key`) - LOCATE('/', REVERSE(`key`))) as `key`,
  sum(cnt) as cnt,
  sum(size_in_bytes) as size_in_bytes
from
(
  select
    left (`key`, LEAST
    (
      IF(LOCATE(0,`key`)=0,9999,LOCATE(0,`key`)),
      IF(LOCATE(1,`key`)=0,9999,LOCATE(1,`key`)),
      IF(LOCATE(2,`key`)=0,9999,LOCATE(2,`key`)),
      IF(LOCATE(3,`key`)=0,9999,LOCATE(3,`key`)),
      IF(LOCATE(4,`key`)=0,9999,LOCATE(4,`key`)),
      IF(LOCATE(5,`key`)=0,9999,LOCATE(5,`key`)),
      IF(LOCATE(6,`key`)=0,9999,LOCATE(6,`key`)),
      IF(LOCATE(7,`key`)=0,9999,LOCATE(7,`key`)),
      IF(LOCATE(8,`key`)=0,9999,LOCATE(8,`key`)),
      IF(LOCATE(9,`key`)=0,9999,LOCATE(9,`key`))
    )-1) as `key`,
    count(*) as cnt,
    sum(size_in_bytes) as size_in_bytes
  from memory_6379
  group by
    left (`key`, LEAST
    (
      IF(LOCATE(0,`key`)=0,9999,LOCATE(0,`key`)),
      IF(LOCATE(1,`key`)=0,9999,LOCATE(1,`key`)),
      IF(LOCATE(2,`key`)=0,9999,LOCATE(2,`key`)),
      IF(LOCATE(3,`key`)=0,9999,LOCATE(3,`key`)),
      IF(LOCATE(4,`key`)=0,9999,LOCATE(4,`key`)),
      IF(LOCATE(5,`key`)=0,9999,LOCATE(5,`key`)),
      IF(LOCATE(6,`key`)=0,9999,LOCATE(6,`key`)),
      IF(LOCATE(7,`key`)=0,9999,LOCATE(7,`key`)),
      IF(LOCATE(8,`key`)=0,9999,LOCATE(8,`key`)),
      IF(LOCATE(9,`key`)=0,9999,LOCATE(9,`key`))
    )-1)
) tmp
group by LEFT(`key`, LENGTH(`key`) - LOCATE('/', REVERSE(`key`)))
order by size_in_bytes desc
;

至此,你对这个redis已胸有成竹。

优点:

  1. 对生产环境影响小
  2. 内存占用计算值较为准确
  3. 灵活自定义统计

缺点:

  1. 耗时较长
最后修改时间:2022-07-18 10:57:37
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论