我是创始人李岩:很抱歉!给自己产品做个广告,点击进来看看。
产品架构序言
人人都是产品经理流行了多年,随着市场蓬勃的发展后,也迎来了产品经理的下半场:越来越细分,越来越2B。在面向C端的产品开发及体验进入到瓶颈期后,B端产品开始流行起来,那么构建高可靠、高并发、高容错、高开放的产品架构是必然趋势,所以产品架构这个角色正逐渐
进入大众视野,也必然会成为产品专业的灯塔。
自然情况下,一个孤立系统会由有序变为无序,即它的"熵"会不断增加,最终寂灭。而生物可以通过和外界交互,主动进行新陈代谢,制造
"负熵"
来保证自身有序,继续生存。系统其实跟人很像,随着功能越来越多,调用量急剧增长,整个系统变得越来越无序,如果不做合理的干预和设计,最终会导致无法维护和扩展,成为业务发展的瓶颈。
架构的本质就是对系统进行有序化重构,不断减少系统的“熵”,使系统不断进化。
从用户视角,
线上渠道无论大小平台其购物流程大同小异:
选择商品、加购物车、结算确认、收银支付、生成订单
、等待收货 ,基本上是对现实世界的购物流程进行了抽象复刻,这就是俗称的电商黄金交易流程。
虽然"看上去"一样,但是其背后的运转机制却千差万别。
本文不做具体模块的设计细节讲述,因为各平台的业务属性和发展阶段不尽相同,不具备完全的参照意义,只是从产品架构的视角来剖析电商产品。
电商产品架构
电商正向流程核心为5大部分:推荐引擎、交易引擎、订单引擎、履约引擎,风控引擎,在各引擎中
信息流、资金流、实物流有序的流淌着,最终让客户如约收到完好的商品。
作为产品人员,更重要的是思维转变,不在简单的是功能和业务,善于应用数据思维来更好的满足用户需求,而且是动态的和用户进行互动,再也不是完全静态的让用户按照你既有的设计思路来交流。
当然推荐引擎不是电商的专利,但目前是电商撮合交易最重要的前戏,用户体验是否愉悦舒畅直接影响了最后的买单付款。
推荐引擎和用户每一次的接触都有价值,引擎都需要实时计算返回给用户结果,用户获得结果后的行为,如浏览路径、停留时长等都及时反馈到引擎,形成一次闭环,如此循环反复下去。
很多反馈说,我们没有大数据,没有海量的信息,根本用不到推荐引擎。
推荐引擎是极其复杂的系统,不做实现赘述。
电商平台通过合适商品、促销优惠等手段来吸引用户促成交易,而促成
交易本质是为用户提供一个待签的草拟合同,合同的内容要素:商品属性信息、订单金额信息、促销优惠信息、收货地址信息、履约时效信息、运费服务费信息、发票相关信息等,这些都是建立在交易双方自由平等的基础上草拟的合同内容。
交易引擎从用户视角是结算页,而从系统视角是大脑中枢,要求的性能是几十毫秒级,最快速度草拟合同,并且不停地根据用户的选择来呈现最新内容,等待着用户点击提交订单那一刻。
我们以天猫的交易页面来示意说明:
看起来像不像一页合同,正翘首等待着用户提交订单那一刻完成签字画押。
每项合同条款的规则就是产品架构要定义的,而每一个元素的具体可选的枚举值是由合同履约方来定义,那么一旦用户觉得此合同条款及内容可以接受,就会按下提交订单完成合同的签署。
合同的每一项条款背后都是一个复杂的应用系统来提供服务,比如配送时间服务,就是一个单独的系统来维护,其可以在交易无感知情况下,更新其可以提供的配送服务。
交易引擎只是提供条款服务方可以自定义合同条款及履约方法的一套条款框架自运行机制。
用来根据用户的选择来调取条款服务方加载对应的条款内容。任意
店铺根据所有可选合同条款及内容自选需要多少供用户选择。那么当用户购买了此店铺的商品且开始结算的时候,交易引擎就会根据店铺已选择的模板内容来调取相关的应用系统来加载合同具体内容展示给用户。
由于业务发展需求变化快,交易引擎需要更加高效的支持,那么必须做到所有的数据交互要做到最小粒度,并提供扩展点供让业务自定义数据来影响相关履约流程。如SKU
维度入参和作为通道将自定义参数透传。
交易引擎是草拟合同,而订单则是双方白纸黑字签约,乙方要按照合同为用户来履约。
那么系统究竟是如何来为用户履约的呢?
在整个流程中需多个系统精密协作来完成一个订单履约。
大型电商大都采用微服务架构,恰好消息中间件成了解决微服务之间交互问题的重要组件,如应用耦合、异步通知、流量削锋等问题,最终实现高性能、高可用、可伸缩、一致性的产品架构。
各个系统都在嗷嗷待哺,等着订单数据来触发其业务流转,这是订单系统核心工作之一。随着订单在主干道和分支业务系统之间交互流转,其会影响订单的流转速度和方向,而每次的交互都可能产生新的数据,那么保证任意时刻数据一致性是至关重要的。
分布式系统几乎不可能每一个时刻完全保证数据一致性,所以需要建立一个数据使用白皮书来规范数据的交互和使用。
任何提供服务的系统都要维护其边界内核心数据的准确性,即主数据。其他系统的这部分数据需来源于主数据,尤其是强依赖的数据,无论什么情况都首先需
以主数据为准,
甚至要通过反查来确认数据准确性。
主数据的数据来源也不是完全可以自己闭环,也会依赖其他系统的数据上收,所以其必然也存在数据时间差。
典型的是订单状态数据,其状态是在流转变化的,由订单生成到订单完成之间会经历大大小小的十多个状态,而状态数据由于是异步更新的,那么利用消息机制进行广播,相关系统监听这部分消息来触发其业务逻辑。如到了订单到了支付完成状态其主数据会发出支付完成消息,生产系统会监听并消费到此消息来触发其拆单拣货打包配送等操作。
基于订单状态的变化而广播消息是订单数据分发的核心机制之一,另外一部分是关键业务数据或个性化业务特殊触发的消息。
订单号是典型的结果数据,无特殊情况是不能被修改的。结果数据通常是可以信赖的,但随着业务发展,系统中会有各种错误而需要数据修复,这可能会导致结果数据被修改。
随着用户场景越来越丰富,业务发展越来越复杂,必然存在修改订单数据的场景,这对分布式的异步系统是非常挑战的,核心原因为过程和结果数据分发到相关系统已经触发其业务进程中,而在这期间修改数据对于已经或正在执行的业务产生致命影响。如修改收货地址,直接影响到运费价格和履约时效的重新计算,会引发很多相关系统做出应变。
所以通常提供订单后修改数据的能力是非常慎重的,且这部分数据通常会通过带有版本号的数据快照来记录,以区分和追溯。
由于主干道对数据时效要求极高,此时大部分是通过接口进行数据通信交互,而对其他系统并不在主干道或对时效要求不高,可通过消息机制的方式来实现数据交互。
消息队列是基础数据结构中的“先进先出”的一种数据机构。
生活中排队买东西,就是典型的“先进先出”。
通
过消息广播数据的机制,可以解决:
应用解耦、流量消峰、消息分发、异步通知等。
应用解耦:
应用中有订单系统、财务系统、仓配系统等各种业务系统。
用户创建订单后,如果耦合调用所有相关系统,任何一个子系统出了故障,都会造成下单操作异常。
当转变成基于消息队列的方式后,系统间调用的问题会减少很多,比如物流系统因为发生故障,需要几分钟来修复。
在这几分钟的时间里,物流系统要处理的内存被缓存在消息队列中,用户的下单操作可以正常完成。
当物流系统恢复后,继续处理订单信息即可,中单用户感受不到物流系统的故障。
提升系统的可用性。
流量消峰:
举个例子,如果订单系统最多能处理一万次订单,这个处理能力应付正常时段的下单绰绰有余,正常时段下单一秒后就能返回结果。
但是在高峰期,如果有两万次下单操作系统是处理不了的,只能限制订单超过一万后不允许用户下单。
使用消息队列做缓冲,我们可以取消这个限制,把一秒内下的订单分散成一段时间来处理,这使有些用户可能在下单十几秒后才能收到下单成功的操作,但是比不能下单的体验要好。
消息分发:
多个服务对数据感兴趣,只需要监听同一类消息即可处理。
例如A产生数据,B对数据感兴趣。如果没有消息的队列A每次处理完需要调用一下B服务。过了一段时间C对数据也感性,A就需要改代码,调用B服务,调用C服务。只要有服务需要,A服务都要改动代码。很不方便。
有了消息队列后,A只管发送一次消息,B对消息感兴趣,只需要监听消息。C感兴趣,C也去监听消息。A服务作为基础服务完全不需要有改动。
异步消息:
有
些服务间调用是异步的,例如A调用B,B需要花费很长时间执行,但是A需要知道B什么时候可以执行完,以前一般有两种方式,A过一段时间去调用B的查询api查询。
或者A提供一个callback api,B执行完之后调用api通知A服务。
这两种方式都不是很优雅
使用消息总线,可以很方便解决这个问题,A调用B服务后,只需要监听B处理完成的消息,当B处理完成后,会发送一条消息给MQ,MQ会将此消息转发给A服务。这样A服务既不用循环调用B的查询api,也不用提供callback api。同样B服务也不用做这些操作。A服务还能及时的得到异步处理成功的消息。
订单状态由订单系统来维护,也是其最重要的数据。其几乎控制着整个电商系统的运行流转。
每一个状态的变化会影响和指引订单的信息流、实物流、资金流的流向。通常在大型电商平台会有上百个系统来监听订单状态的变化来触发业务,作为业务开始的起点。
每个状态都是在不同的作业流程中各系统来触发改变,并将数据回传到订单主数据,由订单主数据来统一维护和调度订单状态,以确保数据一致性。
由于订单状态的重要性,其在设计之初要特别小心。
个性化状态不能加到主干流程,可作为订单扩展数据存在。
每个
状态的流转需有前置和后置状态的合法性校验,且作为可配置。如能从状态1到2,但是不能从状态3到2。
所谓的订单履约就是按照订单上的承诺来履行和用户的一个承诺的约定。而通常为了考虑履约成本,且由于商品所在
物理上并不是一个不可拆分的单元,也即:它不是一个颗粒度最小的实体,可以进行多种形式的分解,具体如何分解根据不同的业务场景,可以进行不同形式的拆分。
订单拆分是通过客户在前台提交的订单,把客户承诺的合同或履行约定,拆成货主可生产的一系列子单,
其实最核心的是
拆信息、拆资金、拆实物。其实不同的平台拆分维度很多,不做赘述。拆分后,
比如说仓库生产、配送环节、售后环节,实际上都是参照子单去进行操作。
像双11或者618等这种大促的时候,我们的购物车可能一次性会有10个甚至有若干个东西要购买,最后发现被拆成多个订单,什么原因呢?
即使针对同一个货主,也有可能其不同品类的商品由于储存环境等因素会被放到不同的仓,
这样就会带来一个拆分,这是最主要的一个维度,即库房。
京东为例,京东现在有自营和POP,而POP里边有不同的商家,京东为了要给不同的商家进行结算,不可能在一张订单上同时存在两个商家的商品,这将导致京东无法跟商家做结算。因而,京东会根据商家去进行拆单。
有些是业务本身的特殊性,需要单独履约。比如用户下单买了A和B商品,但是B暂时无货,那么可以选择有货先发,那么就会被拆开分别履约。
基本365天都会有不同类型的促销。
比如买个东西,满199减 100啊(活动预热),大家都会凑单凑到199。
于是,用户就会买食品凑够199然后减掉100。
假如用户买了10件商品,减了100元,那么具体这100块钱怎么减呢?
对于客户来说,他们不理会平台怎么操作这个优惠折扣,只要这100块钱在自己结算的时候抵扣即可。
比如,用户花了200块钱,而实际只是收了用户100块钱,这就可以了。
但对于平台来说,这100块钱并不是直接减100这样来登记的,其不在订单里,是以商品的金额订单里,商品金额的比例分拆优惠的钱。
订单转移可以理解为订单的
计划,其是为了实现订单履约,而制定的生产方案。一个
合理的生产计划,能在保证时效承诺的前提下,起到优化生产,降低成本的作用。
由于平台越来越开放,不同的订单来源于不同渠道,需要由不同的生产系统来履约。那
系统是如何确定以什么
方式为客户履约,其实订单履约计划是履约的一个核心环节,将待履约的订单按照履约计划
分发到不同的库房去生产。
但对于库房来说,不可能来了一张订单就生产一个订单,这样的库房是没有计划性的,
容易导致生产混乱,所以
订单都会按照履约计划成堆生产,而不是单独去生产。
FTP,即Fulfill to Promise,即针对现货去做履约计划。
ATP,即Availableto Promise,即针对没有现货去做履约计划。
未来的趋势一定是ATP的比重会变大,就是怎么把供应商的库存,怎么把在途的库存,怎么把一些计划里的东西,都能实际的用起来
。
在大促期间,用户的第一的需求是我能买到这个货(因为便宜)。
可能就对时效的要求不高。
有一些东西会通过让用户选择牺牲时效,而把一些在途的库存或在供应商仓库里的库存,都会去把这个东西认为是可以生产履约的库存。最后
,会让消费者真正的能享受到这个实际的优惠。
风控引擎需在事前、事中、事后对可疑行为进行系统或人工干预。
目前由于大量黑灰产、羊毛党、黑客们的存在,这些人已不是单打独斗,而是与时俱进地团队作战,如果系统不针对这些人或系统的行为进行防范,随时有可能被恶意攻击而导致系统瘫痪,从而无法给真正的用户提供服务。因此,在电商系统里面,风控是极其重要的系统,甚至是凌驾于其他系统之上,否则一旦发生就会产生巨额经济损失。
任何数据写入的地方,那么这两个前端界面可输入的地方,都会存在安全隐患。这些可输入的内容,比如文字、图片、视频等存在的风险,属于内容风险。我们需要对文字进行敏感词过滤,对图片进行签黄以及对图片上的文字进行审核,对视频的内容也需要进行审核。
所有系统必然存在漏洞,只是还没有被发现而已。营销作弊、刷红包、薅羊毛、推广作弊等欺诈风险。目前黑客们每天跃跃欲试,其每天可能针对目标攻击数次,常见的
批量注册、批量登录、批量抢单、报文篡改等。
电商平台每天各种促销优惠活动,在促销优惠设置及相互叠加后极有可能出现极低价格,甚至0元单的出现,那么瞬间就会被用户尤其黑灰产、羊毛党等薅个精光。所以针对价格相关影响因素需要有实时监控系统,满足预设规则及时报警,甚至系统直接锁定。
以支付为示意,风控模型是多维度异常复杂的系统,而且都是实时性要求极高,否则会影响主流程的继续运行。
产品架构最大的特点在于,眼中没有产品形态的概念,是需要在充分理解用户需求的基础上,规划设计在生态内各角色协同完成工作的一套机制。
产品架构设计,需尽最大努力感知不到业务的存在,应只专注于数据结构、数据分发、数据协同,但却可以提供一个舒适的、自由的、开放的环境让业务茁壮成长。