【1】案例一现象:
生产系统刚开始运行阶段,系统稳定。可是运行了一段时间后,发现部分时间段系统接口响应变慢。查看客户端日志常常会出现以下错误:java
redis.clients.jedis.exception.JedisConnectionException:java.net.SocketTimeoutException:Read time out
问题定位:执行 slowlog 查看慢查询日志,发现大量的 keys 命令操做,keys 命令在大量并发状况下性能很是差,生产环境,尽可能避免使用 keys,接下来找出使用 keys 的代码作优化,直到 time out 问题解决。redis
192.168.17.46:6386> slowlog get 1) 1) (integer) 22 2) (integer) 1563344158 3) (integer) 10193 4) 1) "SET" 2) "getBatchChapterFiles" 3) "\x0b\xfa\529:\t489761532B\x02-1J\t48976181... (1293 more bytes)" 2) 1) (integer) 21 2) (integer) 1545403066 3) (integer) 10915 4) 1) "GET" 2) "getVolumeChapters#data"
【2】案例二现象:
生产环境长时间的运行后,常常会有接口返回数据失败的状况,或者是从监控上发现数据库压力某一时间暴增。查看客户端日志发现以下错误:
redis.clients.jedis.exceptions.JedisConnectionException:Cloud not get a resource from the pool数据库
在redis日志里面发现报错:
[2489] 02 Jun 10:43:42 # Error allocating resoures for the client服务器
问题定位:执行 client list 命令,发现大量的 client 的 idle 时间特别长。检查配置发现 timeout 和 tcp-keepalive(心跳检测) 均为启用(均为0),Redis 服务端没有有效的机制来确保服务端链接是否已经失效。当服务器与客户端网络发生闪断,致使tcp中断,这种状况下的 client 将会一直被 redis 服务端所持有,就会出现 idle(空闲)时间特长的 client 链接。
解决办法:设置 timeout 和 tcp-keepalive 来清理失效的链接。网络
redis/bin>redis-cli -h 192.168.17.46 -p 6386 info Clients # Clients connected_clients:5000 ---------------偏大 client_longest_output_list:0 client_biggest_input_buf:0 blocked_clients:0 192.168.17.46:6386> CONFIG GET timeout 1) "timeout" 2) "0" 192.168.17.46:6386> CONFIG GET tcp-keepalive 1) "tcp-keepalive" 2) "0"
192.168.17.46:6386> client list id=612260747 addr=192.168.17.92:53069 fd=806 name= age=114 idle=21 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping id=612260593 addr=192.168.41.44:38248 fd=381 name= age=131 idle=61 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get
字段定义
addr : 客户端的地址和端口
fd : 套接字所使用的文件描述符
age : 以秒计算的已链接时长
idle : 以秒计算的空闲时长
flags : 客户端 flag
db : 该客户端正在使用的数据库 ID
sub : 已订阅频道的数量
psub : 已订阅模式的数量
multi : 在事务中被执行的命令数量
qbuf : 查询缓冲区的长度(字节为单位, 0 表示没有分配查询缓冲区)
qbuf-free : 查询缓冲区剩余空间的长度(字节为单位, 0 表示没有剩余空间)
obl : 输出缓冲区的长度(字节为单位, 0 表示没有分配输出缓冲区)
oll : 输出列表包含的对象数量(当输出缓冲区没有剩余空间时,命令回复会以字符串对象的形式被入队到这个队列里)
omem : 输出缓冲区和输出列表占用的内存总量
events : 文件描述符事件
cmd : 最近一次执行的命令并发
【3】案例三现象:
Redis 忽然间不能访问,返回以下错误:tcp
redis.client.jedis.exception.JedisDataException: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 日志,发现以下错误:Cant save in background:fork:Cannot allocate memory Redis在保存内存的数据到磁盘时,为了防止主线程假死,会Fork 一个子进程来完成这个保存操做,这个Fork 的子进程须要分配与主进程相同的内存,这时候就至关于须要的内存翻倍了。若是这时候可用内存不足以分配须要的内存,将会致使Fork 子进程失败而没法将数据持久化到磁盘。修改Linux内核参数 vm.overcommit_memeory=1(表示内核容许分配全部的物理内存,而无论当前的内存状态如何) 问题即可解决。ide
192.168.17.46:6386> CONFIG GET logfile 1) "logfile" 2) "/home/redis02/redis/log/6386.log"