亿级交易平台:从 0 到 1 设计思路

点击上方“芋道源码”,选择“设为星标

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 8:55 更新文章,每天掉亿点点头发...

源码精品专栏

 

本文主要介绍每日优鲜五年来交易平台实践的心路历程

一、前言

1.1 每日优鲜简介

每日优鲜定位于自营全品类线上综合超市,成立于2014年11月,致力于让每个家庭买得省心,吃的放心。目前,每日优鲜已经完成水果、蔬菜、肉蛋、水产、乳品、零食、速食、饮品、轻食、粮油、日百等全品类布局,通过首创的生鲜到家“前置仓”模式,在中国16个城市为数千万家庭提供“3000款商品,最快30分钟送达”的服务。凭借着上游供应链和智慧连锁核心能力上的长期投入,每日优鲜业务规模已超过百亿。2020年7月,每日优鲜完成由中金资本领投的4.95亿美元融资,在生鲜电商细分领域,市场份额、营收增长、用户规模以及盈利能力均保持行业第一。

1.2 交易平台简介

跟大多数互联网电商一样,随着公司业务的发展,每日优鲜也陆续拓展出了多业务线(极速达、云超、厂家直送、便利购、菜市场等)。各业务线发展初期,为了快速跑通MVP,组建临时团队、从0开始搭建系统,但这就导致烟囱式系统林立、数据相互割裂,不仅成本高企,也为业务整合带来困难,技术架构从烟囱式系统走向平台化架构成为必然选择;对交易系统来说,各业务形态的订单数据模型差异不大、交易业务流程类似,构架一套交易平台来支撑多业务形态的交易业务具有可行性,因此“每日优鲜交易平台”应运而生。目前每日优鲜交易平台拥有数十亿的海量订单数据、能够稳定地支撑公司数十种业务形态、也能够在3天内高效支持新业务的接入。

二、背景

2.1 没有交易平台时面临的困难是什么?

2.1.1 成本高企

各业务团队都有交易系统,重复造轮子,造成运维成本、研发成本的浪费。

2.1.2 数据割裂

各业务团队的订单数据的割裂存储、数据模型的不统一,造成依赖于订单数据的大数据、财务、客服等服务为了适配不同数据模型,冗余了大量的适配逻辑和兼容逻辑,增加了这些系统的复杂度;复杂度的增加,不仅仅是沟通成本、研发成本的增加,也降低了系统稳定性。

2.1.3 业务迭代需求响应慢

交易系统功能定制化,抽象性、扩展性、复用性都较差,需求响应慢,影响业务迭代效率。

2.1.4 创新业务试错成本高

创新项目不能利用现有交易系统,只能组建临时团队,搭建新的交易系统,拉高了试错成本。而较高的试错成本,会阻碍创新项目启动的机会,延误商机。

2.2 交易平台要解决的核心问题是什么?

2.2.1 什么是交易平台?

交易平台是支持多业务形态下的正向、逆向交易流程的一套软件系统。它具有较高的数据模型抽象性、业务功能抽象性,通过对基础功能(能力域)的配置化流程编排,可支持差异化的业务流程,也可快速支持新业务;能够隔离业务间的相互影响,保障多业务平稳运行。

2.2.2 交易平台要解决的核心问题

2.2.2.1 效率问题

如何快速支持业务需求?说到底就是如何抽象数据模型和业务流程,提高系统的扩展性和复用性,包括如下几个面向:

  • 不同业务形态的数据模型的差异如何存储、传递?

  • 不同业务形态的功能的差异如何处理?

  • 不同业务形态、不同类型的订单,业务流程差异如何支持?

  • 如何定义和管理不同业务形态、不同订单类型?

2.2.2.2 稳定问题

如何保障系统平稳运行?包括系统稳定性和业务正确性,具体面向如下:

  • 多业务在一套系统运行,存在相互影响的可能,如何避免?

  • 出现问题如何快速定位?如何确定是哪个业务出了问题?

  • 业务的正确性如何保障?如何快速主动发现问题?有问题的数据如何快速修复?

