分布式缓存技术方案

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一、背景

在高并发的分布式的系统中,缓存是必不可少的一部分。没有缓存对系统的加速和阻挡大量的请求直接落到系统的底层,系统是很难撑住高并发的冲击,分布式系统中缓存的设计是很重要的一环

使用缓存的收益:

●加速读写,缓存一般是内存操作,要比传统数据库操作要快的多

●降低后端的负载。缓存一些复杂计算或者耗时得出的结果可以降低后端系统对CPU、

IO、线程这些资源的需求

●本地缓存远端调用结果,减少服务间的调用,提升服务并发能力

目前问题:

●目前业务中对缓存的使用并不多,在这次直播活动中,组件性能瓶劲很多,有很大一

部分是可以通过缓存加速的

●疫情直播活动期间,几个核心服务由于人手、改造难度问题等,最后由罗陈珑做一了

个缓存代理服务,把UC、EOMS的部分接口做了缓存代理,这些缓存本来应該由服务提供者来实现的

●数据一致性问题,加了缓存之后,随之而来的就是数据一致性的问题,发现有数据不

能及时更新

●目前大家对缓存使用方式不太统一,有的组件使用本地JVM缓存时封装太复杂,出现

问题不好定位,清除缓存也不好做

二、目标

●降低分布式缓存技术使用门槛,将分布式缓存框架作为微服务开发必备的脚手架,让

开发者更易使用,避免因技术门槛而放弃使用缓存

梳理核心业务,使用分布式缓存加速服务响应速度,降低服务负载

三、分布式缓存方案

3.1 @WafCacheable 缓存

3.1.1 分布式缓存和本地jvm缓存

为了提高接口能力,需要将一些频繁访问但数据更新频率比较低的放入缓存中,不要每次从数据库或其他耗时耗资源的数据源中取。使用@WafCacheable 注解,缓存过期时间可以根据数据更新频率自由设定,不设置默认为2小时。 @WafCacheable 标记的方法被拦截后,数据获取的优先级:本地jvm缓存>redis缓存> 数据源(DB、RMI、其他耗时耗资源的操作)

@WafCacheable

使用场景:高频访问低频更新的数据

注意:@WafCacheable 对同一个类里的内调方法(A调B, B上加注解不生效),如果直接用this.B(),加在B上的缓存不生效,需要使用${service}.B()调用(${service}指service实例)。

3.1.2 RMI缓存

RMI(Remote Method Invocation)是指微服务提供的SDK中FeignClient方式申请的接

口,具体参考

/noteshare?id=dda3f2af3976689339c9ffa5ba0b0675 RMI上也可以加@WafCacheable注解。

使用场景:对于数据变化频率在2小时以上的,为了减少服务端的请求,提高接口性能

缓存方式:本地jvm缓存

作用域:客户端/消费者,拦截的包要注意,只拦截以下规则的包命名

建议RMI上缓存时间不要超过同一接口service上的过期时间的1/2, 最好设置为1/4.

3.1.3 关闭缓存方法

1)配置文件中修改

●在application.yml中加入

waf:

cache:

enabled: false

注意:生产环境禁止关闭缓存

●调用rest接口关闭当前结点缓存

2)管理接口动态设置

3.1.4 缓存配置

默认情况下缓存是开启状态,缓存队列大小3W,单个对象20K以下会放入jvm,否则只放入redis,当然也可以通过缓存模式可以强制指定放入jvm.

application.yml 配置:

waf:

cache:enabled: true #控制缓存开关max-object-siz e: 30 #缓存单条对象最大上限大小,单位k b max-queue-si ze: 20000 #缓存队列上限

3.1.5 缓存注解的使用

3.1.5 手动使用缓存

CacheService是封装了jvm缓存和redis缓存,在使用sdk操作缓存时,会同时往jvm和redis都放一份,部分api支持对象大于设置的单个对象大小上限可不放jvm. RedisService封装redis的基本操作,包含分布式锁的操作。

3.2 缓存清除/数据一致性问题

缓存能极大的提高系统负载能力,但同时也引入新的问题,数据一致的问题,当一个业务规则或缓存的源数据发生变化时,一般要求被缓存的数据也需要立即更新为最新的数据(少数场景是对数据实时性不敏感或有一定的容忍度)

3.2.1 缓存清理的难点

●缓存key不确定。

通过@Wafcacheable注解设置的缓存,缓存key的生成策略为如果设置了自定义key 的前缀,则使用自定义key前缀+各个参数拼接而成,如果没有设置自定义key则使用包名+类名+方法名+各个参数拼接而成。

●缓存存在多个节点中。

缓存不仅有微服务提供者内部缓存,还有客户端(消费端)的缓存,一般是在rmi通过@Wafcacheable设置的。缓存既有jvm缓存也有redis缓存。 jvm缓存存在于每个application中。

这样意味着需要清除所有微服务节点内部的jvm缓存及redis缓存,包括客户端(消费者端)缓存。

3.2.2 LRU+TTL算法缓存更新

在被动更新缓存上是采用LRU+TTL组合算法实现缓存更新,也就是说只要缓存达到任一清除条件(缓存过期或LRU)都会被清除

LRU算法,当缓存容量不足时(控制了缓存上限,避免OOM),淘汰最久没有被访问过的,始终保持热数据的缓存命中率

TTL算法,也就是超时剔除,给缓存数据手动设置一个过期时间,当超过时间后,再次访问时从数据源重新加载并设回缓存期,

3.2.3 主动通知缓存更新(立即生效)

由上层应用在配置更新后,通过MQ消息通知给微服务,微服务各应用节点以广播消

相关文档
最新文档