今天遇到一个问题
MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.

redis 2.8.9 虚拟内存 redis把内存撑爆了_d3


网上很多帖子都说通过redis-cli 执行命令 config set stop-writes-on-bgsave-error no可以解决,但是这仅仅是让程序忽略了这个异常,使得程序能够继续往下运行,但实际上数据还是会存储到硬盘失败!

不过为了先快速解决问题,让用户先能够登录进系统,所以我还是在每个主节点执行了config set stop-writes-on-bgsave-error no。但是进入系统的时候报了MISSCONF Errors writing to the AOF file:No space left on device错误,这是因为我访问这个页面的时候代码有对redis集群做写操作,要往redis集群写数据,但是内存空间不足造成的。

redis 2.8.9 虚拟内存 redis把内存撑爆了_数据_02


遇到这个类似内存不足的情况不要慌,大致的解决思路无非就两个,要不就是加大redis集群的内存,要不就把redis集群中没用的数据清除掉,把空间腾出来。

我选择把redis 集群中没用的数据清除掉这种解决思路。

首先我就要排查是什么数据导致redis的内存撑爆了,哪些数据是可以清楚的。

由于我使用的是JedisCluster对集群做操作的,所以往redis集群写数据的地方必定是调用了redisCluster.set方法的,通过IntelliJ工具(按ctrl+H快捷键),我们可以很方便的找到我们哪些地方往redis集群写数据,如下图

redis 2.8.9 虚拟内存 redis把内存撑爆了_爆满_03


通过对每一个jedisCluster.set方法的检查,我把对redis集群的写操作总结为以下五种。发现造成redis集群内存爆满应该是因为第3点与第6点。

第3点因为用户的token不是固定的,每次token改变都会往redis集群里写一条新的数据,有没有清除机制,导致数据堆积。

第6点是因为只要这四种列表有新的数据,就会往redis集群里写一条新的数据(为了实现未读显示红点功能),而且value还是一个多字段的对象,占用内存比较严重。

redis 2.8.9 虚拟内存 redis把内存撑爆了_d3_04

发现了产生堆积的地方,接下来就是如果去改正了。
首先我先修改程序,为第3点的manager token增加一个过期时间,把第6点的业务逻辑由永远不过期该为只要查看了就从redis集群中移除。

然后就是清除以往堆积的数据了(先根据实际情况考虑是否能清除,清除后会有什么影响),我这里把第3点的manager token清除对用户没什么影响,只需要重新登录就可以了。把第6点的数据清除,只是会在访问列表的时候,会多了一个红点。

如果批量清除redis cluster中的某个前缀key的数据?
我的是linux系统,
新建一个redis_del.sh文件,文件的内容如下

#!/bin/bash
redis_comm=/home/docker-compose/redis/redis-5.0.5/src/redis-cli
redis_ser01=120.24.168.90
redis_ser02=120.24.168.90
redis_ser03=120.24.168.90
port01=7000
port02=7001
port03=7002
$redis_comm -c -h $redis_ser01 -p $port01 -a 123456 keys $1 | xargs -i ./redis-cli -c -h $redis_ser01 -p $port01 -a 123456 del {}
$redis_comm -c -h $redis_ser02 -p $port02 -a 123456 keys $1 | xargs -i ./redis-cli -c -h $redis_ser02 -p $port02 -a 123456 del {}
$redis_comm -c -h $redis_ser03 -p $port03 -a 123456 keys $1 | xargs -i ./redis-cli -c -h $redis_ser03 -p $port03 -a 123456 del {}

redis 2.8.9 虚拟内存 redis把内存撑爆了_redis_05


这里注意的是,建议直接在linux系统上面新建一个文件touch redis_del.sh,不要在windows系统上面建好再复制上去,因为例如上我上一张截图,在windows下使用nodepad++写好这个redis_del文件再上传上linux服务器,这个文件会有一个编码问题,导致执行会出错-bash: ./redis_del.sh: /bin/bash^M: bad interpreter: No such file or directory。

另外,如果执行redis_del.sh脚本的时候报-bash: ./redis_del.sh: Permission denied,先执行以下命令chmod -R 777 redis_del.sh

开始执行sh脚本删除数据,输入命令./redis_del.sh keys*

删除成功,如下图

redis 2.8.9 虚拟内存 redis把内存撑爆了_d3_06

=分割线===================

上面以为修复了的MISCONF Errors writing to the AOF file: No space left on device,今天又报了,也就是说昨天的解决思路是不完全正确的,这个错误说磁盘空间不足了,我们首先应该在宿主机执行df -h命令看一下内存的使用情况,如下图,可以看到,use%已经100%了。

redis 2.8.9 虚拟内存 redis把内存撑爆了_redis_07


到时是哪里占用了那么大的内存呢?我们首先回到根目录,然后使用du -sh * 命令,从根目录一层一层往里面看,看看到底是哪个目录占用的资源最大,如下图

redis 2.8.9 虚拟内存 redis把内存撑爆了_redis cluster_08


先看看log目录,占了15G,我整个云服务器磁盘空间才40G,日志给我整了15G!?这不是开玩笑吗,首先想到这里面的日志有哪些是可以删的,里面有个journalctl 目录,占的空间比较大,占了3.9G