2.2.2.3 性能问题

作为交易系统,管理海量正向数据、逆向数据的读写,如何满足C端、B端的读写性能要求?具体面向如下:

  • 海量数据怎么存储才能保证读写性能?是否要分库分表?

  • 多维度的复杂查询如何支持?在分库分表情况下,如何支持复杂查询?

  • 读写流量如何避免相互影响?

  • C端、B端流量如何避免相互影响?

2.3 交易平台的价值

2.3.1 降低成本

收敛各业务团队的烟囱式交易系统,降低运维成本、研发成本。

2.3.2 提高效率

高扩展性、高复用性,对内对外大幅提高研发效率。交易平台自身对接新业务需求仅需3天;数据模型的统一,降低大数据、财务等外部关联服务的复杂度,提高的这些关联服务支持新需求的效率。

2.3.3 业务赋能

创新项目可以低成本跑通 MVP,降低试错成本;体现技术驱动业务发展的能力。

2.3.4 标杆系统

交易平台率先完成平台化,对标行业领先;随着交易平台的价值的逐步体现,在公司内部树立标杆形象,促进达成建设平台化架构的共识,引领兄弟部门平台化建设的步伐;最终形成业务中台化,打造全链路的高效、稳定的业务赋能能力。

三、技术实现

3.1 业务架构

交易平台承接各业务前台的交易应用的请求,依赖商品、营销、支付等基础服务,处理各业务形态的正向交易、逆向交易,具体业务包括正向交易、逆向交易、履约分发、订单中心、数据处理、运营工具、公共组件等。

图片

3.2 系统架构

按照功能,交易平台内部系统划分为4层,包括存储层、数据处理层、业务层和应用层。其中业务层按照订单生命周期划分为生单模块、支付模块、履约模块、逆向模块以及查询模块。

图片

3.3 技术保障

3.3.1 差异管理方案

3.3.1.1 业务身份定义

作为平台化架构,定义业务身份是首要任务。业务身份的定义,是用于区分不同业务、不同品类的差异功能,是业务管理单元;需要定义一套合理且具有扩展性的业务身份方便业务管理。基于业务场景,我们使用3个维度定义业务身份:

  • 业务线:区分不同运营团队所运营的业务,比如主商城、便利购、开放平台等

  • 渠道:同一个业务线,有不同的流量渠道,比如便利购业务下有普通柜、智能柜等

  • 订单类型:根据商品类型、履约形态的不同,定义不同的订单类型,比如极速达订单、云超订单等

图片

3.3.2 扩展性方案

3.3.2.1 数据模型扩展

订单数据模型,除了通用的买家信息、卖家信息、商品信息、支付信息、买家履约信息(支付信息)、卖家履约信息等基本信息之外,不同业务形态的订单还有差异化的数据需要存储和传递。我们的解决方案是通用信息结构化存储+差异信息JSON存储,具体如下:

  • 通用信息:通用信息结构化存储

  • 差异信息:服务间传递、存储用JSON格式, 后续处理由业务自定义逻辑处理,与通用逻辑解耦

  • 金额类信息:预期到有频繁的扩展需求,金额类型和金额值采用KV结构化存储,提高可扩展性

  • 图片
3.3.2.2 业务功能扩展

支持多业务问题本质上是业务功能如何抽象的问题,而差异逻辑处理则是在抽象通用基础能力的基础上,如何在部分处理环节支持差异性逻辑。我们采用的是抽象通用能力+预留扩展点的方式,具体如下:

  • 抽象通用能力:调研业务场景,对功能进行统一抽象,形成业务通用能力域,方便多业务复用

  • 预留扩展点:在通用能力域中针对可能存在差异地方预留扩展点,方便差异逻辑的实现;差异逻辑可通过配置化解决,也可用差异化代码实现。

图片
3.3.2.3 业务流程扩展

差异化流程的本质是串联能力节点形成业务流程,信息可在能力节点之间传递。我们采用流程编排+标准上下文的方式实现,具体如下:

  • 流程编排:我们团队自研流程引擎ark-maze组件,进行业务流程编排

  • 标准上下文:流程节点之间数据通过上下文传递,定义业务流程通用的上下文结构

