k8s 中redis集群中报错
k8s中生产环境关于redis集群导致pod报错连接redis失败1、当出现了pod出现了pod连接reids 失败的原因的日志 首先确认redis的日志 如果有没有报错2、查看pod的状态是不是running 的状态我这里基本上都没问题然后我用kubectl delete pod redis-0 等一个pod起来了,然后在启动项目的pod这种重启方法不行然后用kubectl get pod -o
文章目录
k8s中生产环境关于redis集群导致pod报错连接redis失败 记录第一次报错记录
1、当出现了pod出现了pod连接reids 失败的原因的日志 首先确认redis的日志 如果有没有报错
2、查看pod的状态是不是running 的状态
我这里基本上都没问题
然后我用
kubectl delete pod redis-0 等一个pod起来了,然后在启动项目的pod
这种重启方法不行
然后用
kubectl get pod -owide | grep manman-redis #来查看pod的ip地址
查看到pod的IP地址后 进去pod
kubectl exec -it manman-redis-0 -- bash (这里的redis名字 举了一个例子)
[nec@elearningpre-release-jumpbox ~]$ kubectl exec -it manman-redis-0 -- redis-cli -c
127.0.0.1:6379> cluster nodes (去查看)
这个图就是
刚才我们用kubectl get pod -owide | grep manman-redis 来查看pod的ip 进行一 一对应 查看ip是否正确 然后把那个slave的ip 用
cluster forget 输入后面的那个容器的id (请看上面的图片)
重启项目的pod就可以了
记录redis集群在K8S环境内第二次报错
**
redis集群无法加入节点加入节点的时候地址错误(k8s环境中的redis)
是重新 初始化的redis集群
如果是生产环境下需要把redis集群中/data 目录下的appendonly.aof
core
dump.rdb
这三个文件需要拷贝到本地应该会很大
直接初始化这个集群 然后把本地的三个文件导入到对应的redis 集群中的
一 一 对应导入redis 导入上面的三个文件
k8s 环境中 导入一个pod中需要重启一个pod或者都导入成功了重启6个pod
这样的话redis 集群就会初始化。 然后redis集群也不会受到影响
记录redis集群在K8S环境内第三次报错
记录一次关于k8s 集群中得redis集群出现
Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting fo
报错 下面截图为程序报错
这是由i/o磁盘线程较高导致的redis 持久化 AOF和 RDB 引起的生产故障
具体这个故障分析都是在网上找的看写的不错
问题分析
首先我们要知道,redis 是一个多路复用的单进程应用程序。多路,指的是多个网络地址,复用是指重复利用单个线程。当打开 AOF 持久化功能后, Redis 处理完每个事件后会调用 write(2) 将变化写入 kernel 的 buffer,如果此时 write(2) 被阻塞,Redis 就不能处理下一个事件。Linux 规定执行 write(2) 时,如果对同一个文件正在执行fdatasync(2)将 kernel buffer写入物理磁盘,或者有system wide sync在执行,write(2)会被Block住,整个Redis被Block住。
如果系统IO 繁忙,比如有别的应用在写盘,或者Redis自己在AOF rewrite或RDB snapshot(虽然此时写入的是另一个临时文件,虽然各自都在连续写,但两个文件间的切换使得磁盘磁头的寻道时间加长),就可能导致 fdatasync(2) 迟迟未能完成从而 Block 住 write(2),Block 住整个 Redis。而,我们的生产主库和从库都同时开启了AOF已经RDB save的方式做持久化。
为了更清晰的看到fdatasync(2)的执行时长,可以使用 "strace -p (pid of redis server) -T -e -f trace=fdatasync",但会影响系统性能。Redis提供了一个自救的方式,当发现文件有在执行 fdatasync(2) 时,就先不调用 write(2),只存在 cache 里,免得被 Block。但如果已经超过两秒都还是这个样子,则会硬着头皮执行 write(2),即使 redis 会被 Block 住。此时那句要命的 log 会打印:"Asynchronous AOF fsync is taking too long (disk is busy?). Writing the AOF buffer without waiting for fsync to complete, this may slow down Redis."。之后用redis-cli INFO 可以看到 aof_delayed_fsync 的值被加1。因此,对于 fsync 设为 everysec 时丢失数据的可能性的最严谨说法是:如果有 fdatasync 在长时间的执行,此时 redis 意外关闭会造成文件里不多于两秒的数据丢失。如果 fdatasync 运行正常,redis 意外关闭没有影响,只有当操作系统 crash 时才会造成少于1秒的数据丢失。
网上有小伙伴说,该错误在后续版本有修复。
解决
1、如果是linux 服务器redis集群 执行
查看内核参数
sysctl -a | grep dirty_background_ratio
vm.dirty_background_ratio = 10
sysctl -a | grep vm.dirty_bytes
vm.dirty_bytes = 0
执行这个命令
echo “vm.dirty_bytes=33554432” >> /etc/sysctl.conf
sysctl -p
2、如果是k8s redis集群的问题 要添加初始化容器
在redis 集群中的yaml 文件中添加 以下图中的字段
initContainers:
- name: "redis-init"
image: busybox:latest
securityContext:
privileged: true
command: ["sysctl","-w","vm.dirty_bytes=33554432"]
注意添加完重新把yaml文件apply 一下 把redis的pod删除 等起来一个pod在删除另外一个pod
把redis集群的pod全部删除完成后
进去pod
sysctl -a | grep vm.dirty_bytes (查看一下结果)
这样程序就不会报错
记录redis集群在K8S环境内第四次报错
关于redis内存原因
由于业务量的不停的增加导致内存不足和开发沟通 第一次加了5G的内存后来不到一个月内存持续的上升
由于当时redis不能使用导致当时网站停止后来加上5G的内存 经过监控发现 redis的pod持久上升所有排查了 将近3天的内存过大的原因
在k8s环境上由于使用的是无状态服务只能使用deployment 所以没有用到集群
排错思路
1、
当时让开发写了一个设置过期时间的脚本 运维也可以设置但是有可能会导致redis雪崩的问题 所以当时让开发提供的脚本只是把里面的过期的键值清理10w条左右 重启redis后依然内存问题没有下降
2、看了看服务器上redis的内存碎片的值也不是很高
redis-cli
memory info
我们的服务器上的内存碎片不高
mem_fragmentation_ratio: 1.03
3、redis-cli bigkey
这个命令可以简单的扫描一下 里面的业务中有没有用单一key的hash list或者set存了大量数据的
扫描这个是redis db0 库里面的 进入其他db中可以扫描一下是不是有当时我没有扫描我直接把rdb数据文件导出下来 自己分析看到db7 库中有一个key的值达到了13G
和开发沟通这个问题开发这个可能是以前的他们把内存机制已经写进了代码里
解决
一定和开发 或者业务上的人确认redis的数据可不可以删除 (一定要确认)
然后备份
直接进去db7 删除这个key值 redis pod中的内存一下就下降了
当时一直都在和开发寻找这个问题把redis的发布订阅都看了 后来解决最笨的方法把rdb文件导出看一下里面的key值
监控一下发现redis的内存没有那么高 业务正常使用
更多推荐
所有评论(0)