cover_image

餐饮与零售商品架构融合升级

宋志朋 SQB Blog
2024年11月29日 08:13

unsetunset引言unsetunset

随着消费者需求的多元化和市场竞争的加剧,零售和餐饮行业正面临前所未有的机遇与挑战。企业需要更加灵活和高效的系统来支持业务发展。在完成零售商品系统架构升级后,我们迎来了一个更具挑战性的任务:如何将餐饮商品系统优雅地融入现有架构,打造一个共享共建的统一商品平台。本文将深入探讨这一架构演进策略。

unsetunset第一阶段:零售商品的架构突破unsetunset

零售系统的架构升级是一次深度变革,不仅治理了技术债务,还为未来的业务扩展奠定坚实的基础。之前写过文章介绍:拆解零售商品架构的底层逻辑,感兴趣的同学可以看下

这里我们重点介绍下经过多轮技术迭代后在以下几个关键方向取得突破性进展

图片
  1. 业务解耦:通过领域驱动设计(DDD)重构系统,将庞大的商品系统拆分为多个独立的业务单元,如主商品类目库存供应商进销存搜索商家工具等,每个单元都有清晰的边界和职责,减少横向干扰。
  2. 领域模型构建:我们为每个业务单元抽象了稳定的领域模型,通过统一语言更好的表达业务。使得业务逻辑和复杂技术分离,提高了系统的可维护性。
  3. 服务标准化:我们将核心业务逻辑下沉到领域层,提供标准化的领域服务、仓储服务,使得上层应用可以更灵活地组合这些服务实现不同的业务需求。
  4. 数据结构优化:对底层数据模型的重新设计,实现更高效的数据存储和查询,如:使用 JSON 字段存储多维商品价格,引入 Elasticsearch 支持复杂查询等。

系统架构升级后,使得添加新功能或修改现有功能更加简单。比如 ,后续新增的 一品多码多包装条码秤自营外卖门店商品克隆 等业务功能,落地效率高,能快速适应不同的零售场景需求。

unsetunset第二阶段:餐饮商品的挑战unsetunset

在升级零售系统后,我们将目光转向了智慧门店中另一个重要的业务板块——餐饮。与零售相比,餐饮数据的规模更大,业务玩法更为复杂。目前餐饮的商品数量在 三千万左右,日均处理超过 300 万笔订单,在市场中占据着举足轻重的战略地位。

图片

然而,随着业务的快速发展、功能的不断迭代以及玩法的日益多样化,餐饮系统开始面临 "熵增" 的考验,系统复杂性不断增加,导致管理难度和维护成本急剧上升。经过代码分析,我们梳理出几个大的系统痛点。

图片

1、架构限制:餐饮系统采用的传统 MVC(Model-View-Controller)架构在初期快速开发时发挥了作用,但随着业务的复杂化,各个子域之间耦合度高,导致 "牵一发而动全身"  的情况频发。

2、服务边界模糊:单个 RPC服务内部,存在着严重的业务逻辑交叉现象。一个服务中充斥着 SPU、SKU、水位线、加料、口味做法、标签等多个业务子域的*manager*mapper方法,交叉调用导致服务边界模糊、职责不清,增加了代码的复杂度。

3、领域模型缺失:面向数据库表结构编程,业务逻辑散布在各层,难以进行有效的领域建模和业务抽象,代码复用率低,相似功能在不同模块中重复实现。

4、扩展性不足:比如:餐饮的商品缓存是一个超大的类,里面除了商品的基础数据,还包含加料、口味做法、标签、售卖时段、分类、原料等,任何一块内容的修改都会导致缓存失效。

面对这些挑战,我们认识到单纯对餐饮系统进行局部优化是不够的。借鉴零售系统成功升级的经验,一个更大胆的想法浮现出来:我们是否可以将零售和餐饮这两个看似不同却又密切相关的业务整合起来,构建一个更加灵活的统一平台?

unsetunset为什么要融合?unsetunset

尽管餐饮和零售服务于不同业务场景,但核心都是围绕商品展开。从业务维度分析,两者在多个方面具有共性特征,为系统融合奠定基础。

在基础属性上,两个领域都包含了商品名称商品图片分类售卖渠道单位售卖方式等基础属性,以及多维度的价格体系(如会员价售价成本价 等)。在业务流程上,两个领域都需要支持商品的创建、修改、上下架、置顶、排序、删除等业务操作。

图片

零售和餐饮商品的共性有很多,但也存在不少差异。首先在业务形态上,餐饮商品支持口味做法加料等业务玩法,同时还要考虑售卖时段套餐 等特殊场景。

而零售商品更注重标准化管理,需要处理多包装进销存供应商等业务场景,商品规格也更为规范,包含条码扩展条码。特别是在称重商品上,还需要考虑价格、单位的转换以及库存的精细化管理。

我们既要消除共性业务的重复建设,也要关注个性化业务的独立建设

图片

另外,在技术方面由于餐饮业务的起步较早,系统架构陈旧,而且系统是独立开发的,与零售系统没有共享底层架构,对于迭代的新业务,需要重复开发。

融合的核心在于识别和提炼零售与餐饮业务的共性元素,构建统一的、可扩展的商品平台。这不仅是技术层面的整合,更是对业务模型的深度重构。保持各自业务特色的同时,最大复用共享资源。

图片

unsetunset架构升级的实践之路unsetunset

考虑到架构升级的技术复杂性、风险因素和巨大的开发工作量,我们采用渐进式改造方案,将大任务分解为多个可控的小任务,以确保业务迭代和技术升级两条主线呈螺旋式演进实现整体升级。