流程引擎ark-maze组件,以“责任链”模式来组织复杂处理流程的执行过程,保障服务节点能够按照顺序执行,并且能够传递执行结果;发生异常可逆序进行回滚操作;支持节点的串行、并行执行。ark-maze组件架构图如下:

图片

3.3.3 稳定性方案

3.3.3.1 服务隔离

一套系统支持多个业务形态,导致业务间相互影响的原因如下:

  • 应用资源相互影响:某业务占用资源过多,影响其它业务

  • 存储相互影响:共享存储,导致业务间相互影响 我们采用多级别隔离机制,具体如下:

  • 线程池隔离:我们的分布式服务框架采用的是阿里开源框架dubbo,不同业务使用不同的dubbo的group,达到dubbo线程池的隔离,避免多业务争抢线程池的情况。

  • 服务器隔离:服务器按业务线分组独立部署,不同业务请求路由到相应的服务器集群。基于业务线配置不同profile文件,服务器按profile分组部署,不同的proflie注册不同group的dubbo服务,dubbo消费者使用不同group的服务。

  • 存储隔离:使用分库策略,不同业务数据路由到不同数据库集群。权衡业务流程规模、系统复杂度、运维成本,目前每日优鲜在【线程池隔离】级别。

图片
3.3.3.2 分业务监控

多业务监控本质上是在原有监控指标增加业务维度即可,相关监控指标包括:应用指标:异常日志、调用量等;业务指标:下单数、支付数、取消数等;

图片
3.3.3.3 业务保障系统

如何保障多业务正常运行?其本质就是如何快速发现问题,并且具有一定的自动修复的能力。我们搭建了业务保障平台,实时地发现业务数据的一致性和正确性问题,某些异常场景能做到自动修复,如果不能自动修复,第一时间报警给相关负责人。业务保障平台通过事件触发执行校验规则,规则支持自定义脚本和自定义api接口。

3.3.4 高性能方案

3.3.4.1 存储高性能

作为交易系统,存储海量订单数据,对外提供高可用、高性能的读写服务是必须要支持的。为了保障高可用、高性能,我们采用如下方案:

  • 分库分表:为了解决单库单表的存储上限和并发处理上限的问题,我们在设计初期以当时预估的5年内的订单规模,设计为N个分库N个分表。以订单号后N位取模作为分库分表的路由规则。

  • 读写分离:Mysql集群采用1主+1备+N从的高可用架构。写流量走主库,主库配置备库,保障高可用;读流量走从库,有实时性要求的读流量也走主库,由上游应用根据业务场景来决定;B端、C端读流量分离,避免B端流量影响C端用户流量。

  • ES搜索引擎:Mysql采用分库分表的方案,导致Mysql不能提供多表联合查询和多维度的复杂查询,采用其他搜索引擎提供复杂查询能力成为必然。我们采用分布式文档数据库Elasticsearch搜索引擎。监听Mysql数据库的binlog实时同步增量异构数据到Elasticsearch。为了保障ES集群的高可用,搭建2套ES集群作为互备,也能做到B端、C端流量的分离;Mysql数据同步ES有秒级的延迟,有实时性要求的C端流量不走ES,只能走Mysql主库查询,例如:待支付订单列表页查询Mysql,而其它实时性要求不高的或者用户无需感知实时状态的订单列表页(如:待配送、配送中的订单列表页)查询ES。

3.3.4.2 流程异步化

非核心业务处理如果混杂在核心链路中,影响核心流程的性能和稳定性。非核心处理剥离出来,异步化处理,提高整体的性能和稳定性。以订单取消流程为例:

图片

3.3.5 一致性方案

3.3.5.1 最终一致性事务框架miss-tfc

