记一次上线后redis出现的问题及处理方法。
前言
在此项目之前,有一个项目用到了redis,那个项目中的key数较少(2W左右),目前没出现问题(如果之后key数上升,有些地方也需要进行调整),使自己的判断出现了问题,以为redis是可以随便用的,然后就产生了下面的问题。
问题及处理
1.key数的增长异常
原因:因为系统采用redis作为session的存储,在每次有web请求时都会创建一个session,而提供出去的接口访问特别密集(一天200W次),导致了增加了很多session的key。
解决:当接收接口调用时,不开启session。
2.keys的阻塞
原因:当key数增加时,由于接口中会使用keys查询账号信息,导致查询时间增长,阻塞其他查询。
解决:修改系统中keys查询改为键查询。
3.del的阻塞
原因:当删除较大的key值时,需要的时间会变长,可能阻塞其他查询。
解决:修改系统中del为unlink异步删除。
4.内存占用过大
原因:当缓存如简历(10k左右),头像(15k左右)等信息时,随着key的增多,内存会占用很大。
解决:修改系统只有当简历(简历详情页面)与头像(简历详情,面试官列表)被使用时,才进行缓存7天。
5.read error on connection
原因:在排除了慢查询,cpu,内存,网络问题后,只能猜想是由于rdb的频繁同步引起阻塞导致执行超时
解决:修改3台机器的rdb同步时间为6小时一次,一台从机的rdb同步时间为1小时一次。
总结
1.模糊查询
模糊查询指用redis中keys
命令,来一次性查询多个匹配模式的key,当想将redis当作数据表使用时,可能会下意识的使用此方法。
如果非得需要将redis当数据表使用可通过set
数据结构或通过程序代码将数据表在redis与程序中进行序列化与反序列化。
keys的性能在服务器中key数较少或并发查询不高时,并不会产生明显的问题;反之当key数增加或并发查询变高时,性能会下降很明显(比如需要几十ms才能完成查询),而由于redis单线程的设计,就会导致后面的查询都要阻塞,就可能会导致查询超时的错误。
如下案例为在开发环境下测试的keys(模糊查询)与hgetall(键值访问)随着key数量的变化而产生的性能变化。
最终测试结果是,keys性能会越来越差,而hgetall性能基本保持不变。
2.大key删除
redis中的del命名为同步删除,如果删除的key对应的值较大,在并发情况下可能会出现阻塞,在redis4.0版本后可使用unlink实现异步删除。
3.服务器公用
因为之前系统key数较少占用的空间不大,想着不浪费资源的目的,此系统的redis服务器也使用之前系统的,不幸的是因为此系统的故障,导致了原系统也出现了问题。
- 不同系统千万不要公用服务器
- 如果要公用,在上线前确保进行非常完善的评估
4.压力评估
如果在系统上线前能做压力测试是最好的,通过压力测试可以暴露出正常使用较难发现的系统bug和性能问题。
如果没有条件做压力测试,则需要根据上线后的预测使用与并发量(这里需要比较准确
)来评估系统的性能是否能满足需要,一般包含如下几点:
1.连接数
这里评估的是并发量是否会超过redis的最大客户端数(maxclients),根据需求适当的选用短链接还是长连接。
2.key数
这里评估的是随着系统的使用(结合用户数),产生的key数是一个什么量级,如果key有过期时间则结合过期时间进行计算。
3.key值大小
这里评估的是,key里存储内容的可能大小,结合key数可计算出可能占用的内存是否会超出redis的最大可能内存,如果超出则会发生内存与磁盘的swap(maxmemory=0),影响读写的性能。
如果内容大小超过10kb
,即使占用内存在最大内存范围内,也可能导致并发请求的性能下降。
4.命中率
将数据放入redis是为了之后程序可以从里面读取内容,避免从数据库访问,从而降低数据库的压力且提高了读取数据;所以需要考虑放入缓存中的数据,之后会被访问的概率,如果较低可以暂时不放入缓存,将空间留给需要高频访问的数据,避免对空间的浪费。