复杂场景下缓存的实际应用

背景

在开发CNSC时,业务要求,在子账号登陆该站点时,显示的菜单全集=shop菜单并集+merchant菜单。即

image.png

业务诉求

1.首页菜单作为站点里最重要的基础功能之一,必须满足可用性的要求,且响应时间不能超过3s,否则会严重影响用户的体验。

2.用户需要尽可能快(最开始是希望能实时)地感知到到菜单的最新状态变更,假如添加了一个菜单,或者某个店铺的权限发生了变化等。

现状及存在问题

1.cnsc的每一用户拥有的店铺数差别较大,少的可能只有几个,最多拥有五千个店铺。

2.菜单逻辑本身逻辑较为复杂,每一菜单(子菜单)都可能设置了对应的feature toggle 和auth code。每个店铺的toggle属性和auth code也都不一样。菜单本身也会变动。

3.由于牵连的关联方较多,任意关联方的变动,都会导致菜单本身的逻辑发生改变。有一些变更我们也无法感知到。

4.在不做并发获取相关资源的前提下,菜单计算时间和店铺数成正比,超过一千个店铺时,单一接口返回时间都超过3s了。

5.由于CNSC用户初版无法统计出热点用户和用户习惯。所以针对所有用户菜单做缓存,缓存数据的离散性会很高,命中率会比较底,一旦没命中缓存,菜单返回时间就会大大增长。

解决思路

  • ~~缓存所有菜单,最开始的时候就拿到所有的用户全集,同时对所有用户的菜单进行计算并缓存,后续定期有定时任务去不断刷新用户缓存。 ~~

        否定原因:1.暂时无法获取到用户全集,且如果用户量较大,定时任务计算频率不好制定,担心一轮还没计算完成就开始要开始新一轮的计算了。
    
  • 缓存所有菜单,最开始预热部分活跃用户,同时感知到所有可能导致用户变更的变化,由这些变更的内容出发异步任务去计算菜单更新。

        否定原因:1.没办法感知到所有的变化,异步任务如果出错,同样会出现接口返回缓慢,甚至一直更新不了用户菜单的情况。
    
      。。。
    
      。。。
    
  • 实测得出不同店铺数的用户的菜单计算时间,基于不同的响应时间设计不同的缓存方案。在有缓存和无缓存的情况下的实际逻辑也分情况处理。

      选取原因:在技术和业务上有一个较好的平衡,不会浪费太多缓存空间,方案可行性强、相对较为稳妥健壮。对于绝大部分用户来说体验也不会太差。 
    

否定和提出新的方案的过程,也是不断和业务battle的过程。

实际设计

1.对应接口缓存和批量查询接口的实现。

2.全量菜单缓存,其它的数据需要的时候再计算出来。

3.根据不同店铺数,设计不同的方案。

4.有任意进程更新缓存时,其它进程就不需要再浪费资源一起做更新了。(通过标识位+5min的计算时间同时决定)

5.计算后的菜单进行缓存,物理过期时间为30天,逻辑过期时间为30min,强制缓存更新计算时间为35min。

image.png
image.png

总结

在实际的场景下,特别有时候在复杂业务的场景下,并没有一种普适的缓存策略或通用方案可以完美符合相关需求的。更多的时候,还是要根据具体的场景分析来决定具体使用的方案,有的时候,甚至会混合几种方案一起使用,根据不同情况应用对应方案的不同细节设计。

例如上述的cnsc 菜单缓存方案,其实也并没有完全应用cache aside的方案,同时也用到了write back方案中的异步更新的思路。

每个方案都有每个方案的优点和缺点,根据业务需求的属性,具体分析并能找出合适的方案,才是最重要的。

其它场景

Gateway的路由数据:缓存穿透、缓存雪崩。

设计:更新redis缓存加锁。本地缓存随机过期。多级缓存。

image.png

最新的方案

不再由请求触发local cache,是有一个异步的定时任务去触发更新?更像是一个write back的缓存策略?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容