通常在核心业务流程中存在发送MQ,发起RPC调用第三方、刷新ES等场景,如:在生单流程中,需要在保存数据库后发送一条MQ消息。而以上这些场景是需要保证一定要执行的。当机器遇到宕机这类故障后,这些任务则有几率不会被执行。为了解决以上问题,通常的做法是每个业务写一个任务表定期执行;但是这样做带来的问题是巨多的任务表,维护和操作也不方便,重复的操作逻辑也会散落在各个业务处理中。我们团队miss-tfc框架则是为了解决以上问题而生的,它会把需要执行的任务持久化到数据库中,然后不断的重试补偿动作,直到任务处理成功。架构原理:通过拦截器配置指定类的指定方法保存起来镜像存储到任务表,并且与当前业务的写库事务绑定在一个事务中。等事务提交后,可以选择性的配置实时当前同步线程做、实时异步线程做、异步调度做等。

3.3.6 灰度方案

3.3.6.1 增量数据双向同步

交易平台收敛原来的各业务团队的烟囱式老交易系统,涉及读写流量的平滑切换处理,我们采用【灰度写流量->写全量->灰度读流量->读全量->老系统下线 】的方案。在这个过程中,考虑到用户列表等业务场景需要全量订单数据的情况,新老数据库都需要持有全量订单数据,我们用【增量数据双向同步】机制来保障。增量数据双向同步:交易平台的增量数据同步到老订单数据库,老订单系统的增量数据同步到交易平台数据库,使新老订单库同时保有全量订单数据。

图片

四、踩过的坑

4.1 过度设计

4.1.1 过早的服务器隔离

在各业务形态流量规模还没有到影响稳定性的情况下,过早的以业务线维度部署服务器达到所谓的服务器隔离的级别,导致了测试机器、生产机器的成本浪费,同时也增加了测试的复杂度和成本。

  • 解决方案:隔离级别从服务器隔离 降为 线程池隔离

4.2 依赖组件

4.2.1 核心链路依赖开源组件

订单状态的流转,我们采用了消息驱动的方案;为了与业务代码解耦,消息是用阿里开源的数据库同步系统otter监听数据库订单表的binlog来发出的。支付成功后的履约分发等核心链路也依赖这种消息驱动;某次网络问题导致otter消息阻塞,造成近30分钟的订单不能履约的故障。开源组件本身的设计不足、或者对开源组件没有完全掌握,遇到问题不能快速定位、快速解决,都是稳定性不可控的因素。

  • 解决方案:痛定思痛,我们从核心链路彻底去掉开源组件otter,自研一致性组件miss-tfc,详细参考【3.3.5.1 最终一致性事务框架miss-tfc】;针对自研组件,我们有更大的热情、更强的自主性进行长期地维护、推广和完善。

五、未来展望

经过了2年多的持续建设,目前交易平台能够高效、稳定地支撑公司业务的快速发展,但还是存在一些功能需要持续完善。

5.1 业务参数动态配置化

目前业务参数配置较为混乱,在系统配置文件(yml文件)、分布式配置中心(missconf)都有,静态、动态的区分混乱,导致管理成本高。后续规划建设交易平台配置中心,统一、动态管理业务配置。

5.2 流程编排可视化

搭建业务流程管理中心,能力地图、流程编排可视化展示,流程编排可动态生效。

5.3 订单全链路监控

建立基于订单生命周期全链路的数据流,实时跟踪订单各个环节的处理状态,并将作业数据可视化;有效防止订单流转失败、漏单、超卖等其他系统异常和业务异常情况;掌握各系统作业效率,帮助内部效率提升。

六、总结

在每日优鲜交易平台建设过程中,我们借鉴行业最佳实践,也踩过大大小小的坑,探索并形成了自己的平台化架构建设的方法论,希望对大家有一些启发;同时也欢迎大家来件一起探讨。

作者简介

  • 陈国民,2017年加入每日优鲜,目前主要从事交易平台建设的相关工作。邮箱:chengm@missfresh.cn

  • 感谢芋艿的表弟苏磊(公众号:????再见伐木鸡????)、张祖瑞对本文的指正。

  • 感谢晋冰、陈思彤对本文的指导。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 20 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值