将最近遇到的redis问题总结一下:
1.问题描述
程序从redis里面获取数据,时有时无,概率一半一半
2.问题分析
最近开发遇到了从redis里获取数据时有时无的现象,开始以为是redis出了问题,由于赶上运维重新搭建测试环境,同时又是在测试环境中遇到的,就没太在意,想着用新环境就好了,过来几天将代码移植到新的测试环境中,发现现象依然存在,就和运维描述了一下问题(当时还是以为是redis系统方面出了问题),后来将代码部署到线上测试环境,发现问题依然存在,这个时候我就警觉起来了,开始怀疑是程序方面出了问题,然后开始了代码排查,开始由于固定思维模式,并未发现什么问题,获取数据这块的代码也并未改动过。十分的不解,然后开始仔细回忆bug最开始出现的时间以及在什么模式下会出现,最好锁定是新增的一块功能后,这个bug就出现了(和这块没什么关系),不甘心,继续调试,发现出现问题的时候,从redis榜单中并未获取到数据(正常的是获取到数据的),因为从配置上看是从同一个redis源拿的数据。继续往深了调试,发现取数据之前要验证一下redis key的type 出问题的时候type为none(没有这个redis key),找到问题了松了一口气,然后怀疑是redis 没判断出来,以为是redis的bug(怎么也没想到是redis 串库了)。后来查资料,网上并未找到这个redis bug的相关文章,这就令我百思不得其解了。
后来为了验证是这个版本的代码有问题,就从线上拷贝了一份代码放到线上测试环境,一看并未出现问题。
代码问题,代码问题,代码问题,重要的事情说三遍。
慢慢排查代码之路开始了,灵光一现,在获取redis对象的时侯查验一下对象的ip和端口,不就能确定是不是同一个源了吗,说干就干,经过调试还真发现不是同一个源,redis 串库了。
又开始回想,这个版本增加了什么,代码一行一行的排查,发现是一个方法里面获取某个redis 对象用完后
returnResource 的时return 错了,获取了两个redis Resource ,用完后returnResource return错了。
(大家都知道jedis用完要释放,不然链接用完了就出问题了)
看下面事例代码:
Jedis Jedis1 = jedisPool1.getResource();
Jedis Jedis2 = jedisPool2.getResource();
try {
xxxxx
}catch(Exception e){
}finally{
jedisPool1.returnResource(jedis2); //正确的是return jedis1的 结果写成了jedis2
}
3.解决问题
正确的pool 对应正确的jedis
总结:这个问题本来就不是问题,但由于粗心大意(粘贴复制)写错了东西,导致了这么严重的问题,因为之前也没遇到过串库的问题,所以一开始根本就没网那方面想,不过庆幸的是通过一番努力找到了问题的根本原因,也算积累了经验。
最后再次强调一现,redis数据文件一定要记得备份,备份,备份并定期检查数据备份是否正确。
因为最近亲身经历一次线上redis数据丢失的情况,情况是这样的当运维调整网络后,把redis机器
重启了一下(当然是在晚上11点后了),起来之后发现数据丢了(文件被重新写入了),然后立马去从机拷贝数据,结果从机上根本没有数据,顿时傻了,原来运维在配置主从的时候配置错了,导致从机并没有备份数据并且主redis上数据持久化配置的也有问题,导致重启机器后数据被冲了,无奈没办法,连夜赶到公司从数据库里恢复数据到redis,幸好这个redis刚上线没多久,数据量也不大(几百兆),比较容易恢复。
教训:
操作nosql数据库一定要小心再小心,备份再备份。