服务介绍
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 cache
5小时;server
的redis
存在的数据24小时,不存在的空值半小时(防止大量不存在的数据把Redis
搞崩,还可以更短一些) - 过期策略:
ExpiryPolicyBuilder.timeToLiveExpiration(Duration timeToLive)
按创建时间计时
优化后观察:
这次优化后效果显著,调用量就下降了90%,预计所有业务方改完后调用量还会进一步下降
优化前后对比:
审计日志优化
优化缓存的同时,增加了审计日志,可以用来分析业务方的不合理调用