Redis的使用场景和实例

redis

是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

【1】案例一现象:
生产系统刚开始运行阶段,系统稳定。但是运行了一段时间后,发现部分时间段系统接口响应变慢。查看客户端日志经常会出现如下错误:

redis.clients.jedis.exception.JedisConnectionException:java.net.SocketTimeoutException:Read time out
问题定位:执行 slowlog 查看慢查询日志,发现大量的 keys 命令操作,keys 命令在大量并发情况下性能非常差,生产环境,尽量避免使用 keys,接下来找出使用 keys 的代码做优化,直到 time out 问题解决。

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的使用场景和实例
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 突然间不能访问,返回如下错误:

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(表示内核允许分配所有的物理内存,而不管当前的内存状态如何) 问题便可解决。

192.168.17.46:6386> CONFIG GET logfile
1) "logfile"
2) "/home/redis02/redis/log/6386.log"

赞(0)
未经允许不得转载:主机测评网 » Redis的使用场景和实例
分享到: 更多 (0)