大家好,我是姚半仙,慕课网《Java架构师成长直通车》课程架构师讲师团成员之一。接下来我带大家去实际的新零售业务场景里看看发布订阅模型的应用,从数据模型和缓存策略入手,了解存在的问题是什么。
新零售业务的商品模型
我们先来看一下商品中心后台的简化版数据模型
- 主商品 主商品保存了商品的主数据信息,比如商品名称、产地、规格、标品类型等等
- 门店 在新零售的概念里,线上线下要做整合,因此不论你是在线上购物或是线下门店购物,你所购买的商品都是来自于某个指定的“门店”来进行销售和配送
- 渠道商品 它是主商品的子集,渠道商品是下沉到具体门店的商品,它可以针对主商品的内容做定制。比如说有一件主商品叫“南汇西瓜”,当运营把它发布到10个门店上架以后,这个主商品就派生出了10个渠道商品。每个门店可以根据自己的销售策略,分别给这10个渠道商品设置不同的价格和营销优惠规则
简单来说,商品的数据模型就两部分,主商品(基础信息)和门店商品(定制信息),其中门店商品是需要发布到淘系主链路,和整个淘系中台业务做整合。
商品的缓存模型
为了帮助大家理解商品中心为什么需要发布订阅模型,我们再来看一下商品中心的缓存模型
不同于传统电商的单店商品结构,在新零售业务中我们要时刻考虑“门店”这个概念。在设计app端商品搜索的时候,我们会根据用户所在位置定位一家门店,然后通过主商品ID + 门店ID的方式请求渠道商品的详情页面,在这个搜索过程中渠道商品ID是没有传递到app端的,需要从后台缓存数据中获取。我们的缓存结构如下:
App在请求商品详情页接口的时候,会使用主商品ID+门店ID,后台服务需要根据这两个信息查询到对应的渠道商品ID。我们设置了两级缓存来存储数据,其中商品ID和门店ID作为一个Key,渠道商品ID作为对应的Value。首先尝试从本地缓存中获取渠道商品ID,如果没有查找到则去Tair缓存中查询,最后再去数据库中查询。
存在的问题
在实际应用中我们发现一个问题,当运营修改商品的核心字段时,比如将“规格”从100g变动到200g的时候,淘系主链路会把这个商品当做一个新商品,因此这个“修改商品”的动作就变成了“添加新商品”,这样一来原先的渠道商品ID就会发生变化,我们在本地缓存和Tair缓存中的数据就成了脏数据。
基于发布订阅的解决方案
针对这个情况,在每次运营修改商品数据的时候,如果侦听到主属性发生了变化,就必须要清空本地缓存和Tair缓存中所保存的该商品的数据。我们选择发布订阅模式来解决这个问题:
每次主商品发生修改的时候,会向MetaQ(阿里系的消息中间件)发布一条对应主题的消息,我们针对这个主题配置了一个广播和一个单播监听器:
- 广播组 包括所有商品详情页的后台服务节点,商品修改的消息将被每个服务节点消费,清空本地缓存的对应商品信息
- 单播组 单播消息只会被消费一次,用来删除分布式缓存中对应的商品信息。因此这里配置了一个消息组,保证消息只会被组内某一台机器所消费。
上面我们同时应用了广播和单播两种模式,我们将在下一小节详细介绍如何在Stream中通过消费组来实现单播。
学习Tips:在上面的业务中我们只关注了消息组件的应用,其实这里面还有很复杂的缓存处理逻辑,我在实际业务中加了不少额外逻辑来处理以下的异常情况:
- 缓存和DB更新失败后如何保证一致性
- 对热点商品的缓存移除操作如何避免缓存击穿
- 如何避免恶意用户使用不存在的主商品ID访问服务,导致缓存穿透
- 运营团队在短时间批量发布大量商品后,如何设置缓存过期时间,以免造成缓存雪崩
同学们可以想想以上情况如何应对,可以顺带着回顾下分布式缓存章节的内容。
共同学习,写下你的评论
评论加载中...
作者其他优质文章