前言
本文章只是个人心路历程,只是给予个人的思考思路。并不是绝对的正确答案。
例如
是的主要事情发生在今天,本在百无聊赖之际,想完善一下过去的写的一个小工具类。@Cache与@CacheClear注解。
public @interface Cache{
}
public @interface CacheClear{
}
比如我今天有一个业务,显示某个商品的详情页,详情页上需要商品的名称,点赞数,评论数,库存数等等。
因此我创建了一个接口显示详情数,并且将我的缓存@Cache 加入
@RequestMapping("details")
@Cache
public Object details( String goodsId ){
return details;
}
这样我们就可以轻松实现了一个缓存操作。 但是缓存数据存在风险,例如每次商品的购买都会左右着购买的数量,如果我在购买完成之后不清除掉缓存,因此我们就在购买数量的接口上另写一个接口
@RequestMapping("buy")
@CacheClear
public Object buy( String goodsId , Long userId ){
return result;
}
这样我们就完成了我们的缓存失效功能。 但是我又很快发现,这并不是问题的解决,而是问题的开始。 我们发现,会影响数据的接口并不单单只是这一个方面。还有许许多多的方面。
- 例如,点赞数,评论数,甚至可能出现的点击数。这些都是导致缓存失效的因素,这样我们就不得不在与这些想得到的,想不到的所有相关接口上都加上@CacheClear,杂!
- 其次这些接口可能不单单只是跟获取奖品详情的缓存所相关,将来,我们不难想象这些接口上面可能会有长长一排的@CacheClear,乱!
- 会影响库存数量的因素,可能不单单来自于APP端的后台服务器。商户端以及管理端随时都可能给键盘添加库存,你就需要将这一套代码逻辑迁移到其他平台的服务器,烦!
最后哪怕我们不嫌杂,不嫌乱,不嫌烦。处理完这些,我们就发现我们的代码就是一片雷区,在后期的修改之中哪怕一个小错误都会导致BUG的出现。 因此,最后无奈的我,只能将前面花了一个多小时写的代码,全部回滚。
另外提一嘴,我觉得给商品数,点赞数有关的因素加缓存的确挺扯淡的。
思考
在经历了失败之后,我便开始了思考。 我认为《三体》之中有一个思考问题方式挺不错的,叫做给一个事件下定理。 因此我也模仿了这个规则,给缓存下了定义
- 被缓存的数据,应该是需要一个相对高的性价比去得到的
- 被缓存的数据,应该要有请求压力
最明显的例子,就在于我们对于APP端与后台管理端使用缓存的普遍出发点。 主要就是因为从这两点出发 客户端由于用户多,因此存在请求压力 后台管理端,由于需要对当前的数据进行处理分析,满足第一条
缓存数据也不单单只有一种,它也主要因为缓存的数据需不需要同步处理,而“动”数据与“静”数据。 “动”数据:被缓存的数据由于业务的原因需要进行被动或者主动的修改。 “静”数据: 被缓存的数据,无需进行手动的修改。被缓存的数据存在一个周期性的失效时间。
如何实现呢?
定义完概念之后,我们回来实际一点的按例之中。 就比如说,我们团队要做一个上文之中说到的物品购买的电商系统。 那么我们现在就要考虑,我们如何实现我们的功能呢?
对于静缓存来说 , 这很简单。可以简简单单的通过一个缓存操作便可以完成。 剩下的便是大难题,动缓存。 对于动缓存如何解决,相信不少看过其他文章的人都知道,主要概念就是数据库Redis保持同步的架构理念。大家如果想知道详细内容与理念可以去搜索一下,阿里社区与腾讯社区等一系列社区几乎都有文章讲解实际理论。 那不讲理论,我们就讲讲如何实现吧。 相信看到上文的同学都知道,我们不可能吧实现“同步”的理念分散到各个业务接口里面去。这非常难以管理我们的代码。 那么既然接口不能管理,那么我们就只能把代码写在一个Service里吧
@Service
public class GoodStockSerivce{
public Integer getNumber( String goodId ){
}
public boolean add( Good good ){}
public boolean reduce( String goodIds ){}
}
当然上面只是一个展示而已,实际操作大家可以看看实际情况。 但是理念都是一样的,任何需要修改库存的操作 , 最后都要调用这个 GoodStockService 内部的方法。 用代码的强规定,来保证缓存的强一致。 那么假设自己的分为不同的服务呢? 那么方法也有两个
- 将库存修改的操作,也变为一个服务。提供给不同的服务调用
- 代码复制到各个不同的平台
我们不难看出,对于动缓存的操作概念。他是需要一个专门设计的架构与开发约定的。 要完成这个需要一定的开发量。 其次,这个也不是一个人的事(当然除非你们的任务分配是一个人完成一个功能点的所有开发),动缓存的制定,他可能不是一个接口,一个模块,一个服务,一个系统的共同努力。他就像一个社区 , 需要这个社区的所有参与者都要努力,才能保证这个社区的正常运作。不然,自己在那里再努力的埋头开发,结果其他人没有引入你的概念。哪怕是一个人,你的动缓存在理论上,也会出错。【那时候,满地图找错误的感觉真的让人上瘾】
这种规约的设立,基本上是需要目标缓存业务开始之初就引入的。一般来说越早越好。当然,如果项目初期,你们所在的团队或公司,没有这方面的技术沉淀。并且,似乎也还没有这方面的意识,以及需求的话。这种就是要晚到底了,等到业务有对应的需求,或者线上有这方面的压力的时候。团队这时候再制定计划。 当然,如果你自告奋勇要提出这个理念,那是另外一回事。
那么对于我来说
简单说,他不是一个人的事,需要让团队内的人达成共知。 这种规约的设立,基本上是需要目标缓存业务开始之初就引入的。一般来说越早越好,而对我来说,只能说由于各种的不可抗力,我最后只能在当前项目之中放弃了对动缓存的概念。 因此,我将我的视野投入在了静缓存上。 然而我很失望的发现,对于当前项目来说,静缓存的可用之处是并不多的。 当前的项目前后端通讯方式,都已经是RESTFUL API了,简单来说,就是最基础的通讯原子数据。 对于这类型的数据,静缓存能使用的场景就很少了。 (说实话,我引入谁?引入商品的详情嘛?靠唯一索引查的东西,我实在想不出理由给他造一个缓存) 能引入的场景,似乎也只剩下了主页与查询页,热门商品评论等等**“不太好查”并且“实时性”**要求不高的数据了
|