首页 > 数据库 >Redis哨兵内存碎片化故障处理

Redis哨兵内存碎片化故障处理

时间:2023-12-26 15:45:59浏览次数:40  
标签:mem 环境 redis 哨兵 内存 conf Redis

背景介绍

近期研发同学反馈业务响应波动厉害,怀疑是Redis操作key比较慢的缘故。由于该环境是我一手安装部署的,我将进行问题排查。

Redis环境以及业务环境都已经使用Prometheus进行了监控。

环境说明

我们有两套一样的环境来服务不同的客户,另外一套环境中业务一直平稳运行,Redis并没有任何问题。

由于部分信息涉及公司敏感数据,我将用A环境和B环境来代替问题环境和正常环境。

AB两个环境中都是部署的Redis哨兵模式,但研发同学由于业务需要,在插入Redis master后需要立即读取,所以他们并没有在代码中使用读写分离,担心主从延迟导致读取不到数据。

解决思路

1、对研发同学的判断持怀疑态度,首先确认是不是以为Redis操作key比较慢导致的业务波动
2、对比AB两环境机器本身的性能是不是差异很大
3、查看监控,对比AB两环境中Redis处理数据的差异
4、对比Redis的配置
5、对比Redis的info,查看是否有异常的地方

问题排查

理顺调用链路

由于研发同学是在监控面板看到Redis的业务波动,那我们也从监控面板来入手。调用线路如下:

我根据AB两个环境进行了以下几个方面的对比:

机器本身的性能对比

A环境:21核心 负载 2.16 内存free 11G

B环境:8核心 负载:0.71 内存free 324M

A环境的机器资源远高于B环境的资源。Redis操作key慢不是因为机器性能原因或资源不够导致的

每秒网络流量对比

A环境Redis监控:流入2.76MiB/s 流出5.95MiB/s

B环境Redis监控:1.33MiB/s 流出2.67MiB/s

A环境的流入流量以及流出是要比B环境的流入流出高一些,需要再看下两个Redis的key数量的对比

命令执行平均耗时

A环境Redis监控:1.28ms

B环境Redis监控:140us

A环境的Redis操作key的速度确实要慢一些。

每秒命令花费的总时长

A环境Redis监控:20ms

B环境Redis监控:5ms

正如研发同学所说,A环境的Redis确实比较慢,接下来就是要查出Redis慢的具体原因了

保存策略

A环境

127.0.0.1:6379> config get save
1) "save"
2) "3600 1 300 100 60 10000"

B环境

127.0.0.1:6379> config get save
1) "save"
2) "3600 1 300 100 60 10000"

保存策略是一样的

配置文件

配置文件就不放出来给大家看了,涉及敏感信息太多。将对比之后的差异拿出来供大家参考

配置文件对比结果有差异的部分如下所示:

protected-mode yes
stream-node-max-bytes 4096

解释

protected-mode yes
是否开启保护模式,默认开启。要是配置里没有指定bind和密码。开启该参数后,redis只会
本地进行访问,拒绝外部访问。要是开启了密码 和bind,可以开启。否 则最好关闭,设置为no。
stream-node-max-bytes 4096
Stream是Redis 5.0版本新增的数据类型。stream-node-max-bytes:单位为Byte,默认值为4096,即每个宏节点占用的内存容量上限为4096 Bytes。取值范围:0~999,999,999,999,999。0表示无限制。

两个参数的差异和Redis操作比较慢并没有太大关系

进程对比

A环境Redis进程

# cat /proc/33126/status 
......
VmRSS:  10069084 kB     # 换算约等于10G
......

B环境Redis进程

# cat /proc/242235/status
......
VmRSS:    216592 kB # 换算约等于0.2G
......

解释:

VmRSS:程序现在使用的物理内存.

VmPeak:代表当前进程运行过程中占用内存的峰值.
VmSize:代表进程现在正在占用的内存
VmLck:VmLck代表进程已经锁住的物理内存的大小.锁住的物理内存不能交换到硬盘.
VmData:表示进程数据段的大小.
VmStk:表示进程堆栈段的大小.
VmExe:表示进程代码的大小.
VmLib:表示进程所使用LIB库的大小.
VmPTE:占用的页表的大小.

发现A环境中的Redis使用的物理内存远高于正常环境B中Redis,那会不会是因为A环境中数量量较大的缘故?继续调查

A环境Redis进程

# ps axo pid,comm,pcpu|grep 33126
33126 redis-server     4.5

B环境Redis进程

# ps axo pid,comm,pcpu|grep 242235
242235 redis-server    10.8

Redis info对比

A环境Redis详情:

127.0.0.1:6379> info 
# Server
redis_version:6.2.12
# Memory
used_memory_rss_human:9.60G  Redis进程占用的物理内存总量
used_memory_peak_human:9.35G 以可读格式返回内存使用的最大值
mem_fragmentation_ratio:227.45 碎片率过大,导致内存资源浪费;,如果值越大,说明碎片越严重。
mem_allocator:libc # 内存分配器。默认是jemalloc
# Stats
total_connections_received:1085788
total_commands_processed:23625699956 服务器处理的命令总数
instantaneous_ops_per_sec:16904 每秒处理的命令数
# Keyspace
db0:keys=91039,expires=76193,avg_ttl=197651010
db10:keys=1124,expires=0,avg_ttl=0

B环境Redis详情

127.0.0.1:6379> info
# Server
redis_version:6.2.7
# Memory
used_memory_rss_human:210.41M
used_memory_peak_human:10.21G
mem_fragmentation_ratio:1.69
mem_allocator:jemalloc-5.1.0
# Stats
total_connections_received:1214805
total_commands_processed:84962263325
instantaneous_ops_per_sec:5752
# Keyspace
db0:keys=249802,expires=22780,avg_ttl=259788874
db10:keys=68340,expires=1,avg_ttl=29650800
db11:keys=3,expires=0,avg_ttl=0

通过查看info,我们可以看到A环境的key数量比B环境是要少的,既然少还执行这么慢,应该是其他地方出现了问题。

A机器的mem_fragmentation_ratio远大于正常值,并且mem_allocator是libc(默认是jemalloc,并且默认的jemalloc对于内存碎片管理是支持手动回收的。 )

A环境的Redis中key的数量还没有B环境多,却用了将近10G的内存,有很大问题。

mem_fragmentation_ratio的值代表含义如下:

  • mem_fragmentation_ratio < 1 表示Redis内存分配超出了物理内存,操作系统正在进行内存交换,内存交换会引起非常明显的响应延迟;
  • mem_fragmentation_ratio > 1 是合理的;
  • mem_fragmentation_ratio > 1.5 说明Redis消耗了实际需要物理内存的150%以上,其中50%是内存碎片率,可能是操作系统或Redis实例中内存管理变差的表现

确定问题

经过以上排查,大概是因为Redis内存碎片化的缘故导致A环境的Redis操作较慢。

什么是Redis内存碎片化?

Redis分配内存时,会根据需要申请一段连续的内存空间。但当Redis删除或修改数据时,释放的内存空间并不一定能被立即重新利用,尤其是当这些空闲内存空间大小不一致时,就可能导致内存碎片的出现。

为了提高内存使用的效率,Redis内部使用内存分配器来对内存的申请和释放进行管理。Redis使用的内存分配器默认是「jemalloc」。

我翻看当时安装A环境的Redis时使用整理的安装文档,如下:

# 消除警告
sysctl vm.overcommit_memory=1
echo  never > /sys/kernel/mm/transparent_hugepage/enabled 
echo "511" > /proc/sys/net/core/somaxconn
sysctl  net.core.somaxconn=4096
# 开始安装
apt install make  gcc
wget https://download.redis.io/releases/redis-6.2.12.tar.gz
mv redis-6.2.12.tar.gz  /etc/
cd /etc/
tar xf redis-6.2.12.tar.gz
mv redis-6.2.12 redis
rm -rf redis-6.2.12.tar.gz
cd redis/
make  && make  install
echo $?
mkdir /etc/redis/conf
cp redis.conf ./conf
rm -f /etc/redis/redis.conf
#sed  -i 's#daemonize no#daemonize yes#g' /etc/redis/conf/redis.conf
groupadd redis
useradd redis  -g redis -M -s /sbin/nologin
chown -R redis:redis /etc/redis

vim /etc/redis/conf/redis.conf
requirepass 2023@666.168
slaveof 10.0.0.10 6379
masterauth 2023@666.168


 
cat >/usr/lib/systemd/system/redis.service<<EOF
[Unit]
Description=Redis persistent key-value database 
After=network.target 
After=network-online.target 
Wants=network-online.target
 
[Service]
LimitNOFILE=65536
ExecStart=/usr/local/bin/redis-server /etc/redis/conf/redis.conf --supervised systemd 
ExecStop=/usr/local/bin/redis-cli -a 2023@666.168 shutdown 
User=root
Group=root 
RuntimeDirectory=redis 
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target 
EOF
systemctl daemon-reload
systemctl start  redis
ps -ef |grep redis

默认安装的Redis就是使用jemalloc才对,不应该是libc,很奇怪这一点,为何会装成了libc呢?

解决方案

经过和研发同学沟通今晚将重新安装A环境的Redis哨兵。

