服务介绍
bizconf服务是公司所有业务的通用配置服务,用来保存所有企业、以及用户的业务配置。分为三个级别的配置,系统级、租户级和用户级。
背景
之前就有发现bizconf调用量比较大,需要优化缓存来降低调用,而最初现状是只在server端有Redis缓存
问题爆发点:元旦前最后几天,数据库负载高,导致bizconf服务调用耗时从几毫米升高到 20~30 毫秒,这时客户反馈系统库卡顿、反应慢,经过排查发现调用耗时长的请求和bizconf耗时曲线一致,各个业务都用调用bizconf,还有的业务调用多次,bizconf耗时上涨导致整个系统卡顿
优化目标
在client添加jvm cahce来降低调用,从而做到服务降级,前后共经过俩次优化,第一次优化因为缓存穿透的原因效果不明显,第二次优化后效果显著
优化前调用量:
第一次优化
优化范围:在server和client中添加jvm cache
使用缓存:使用caffeine cache,分级缓存,在server和client中分别添加两个cache,企业级和用户级的cache
缓存设置:
- size:
server中cache size为50000,client中cache size为5000, - 过期时间:一个小时
- 过期策略:
expireAfterAccess(long, TimeUnit)按最后访问时间计时 - 基于引用:
softValues()设置为软引用
优化后观察:
观察发现虽然添加了jvm cache,但是调用量降低的效果不明显,甚至可以说无效果
又观察Redis调用量和db调用量,发现db调用量和Redis调用量差不多,少的很有限,这时觉得这种情况不对,怀疑发生了缓存穿透,缓存没有生效
Redis和db调用量:
经过排查发现一些数据多次的访问数据库,询问对应业务,是在判断企业的某些状态,如果返回false或不存在则认为没有,至此问题定位,缓存穿透导致大量访问数据库,从而解释了为什么优化的效果不明显
针对缓存穿透有了下面的第二次的优化
第二次优化
针对缓存穿透一般有两种处理方式:使用布隆过滤器和缓存空值
布隆过滤器
布隆过滤器具体可以参考https://blog.csdn.net/yuanlong122716/article/details/104402602
布隆过滤器有两个非常重要的缺点:
- 存在误算率,虽然不会错判但是会误判,什么意思呢,返回不存在则一定不存在,返回存在但是并不能判断一定存在
- 不可以删除
如果使用布隆过滤器则有两个场景,保存白名单和黑名单:
- 白名单:如果保存白名单,需要把数据库中所有的数据(表示存在的逻辑true)都保存起来,并且新增时需要同步的维护布隆过滤器数据,但因为是分布式服务需要保证所有服务都同步的维护布隆过滤器,难度比较大;同时布隆过滤器不支持删除,所以不考虑使用白名单
- 黑名单:如果保存黑名单,把不存在的数据保存起来,但因为会有误判,可能会把存在的数据认为不存在从而返回了空,从而使数据错误,所以不可取
分析考虑,不采用布隆过滤器,采用缓存空值的方法更为有效和简单
缓存空值
优化目标:
优化范围:在client中添加jvm cache,在server中只使用Redis cache
使用缓存:第一次优化时client端缓存的数据有限,这次决定使用ehcache,可以缓存更大的数据量,同样也是分级缓存
缓存设置:
- size:每个
cache堆内存5000条、堆外内存1MB、磁盘50MB - 过期时间:
client的jvm cache5小时;server的redis存在的数据24小时,不存在的空值半小时(防止大量不存在的数据把Redis搞崩,还可以更短一些) - 过期策略:
ExpiryPolicyBuilder.timeToLiveExpiration(Duration timeToLive)按创建时间计时
优化后观察:
这次优化后效果显著,调用量就下降了90%,预计所有业务方改完后调用量还会进一步下降
优化前后对比:
审计日志优化
优化缓存的同时,增加了审计日志,可以用来分析业务方的不合理调用