redis使用list发生事故

应用有两台服务器,在其中一台服务器上面安装了redis,作为主服务器,项目接入了移动端,一周后,运维那边突然报告说两台服务器的流量一天比一天多,真的时成等差数列增加,奇怪的是两台服务器的流量出入是互补的。 

redis使用list发生事故_第1张图片

(由于某些原因,无法截图到原始图片)

红色表示Outgoing,绿色表示Incoming,两台服务器的流量进出大致呈现上面的图,其中下面的图是有redis的服务器,上面的图对应的服务器没有redis

这个问题出现是某个接口变得非常卡,通过设置时间查看具体的执行时间,发现在取redis的时候花费了大概1秒,查看redis内存和关键字对应的数据的时候,我们找到了问题。

之前这个接口使用list存储数据的,因为这个接口只是用来验证,生成token存入redis,之后很快就会取用这个token,如果考虑每次请求时间差不多,那么这个过程基本时先进先出,用list处理确实时不错的选择。

redisClient.rpush(key,JSON.Stringify(param),3*60);
往一个key里面存token,并且设置时间周期为3分钟,当取用token的时候:

redisClient.llen(key,function(err,len){
	redisClient.lrang(key,0,len,function(err,list){
		callback(err,list);
	})
})
redisClient.lrem('param',1,value);
会把这个key对应的list都取出来,然后循环找到对应token,并删除(上面代码只有redis的操作)。整个来说都是没有什么问题的,服务端请求时生成token,给客户端使用,用掉之后就会清除,这个接近FIFO的操作用list可以提高查询效率。只是,现在接入了移动端,移动端有一个特点,就是经常断线重连,服务端请求token,给客户端使用,为了安全这个过程一般来说都是连续的,但是移动端的接入,有很大的情况就是服务端生成了token,然后就断线了客户端(移动端)没有取拿这个生成的token,导致token会滞留并累计在redis,导致list会非常的长,每次读取的时候也会非常的慢,同时在读取redis数据到缓存处理的时候,使得两台服务器的流量出入呈现互补。

有人应该会问:不是设置了3分钟的时间周期吗?

是的,设置了时间周期,但是问题就在于这是单个list,如果有新的数据写入那么就会重新设置3分钟的时间周期,移动端访问的频率较高,所以如果有些数据时间周期快到了,这时新存入了一个数据,又给它续了一波命。后来我们改写了token的存储方式,还是设置了3分钟的时间周期,这次新数据存入时就不会影响其他数据的时间周期。


结论:

如果是多个数据都有设置时间周期,那么这些数据不应该存放到list里面,时间周期是对key来说的,单一的list在多个数据设置时间周期时会重置掉




你可能感兴趣的:(js工作笔记)