优化 cache 的使用

为啥 cache 也需要优化

在优化代码之前,大部分小伙伴第一感觉就是加缓存来提升接口的响应性能, 这应该是优化的必备技能吧, 但是缓存没用好,不仅会带来线上重大的事故,也有可能出现性能问题。 可能有的造成重大灾难事故。在我的职业生涯中就碰到过两次重大的因为 redis 造成的重大灾难事故。其中之一就是因为缓存数据太大, 造成内存不足,监控又不到位造成一个公司核心服务出现故障,后来很多客服发来投诉,说我买了会员为啥我看不了东西。

前面提到这个遗留的审核系统有很多为了代码方便使用, redis 不当之处,这可能不是个例很多小伙伴喜欢用注释 @CacheEvict 或者自定义一个注解 @cache 之类的,然后在需要缓存的方法上加上,这样在调用方法时,只是会在 cache 中没有数据时再去查其他的库。这种做法本身是对的,可是就怕乱用,比如查出来的数据量很大例如一个大的 map, 然而使用的时候代码中用 for 循环使用到这个 map 去拿数据, 这时候就会出现性能问题。

而我们的遗留系统中就有这样一个问题,这里为了区分每个业务线及业务线下面的子业务对应着不同的查询条件, 所以了就建了一个任务表, 打个比方审核人员要去审核博客文章,那么有些审核人员可能专注于审核机审命中的文章,有些人专注于爬虫类的文章,还有的人可能审核来自用户自创文章,等等,总之为了区分每个审核人员对应的审核子业务线,里面会有不同的查询条件来获取对应的文章,因此为了区分在分发时的任务,那么就需要这样一张任务表来区分各自的分发任务,而且这个任务表可以把查询条件存储起来,供后面的质检回扫等功能使用,本身设计上是没有问题的,因为如果没有这个任务表,就需要根据不同的查询条件来区分子业务线,那么代码里会有一大堆的 if else。

说完这个任务表的背景,再来说说代码中是如何处理的,为了方便每个分发任务能够快速取得各自的任务表对应的查询条件,于是开发人员把这个获取任务表的方法用 @CacheEvict 进行修饰,代表我这个任务表会缓存到 redis, 要取任务信息直接到 redis 中获取,而不必再查 mongo 库了。注意这里他是把整个任务表的 map 都存储到 redis, 然而在使用的时候,一个业务线下面就有好几个分发任务,总的任务表有上 100 个,因此审核人员每次拉取审核数据时,都要循环去 redis 中获取这个大的 map。随着任务表不断增大,redis 访问频率会增加,redis 一次获取的数据也会增大,另外还有一个问题就是 redis 出现故障后,整个审核系统就没法审核了,这个事故在我来之后还真出现过,当时阿里云服务出现故障导致 redis 有小段时间连不上,审核人员有一段时间拉取审核数据都是白屏的情况。

另外 redis cache 在代码中还有另外一个使用不当的地方,就是分布式锁,我这里贴一小段代码,看小伙伴们是不是也曾经这样写过代码

RLock rLock = this.redissonClient.getLock(getKey(taskId));
try {
   
	# 1
    if (rLock.tryLock(3, TimeUnit.SECONDS)) {
   
    	# 2
  		doSomethingHere(...)
  	}
} catch (Exception e) {
   
        log
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值