整个升级过程分为纵向、横向两个维度。纵向维度关注上层流量入口的收拢,从网关服务到底层服务的贯通;横向维度则关注业务单元子域的优化和整合。

纵向维度升级

尽管内部代码结构复杂,系统仍然遵循HTTP协议的 “请求-响应” 原则。从链路追踪来看,客户端请求经由网关、基础服务、存储介质等多个环节,中间通过业务逻辑处理、数据转换,最终返回响应结果。

图片

业务网关(API)作为流量的入口,通过标准化接口规范与外部系统交互,有效屏蔽了底层的业务逻辑和实现细节。只要将网关 API 的接口规范标准化后,系统内部的优化相对自由些,而不受外部调用者的制约。

基于这一思路,商品引入融合网关,将餐饮和零售两条业务线的同质或相似服务进行整合,减少重复开发。

图片

融合网关内部定义统一的规范,包括业务 code、业务场景、操作人、门店id、业务参数等。当接收到外部请求后,根据配置好的路由策略,选择合适的执行器来处理相应的业务逻辑。

目前已经完成餐饮和零售商品的多个核心服务集成。比如:在商品管理,统一化实现 AI 助手创建商品、批量修改单位、商品上下架、修改描述等能力;进销存管理在设计初期就为餐饮业务预留技术扩展点,支持快速接入采购入库、退库出库、库存报损和库存盘点等业务,为两个业务线提供了一致的库存管理体验。

对于底层的基础服务,由于历史原因,餐饮和零售还是两套独立的系统,虽然可以确保每个业务线的个性需求能快速响应。但后面随着融合网关的成熟,会逐步迁移更多的相似服务到融合层,实现从上到下的全局化、统一化管理,进一步提升开发效率。

横向维度升级

在整个架构升级过程中,横向维度的改造是另一个重要方向。这个维度主要基于业务单元进行拆分升级,目前餐饮系统包含多个核心业务单元:主商品、加料、口味做法、水位线、商品标签、库存等。每个单元承载着特定的业务职责,但又通过复杂的依赖关系相互关联。

基于"农村包围城市"的技术改造策略,我们选择从外围的支撑域突破。经过深入评估,选择加料业务作为一期切入点。主要考虑到加料是餐饮最基础的支撑域,日均影响订单量达百万级别,系统改造后的收益明显。另外,加料系统的架构痛点具有很强的代表性,其改造经验可以快速复制到其他业务单元。

图片

在正式启动改造前,我们对加料系统进行了全面评估。经过代码走读和性能分析,发现系统存在以下典型问题:

1)架构层面。采用传统 MVC 模式,缺乏合理的领域边界划分,业务逻辑散落各处,如水位线逻辑在单个saveBatch方法中就重复出现4次,严重的代码耦合。

2)数据模型设计。虽然只有三张核心表(加料表、加料分组表、加料商品关联表),由于采用数据冗余的方式,导致任何一张表的字段变更都会产生连锁反应,增加维护成本。

3)性能方面。缺乏合理的上下文管理和逻辑复用机制,如 saveBatch接口中竟然包含 30 多次Mapper调用。频繁的数据库读写不仅增加接口的 RT 时间,也给数据库带来不小压力。

4)可维护性。系统遗留了大量历史代码,这些代码就像埋在系统各个角落的地雷,每次需求变更时都需要小心翼翼地评估影响范围,严重影响系统迭代效率。

图片

针对这些问题,我们采取以下改造措施。首先定义 DDD 领域模型并实现子域解耦,采用 “内部深化、外部收敛” 策略,通过领域事件实现加料和水位线的弱耦合。同时对表结构进行优化,清理 加料表加料商品表 中冗余字段,确保字段变更的影响被限制在单表范围内。

缓存方面,将原本耦合在主商品 Cache 中的加料数据独立出来,采用细粒度的缓存策略,避免加料变更导致所有关联商品缓存失效。代码层面,本着单一的软件架构原则优化 saveBatch 接口,将创建和修改操作分离,清理历史遗留的 “非标准” 数据,去除了大量兼容性代码。

考虑到餐饮线上有数百万的加料数据,为了确保服务平稳迁移,我们开发了灰度模块,支持 “商户标识”和“流量比例”两个维度的流量切换。在安全回滚上,我们开发逆向的数据回滚任务,支持全量、增量两种方式转换老的数据格式。最终将核心接口的 P99 RT 从20多ms优化到 9ms,数据库加料表访问减少 50%。更重要的是,完成与其他业务单元解耦,提升了后续业务的迭代速度。

图片

加料作为餐饮的支撑域业务单元已完成升级改造,接下来我们将逐步推进其他业务单元的升级,有餐饮的特色业务单元,如:口味做法、套餐、搜索等。也有跟零售商品融合在一起的中台商品基础业务单元。当然,考虑到每个单元的业务玩法可能不太一样,在方案实施上会有不同。但大的架构方向是一致的,采用 DDD 统一实体语言,提供企业级的中台领域复用能力,确保各个业务单元之间较低的耦合性。

unsetunset结语unsetunset

零售与餐饮商品的融合不是简单的系统整合,而是通过领域驱动设计,在保持业务特色的同时,构建一个更具包容性和扩展性的统一商品平台。这种演进式的架构升级策略,让我们能够在保证业务稳定的同时,逐步消除技术债务,提升系统的整体健壮性。

unsetunset关于作者unsetunset

宋志朋,来自智慧经营开发部

 

后端技术 · 目录
上一篇零售主商品MVC到DDD升级实践
个人观点,仅供参考
继续滑动看下一个
SQB Blog
向上滑动看下一个