记一次因redis使用引起的生产事故

由于个人接触过的项目数量较少,且偏向B2B的较多,在B2C的项目上缺少一定的经验,也为此次的坑埋下了隐患。

一、项目背景:

B2C的商城项目,但从功能上来说并不复杂,且初期没有活动、折扣、抢购、秒杀等功能,只是简单的商品购买与管理流程。

参照了之前做过的商城项目,沿用了相似的框架,由于规模并不大,因此只是采用了spring boot+mybatis作为常规的开发框架,使用redis作为缓存,初期使用jedis连接,在前期遇到问题后变更为lettuce。

 

二、遇到问题:

可以说是确实的生产事故,项目上线即夭折。

前期错误地预估了商城的商品量,导致在代码以及缓存的处理上存在一些问题,在并发较高(实际上刚开始并不高)的情况下,直接导致大量请求无法获取到redis的连接,且一直处于等待,在持续几分钟后,进程直接挂掉。

奇怪的是,在遇到问题后的性能测试阶段,即使并发量不高,且遇到无法拿到连接的情况,立即停止压测,redis的连接也没有被归还,导致连接池一直被占用,系统迟迟无法恢复正常状态。

1、商城端存在大数据量反序列化

在经过测试以及检查代码后,发现商城端,用户访问频率较高的接口,对redis缓存有大量的取操作,这本身的影响并不大,但在数据量较大的情况下,对取出的数据进行了反序列化操作,这一步实际上是相当耗时的。

2、大集合的removeAll()操作

在经过一行一行的debug后,发现代码中存在两个list的removeAll操作竟然耗时数秒钟的时间,在百度后发现,在list的量级到达一定时,removeAll确实存在一定的效率问题(百度结果是10W级别的list去removeAll 1W级别的list,但实际上应该没有那么多的数据,但确实耗时较长,数据量还有待考证)。

解决方案:在数据量无法减少的情况下,将一个listA转换为setA,对另一个listB进行迭代,如果setA.contains(B),那么从listB中remove,大概是那么一个处理逻辑。

Set<Long> noStockItemSet = new HashSet<>(noStockItemIds);
//采用Iterator迭代器进行数据的操作
Iterator iter = onShelfItemIds.iterator();
while (iter.hasNext()) {
if (noStockItemSet.contains(iter.next())) {
iter.remove();
}
}

3、存在hgetall操作

由于前期没有考虑到数据量的问题,因此redis中存在的一个hash结构的key,其中有万级别的hashkey,这本身问题并不大,但是每一个hashkey对应的value占用的大小产生了问题,本身大概每个value在10kb左右,数据量小的情况下并不会出现问题,但是当数据量大起来,并且使用hgetall操作时,操作就会相当耗时。

当另一个相关的缓存被击穿时,方法会去掉用hgetall,从redis中全量取得该hash结构的values,并且构建另一个缓存以供下一次查询,请求并发较高时,所有与redis有关的操作全部在等待,直接导致进程挂掉。

 

本系统进程挂掉的原因,应当主要是在第3点,没有考虑到大数据量从redis的存取,以及高并发时的处理。

但是在实际测试的过程中,偶尔会出现redis连接没有归还,且配置了redis超时时间的情况,进程久久无法恢复正常,最后还需要定位该问题的原因。

 

三、尝试解决:

实际上系统最后已知的问题,还是在于缓存失效时,同一时间大量请求并发进入,导致大部分请求都直接访问数据库或者去调用第三方接口,而在这些步骤之后又会去全量更新redis的某个key,所以同一时间redis数据库以及http的请求都卡在那边,然后系统直接崩溃了。

还是由于自己没有太多toC项目以及这种情况的处理。

最后的解决方案其实并没有特别完善,但是暂时可以避免系统崩溃的情况发生。

1、优化代码

代码上的优化其实不用多说,主要是一些反序列化的地方,能改则改,也能稍微提升一点速度。

2、加入本地缓存

利用ConcurrentHashMap加入了最基础的本地缓存,能够稍微减缓redis的压力,并在系统启动时预热一部分数据,添加到本地与redis缓存中。

3、优化redis处理

原本redis在处理上存在一些问题,设计之初,在后台修改过相关数据后,会直接删除redis中对应的key,想让用户访问时从数据库或其他地方取出值后再重新维护redis中的值,这也直接导致了问题的发生。

之后暂时改成了定时任务去维护redis中的对应的key,使得redis或者本地缓存中,必有一方是存在数据的,在用户使用的过程中无需从数据库或其他请求去获取,但是问题是会导致系统的实时性出现一些问题。

 

posted @ 2019-09-30 14:18  糖醋小灰  阅读(583)  评论(0)    收藏  举报