redis 2.8.9 虚拟内存 redis把内存撑爆了_redis cluster_09


redis 2.8.9 虚拟内存 redis把内存撑爆了_redis cluster_10

journal 目录是什么?

journalctl 用来查询 systemd-journald 服务收集到的日志。systemd-journald 服务是 systemd init 系统提供的收集系统日志的服务。

只要你不需要日志进行任何调试,可以删除 /var/log/journal/* 内的所有内容,但不要删除目录本身。

你应该看看/etc/systemd/journald.conf,有一个设置可以限制系统存储的日志量(下文有介绍),因此旧的日志会被轮换出来。这个设置并不完美,因为损坏的文件显然不会计入这个总数(至少在几个月之前是这种情况,不确定它现在是否已修复)。

控制 journal 目录大小

可以使用/etc/systemd/journald.conf中的此参数控制此目录的大小:

SystemMaxUse=50M

关于journald.conf文件里面的参数配置的具体含义,可以参考这篇博客:
https://blog.51cto.com/wutengfei/2336490?source=dra

如果上述信令方法不这样做,你可能需要重新启动日志记录服务以强制进行日志轮换。你可以像这样重启服务:

$ sudo systemctl kill --kill-who=main --signal=SIGUSR2 systemd-journald.service

系统日志messages占用空间

/var/log/messages ** – 包含整个系统的信息,包括系统启动期间被记录的日志。mail, cron, daemon, kern, auth等相关的日志信息在这里记录。**

redis 2.8.9 虚拟内存 redis把内存撑爆了_redis_11

docker的镜像文件占用很大的空间

我们一层层的du -sh * 进来,可以发现/var/lib/docker/overlay2目录占用了很大的内存。

redis 2.8.9 虚拟内存 redis把内存撑爆了_redis_12


可以发现镜像文件占用了22.23G

redis 2.8.9 虚拟内存 redis把内存撑爆了_数据_13


然后用docker images 命令查看一下现有的镜像,什么鬼,这些不知道怎么创建的(可以是构建reids cluster的时候创建的,因为当时我构建redis cluster时构建了很多次才成功)。

redis 2.8.9 虚拟内存 redis把内存撑爆了_redis cluster_14


清掉这些没用的镜像之后,释放了大部分的资源。

redis 2.8.9 虚拟内存 redis把内存撑爆了_redis_15


总结:
1. 在设计redis的时候,不管是单机还是集群,都需要考虑内存的分配是否合理。
2. 往redis里存数据的时候,一定要考虑存进去的数据是否应该清除,什么时清除,以免造成数据堆积。

cd /
[root@iZwz91yivd3mhf8pjiqf4aZ /]# du -h --max-depth=1
39M	./etc
97M	./boot
4.0K	./mnt
0	./dev
4.0K	./srv
1.2G	./home
du: cannot access ‘./proc/21112/task/21112/fd/3’: No such file or directory
du: cannot access ‘./proc/21112/task/21112/fdinfo/3’: No such file or directory
du: cannot access ‘./proc/21112/fd/4’: No such file or directory
du: cannot access ‘./proc/21112/fdinfo/4’: No such file or directory
du: cannot access ‘./proc/27336/fdinfo/192’: No such file or directory
0	./proc
2.7G	./usr
16K	./lost+found
4.0K	./opt
11G	./var
76M	./tmp
0	./sys
4.0K	./media
11M	./run
85G	./root
100G	.
[root@iZwz91yivd3mhf8pjiqf4aZ /]# cd ./root/
[root@iZwz91yivd3mhf8pjiqf4aZ ~]# du -h --max-depth=1
604K	./.cache
12K	./.config
140M	./.npm
8.0K	./.pki
85G	./.pm2
4.0K	./.ssh
8.0K	./.pip
85G	.
[root@iZwz91yivd3mhf8pjiqf4aZ ~]# cd ./.pm2/
[root@iZwz91yivd3mhf8pjiqf4aZ .pm2]# du -h --max-depth=1
4.0K	./modules
8.0K	./pids
85G	./logs
85G	.
[root@iZwz91yivd3mhf8pjiqf4aZ .pm2]# cd ./logs/
[root@iZwz91yivd3mhf8pjiqf4aZ logs]# du -h --max-depth=1
85G	.
[root@iZwz91yivd3mhf8pjiqf4aZ logs]# cd .
[root@iZwz91yivd3mhf8pjiqf4aZ logs]# ll
total 88969224
-rw-r--r-- 1 root root 83290534648 Jan 28 13:51 nuxt-server-error.log
-rw-r--r-- 1 root root  7813864060 Jan 28 13:51 nuxt-server-out.log
[root@iZwz91yivd3mhf8pjiqf4aZ logs]# du -sh *
78G	nuxt-server-error.log
7.3G	nuxt-server-out.log
[root@iZwz91yivd3mhf8pjiqf4aZ logs]# 




[root@iZwz91yivd3mhf8pjiqf4aZ /]# docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              100                 10                  7.962GB             7.424GB (93%)
Containers          12                  10                  377kB               0B (0%)
Local Volumes       2                   2                   94.32kB             0B (0%)
Build Cache         0                   0                   0B                  0B