requirepass axb@3kjhRduihj1

哨兵配置 
sentinel monitor mymaster 192.168.2.192 6379 2
sentinel auth-pass mymaster axb@3kjhRduihj1

重新编译安装后业务没有再波动,内存使用量

注释:

测试sentinel auth-pass mymaster xxxx参数设置与不设置时 故障是否会自动转移 ?
答案: 需要设置并且在哨兵中的主从都需要设置masterauth xxx

标签:mem,环境,redis,哨兵,内存,conf,Redis
From: https://www.cnblogs.com/liushiya/p/17928269.html

相关文章

  • 疾速7600MT/s!KELVV科赋CRAS V RGB DDR5内存图赏
    12月18日消息,KLEVV科赋日前推出新款大容量DDR5内存套装,满足游戏玩家、内容创作者和高端PC爱好者的需求。现在,KLEVV科赋CRASVRGB内存套装已经来到我们评测室,下面为大家带来图赏。目前在售CRASVRGB均为16B*2套装,提供6000MT/s、6400MT/s、7200MT/s、7600MT/s、8000MT/s共五种不同......
  • Redis系列之事务机制
    什么是Redis事务学习mysql数据库的时候,我们知道了事务的ACID特性,Redis也是支持事务的,不过和数据库的事务又有什么区别?在mysql数据库中,我们使用begin开启事务,提交是commit,回滚是rollback,然后Redis中的事务是怎么一回事?redis的事务其实可以看做是一组命令按照顺序,串行执行队列中的命......
  • Windows下的Redis启动报错Redis service failed to start解决方法
    报错原因:Redis服务没有找到log文件解决方法在Redis安装目录下打开redis.windows-service.conf文件搜索logfile,找到logfile存放目录,一般默认为Logs/redis_log.txt在Redis安装目录创建Logs文件夹,在Logs文件夹下创建redis_log.txt文件重新启动即可解决......
  • Redis相关
    2023.12.26臭宝今天早上起床没拉粑粑,so sad   o(╥﹏╥)o  1.Redis为什么快?Redis是存在内存中的,Redis是单线程的,避免上下文切换。渐进式RehashRedis的所有数据都是存在一个hash数组上的,hash数组每个元素都是一个链表(所有类型都是,如String,hash,list,set,zset,bitma......
  • 【JVM调优】内存溢出+CPU占用过高:问题排查+解决方案+复盘
    前言最近刚上线了一款社交项目,运行十多天后(运营持续每天推量),发现问题:系统OOM(资源不能被释放)导致服务器频繁且长时间FGC导致服务器CPU持续飚高日志中内存溢出:java.lang.OutOfMemoryError:Javaheapspace程序十分卡顿,严重影响用户使用从以下方面,为大家分享此次问题解决流程问题出......
  • C++大内存分配错误
    C++无法分配大内存当影像较大时,m和n是int类型时,char*a=newchar[m*n]可能出现无法分配内存的错误原因分析:由于早期数据处理需求对内存需要较小,例如早期影像较小,影像长宽的积较小,char*a=newchar[m*n]不会出错。时代变化,影像体积变大,老代码仍旧使用int类型申请内存,将会出错。......
  • Redis进阶 Lua函数
    1.可以直接声明一个局部变量来接收函数,也可以直接简写localsquare=function(i)returni*iend简写:localfunctionsquare(i)returni*iend 2.当调用函数时,参数是一一对应的,如果多了参数,则会忽略,少则会将对应位置的参数赋值为nil 3.如果想要实现可变参数个数,也......
  • 美团面试:ES+Redis+MySQL高可用,如何实现?
    文章很长,且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录博客园版为您奉上珍贵的学习资源:免费赠送:《尼恩Java面试宝典》持续更新+史上最全+面试必备2000页+面试必备+大厂必备+涨薪必备免费赠送:《尼恩技术圣经+高并发系列PDF》,帮你实现技术自由,完成职业升级,薪......
  • Day38 三种数组初始化及内存分析
    三种数组初始化及内存分析Java内存分析Java内存:1.堆存放new的对象和数组​可以被所有的线程共享,不会存放别的对象引用2.栈存放基本变量类型(会包含这个基本类型的具体数值)​引用对象的变量(会存放这个引用在堆里面的具体地址)3.方法区可以被......
  • Ubuntu上安装、使用Redis的详细教程
    sudoapt-getupdatesudoapt-getinstallredis启动方式二systemctlstartredis-server启动方式三serviceredis-serverstart重启redisserviceredis-serverrestart关闭redisserviceredis-serverstop查看redis状态serviceredis-serverstatus4、在宿主机连接redis根据以......