专栏首页Java架构筑基阿里老司机教你微服务化后缓存怎么做
原创

阿里老司机教你微服务化后缓存怎么做

摘要


最近接手的代码中遇到几个缓存的问题,存在一些设计原则的问题,这里总结一下,希望可以对你有帮助

问题


问题1: 店铺数据的获取,将用户关注的数据放在店铺信息一起返回 对外提供的接口

List<Shop> getPageShop(final Query query,final Boolean cache);

返回的店铺信息

当调用方设置cache为true时,因为有缓存的存在,获取不到用户是否关注的数据。

问题2: 统计店铺的被关注数导致的慢SQL,导致数据库cpu飙高,影响到了整个应用

SQL

这两种代码的写法都是基于一个基准

不同的地方的缓存策略不一样,比如我更新的地方,查找数据时不能缓存,页面展示的查找的地方需要缓存。 既然服务提供方不知道该不该缓存,那就不管了,交给调用方去管理

这种假设本身没什么问题,但是忽略了另外一个原则,服务的内聚性。不应该被外部知道的就没必要暴露给外部

无论是面向过程的C,还是面向对象的语言,都强调内聚性,也就是高内聚,低耦合。单体应用中应当遵循这个原则,微服务同样遵循这个原则。但是在实际过程中,我们发现做到高内聚并不简单。我们必须要时时刻刻审视方法/服务的边界,只有确定好职责边界,才能写出高内聚的代码

问题分析


第一个问题,从缓存的角度来看,是忽略了数据的更新频繁性以及数据获取的不同场景。

对于店铺这样一个大的聚合根,本身包含的信息很多,有些数据可能会被频繁更改的,有些则会很少更新的。那么不同的修改频率,是否缓存/缓存策略自然不同,使用同一个参数Booleancache来控制显然不妥

第二个问题,这种统计类的需求使用SQL统计是一种在数据量比较小的情况下的权宜之计,当数据规模增大后,必须要使用离线计算或者流式计算来解决。它本身是一个慢SQL,所以必须要控制号调用量,这种统计的数据量的时效性应该由服务方控制,不需要暴露给调用方。否则就会出现上述的问题,调用方并不清楚其中的逻辑,不走缓存的话就会使得调用次数增加,QPS的增加会导致慢SQL打垮数据库

解法


缓存更新本身就是一个难解的问题,在微服务化后,多个服务就更加复杂了。涉及到跨服务的多级缓存一致性的问题。

所以对大部分的业务,我们可以遵循这样的原则来简单有效处理。

  • 对数据的有效性比较敏感的调用都收敛到服务内部(领域内部应该更合适),不要暴露给调用方, 领域内部做数据的缓存失效控制
  • 缓存预计算(有些页面的地方不希望首次打开慢)的逻辑也应该放在领域内控制,不要暴露给调用方。 在领域内部控制在不同的地方使用不同的缓存策略,比如更新数据的地方需要获取及时的数据。比如商品的价格,和商品的所属类目更新频次不同,需要有不同的过期时间。
  • 跨服务调用为了减少rpc调用,可以再进行一层缓存。因为这些调用可以接受过期的数据,再进行一层缓存没问题,expired time叠加也没多大影响(expire time在这边主要是影响缓存的命中数)

以上述店铺查询问题改造为例

扩展:如果后续有case在跨服务的调用时,对数据的过期比较敏感,并且在调用方也做了缓存,那就是跨服务的多级缓存一致性的问题。那就需要服务方告知调用方缓存何时失效,使用消息队列or其他方式来实现。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 用这四种套路更新缓存,你会少走很多弯路!

    看到好些人在写更新缓存数据代码时,先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中。然而,这个是逻辑是错误的。试想,两个并发操作,一个是更新操作...

    本人秃顶程序员
  • 面试官:你竟然不晓得Mybatis用了哪些设计模式?

    虽然我们都知道有26个设计模式,但是大多停留在概念层面,真实开发中很少遇到,Mybatis源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,能够更...

    本人秃顶程序员
  • 详解Spring的AOP切面编程

    AOP,面向切面编程,作为Spring的核心思想之一,度娘上有太多的教程啊、解释啊,但博主还是要自己按照自己的思路和理解再来阐释一下。原因很简单,别人的思想终究...

    本人秃顶程序员
  • 微服务化后缓存怎么做

    最近接手的代码中遇到几个缓存的问题,存在一些设计原则的问题,这里总结一下,希望可以对你有帮助

    方丈的寺院
  • Windows Server AppFabric Caching

    这套 AppFabric Caching 比我用过的 memcached 复杂多了,MSDN有一篇文章进行介绍Introduction to Caching w...

    张善友
  • CI框架网页缓存简单用法分析

    尽管 CodeIgniter 已经相当高效了,但是网页中的动态内容、主机的内存 CPU 和数据库读取速度等因素直接影响了网页的加载速度。 依靠网页缓存, 你的网...

    砸漏
  • java中常用的缓存框架

      Ehcache是一个Java实现的开源分布式缓存框架,EhCache可以有效地减轻数据库的负载,可以让数据保存在不同服务器的内存中,在需要数据的时候可以快速...

    java乐园
  • 中小型网站架构分析及优化

    老七Linux
  • redis缓存

    缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询...

    挑战者
  • 用Java写一个简单的缓存操作类

    使用缓存已经是开发中老生常谈的一件事了,常用专门处理缓存的工具比如Redis、MemCache等,但是有些时候可能需要一些简单的缓存处理,没必要用上这种专门的缓...

    beifengtz

扫码关注云+社区

领取腾讯云代金券