美团商品平台化之路—关于架构原则的思考

从2015年初到2018年末,已经在美团点评做了4年商品系统。稍微总结一下。

2019/1/3

#业务快跑、平台慢跑#

1.业务快跑

2015年初开始做泛商品系统是为了做ktv预订探索,背后写了一套通用点的商品系统。记得第一版商品系统上线、我做得很高兴,但老板跑过来帮我复盘,“为什么这个项目延期这么久”。额,延期了两周!

我第一次那么吃惊,干得那么沉醉却得到这样的反馈,被泼一盆冷水很深刻。当时的背景是原点评要将ktv团购升级为ktv预订、做mvp,典型的业务快跑方法论。早两周交付就能早两周拿到在线的测试数据。

那我用了什么理念开发呢?把它当成孩子,给它我认为最好的东西。简洁、易组合的api,全栈式批处理,三套独立的商品领域对象,制作/线上表与服务分离,去ddd、最简洁的代码等等。从技术角度,去实现多了支撑ktv预订业务需要的系统能力,很纯粹的就是想写好。后边反思,做业务支撑要掌握trade off,做为业务方在业务初期要尽量让业务快跑,产品和系统应该都用迭代的思想去做事。

2.平台慢跑

业务快跑真的对吗?头两年在业务团队做商品系统,后两年在平台团队做商品系统。得出一个新认知:平台系统要尽可能的慢跑、冷启动。一味跟着业务快跑味道就不对了。

 

Platform Fist

投资平台基础设施还是投资新业务时机,这本质是看哪一种产生的ROI更有价值,它的判断跟行业市场、公司规模、战略、组织、kp强相关。

行业增长较快的机会点、时机很重要,平台基础层少做点、业务上层多做点。假如本身新业务的逻辑就不对头,平台应该多投资源做厚些、复利。创业公司活着最重要,业务不仅要快跑、还要拼命跑。

可以分享下阿里做共享事业部的时机。那时淘宝商城做失败了,技术leader认为商城的商品系统更吊、这应该是支撑阿里巴巴商业的基础,跑去跟CEO老陆讲,老陆干销售的、却听懂了,拍板用商城的商品系统。一个业务做失败了、另一个业务很大很成熟,但技术系统的决策逻辑跟业务之间不是绝对的。

大多数公司业务体量决定了组织上的话语权,无论是产品、技术、销售等资源,还是他们背后的工具。平台系统的决策逻辑不是哪个团队人多,哪个业务体量大,哪个技术老板职级高。平台系统的决策逻辑应该是从技术本质出发,它的核心系统能力及先进性是否更好支撑公司的未来。阿里在有了两个BU、几百个人,业务要多元发展,系统就选择了平台化、打破了技术的组织墙。

今天淘宝的CTO负责了大零售、云、中台、蚂蚁等的技术。所有的技术应该都应该被一个头所负责,且与产品地位相当、有独立决策权。要不然高科技企业就是纸上写写。本质上是科技在驱动商业。

“Platform First”!平台不能被业务牵着鼻子走。平台系统要按计划经济走,哪些是核心能力、哪些价值大,这是基本的判断。

Platform Slow Enough

platform first是方向决策,platform slow enough是开发节奏。平台研发也应该是迭代思维、一点点来,业务支撑不可能覆盖所有的需求。“慢”主要指两方面:

一、平台能力尽可能按计划经济走。不可能一下子业务支撑100%到位,开始可能连20%都不到,不能一味支撑“业务快跑”。阿里业务中台的客户满意度kpi就占15%,初期就是要挨骂的,前台开发、产品都会骂你。没魄力、求全求大反而做不好平台,平台的第一要务是苦练基本功,做强设计、做好代码。平台一开始最好冷启动,尽可能降低客户预期。越偏前台的功能优先级可以越偏后。

二、平台建设速度不要一味求快、更要求质。抽象程度、可扩展能力、稳定性等这些核心能力要同步发展。可扩展性决定平台未来成长的极限,系统抽象决定着现在能力的极限。稳定性在系统质量里是最关键的因素,平台抖一抖影响面很大。

#批判性思维、认知业务#

做业务、感触最深的是:业务理解多深刻、平台能力就有多强大。举一个领域解耦的例子。最开始点评团购商品系统耦合着结算信息(佣金率、结算方式)活动信息(开始时间、结束时间)、以及前端控件信息,商品制作发布耦合着审核流程等。

做商品系统平台化的时候,问自己最多的问题是:商品跟这些真的有关系吗?可不可以没有?强关系、还是弱关系?

我们最终去掉了商品与方案的耦合。从商品领域去掉了结算信息,推动结算方式落地在了客户维度,结算佣金提供了更多的维度的计算,支持类目、方案维度,也支持客户白名单、商品维度佣金。这些都是技术牵头、驱动产品,从无到有的在做事。

再举一个重销售端的例子。一个团单最早被称之为方案(方案是与商家开通合作的签约信息),团购的上单被称为供应链、主要面向销售地推场景。2013-2015美团和大众点评打团购战。双方都靠销售开新城、签独家、铺货、一单一单录进来,针对大客户降佣、甚至提供保底金。团购很多功能都为销售CRM而建设,效率、速度要求很快,团购产品的定位是优惠的套餐。

2016以后随着团购市场的变化,再靠销售一单一单录团单、销售成本已经很大了。2015年开始做的泛商品系统、一开始就面向商家端,商家端的特点是轻、因为商家操作要求简单;后来补上了销售端,后端大部分接口、功能、页面都复用,销售的逻辑与商家的逻辑保持一致,因为我们理解销售更多是辅助的角色。我们不再把商品叫成方案,不再把商品管理叫做商品供应链。O2O商品的本质就是:结构化的CMS+灵活的售卖形式。CMS就是增加元数据描述及存储的扩展能力,灵活售卖形式就是做强价格、库存、售卖规则。

关于商品的b/c架构。无论点评还是美团,搞商品都喜欢b/c架构,b端叫做商品供应链、就会做得跟c端差异化大(数据、逻辑),b/c场景把商品基础层割裂了,就像本来一个完整的人被拆成了上半身与下半身。这样的做法更多是固化思维,以前做得快、就这么搞了;以前这么搞、现在也这么搞,“存在即合理”、缺乏平台化建设性的思考。商品基础层的边界包含商品制作、发布、售卖的场景闭环,数据可以一份、也可以两份、甚至可以三份,但都闭环在商品基础系统里。商品基础系统是不分b/c的、它应该内聚商品能力,从这个基本点出发、商品数据流通与管理成本才最小。

这里最重要的经验是:批判性的思考业务,多思考、多问自己为什么。市场变了,认知要变,不能按老系统思路来。没有边界的去思考问题。

#平台最小感知业务#

作为平台方,在选择技术方案上第一个要考虑的原则是LNP(Least Knowledge Principle,最小感知原则)。通俗一点是平台方尽量不感知接入方。举一些常见的场景吧。

功能开发的场景。功能如果可以标准化,可抽象成多个通用套餐、并提供默认套餐的能力。走默认方案,这样平台方和业务方都没有开发量、连配置化也不用。“鸡犬之声相闻,老死不相往来”才是平台开发的最高境界。这背后要求深刻理解业务,能抽象出来通用的套餐。

“每个人都生活在富足、祥和、宁静、喜乐、满足的世界中,交流或者不交流,来往或者不来往,对他们的生活均没有丝毫影响,每一个人都活在当下那一刻, 享受那一刻,听着窗外的鸡叫声、狗吠声,头顶白云飘飘,身边清风阵阵,唯恐有任何不速之客打破这一美好时刻。”

数据交互的场景。尽量平台方定标准、建立一个数据层来做隔离,由业务方来驱动&Control;这样平台方不依赖任何接入方,依赖也很干净。如果要感知,也尽量不要用以spi(rpc)的方式,spi(rpc)会让接入方的依赖关系变得很复杂,扩展点(jar)方式很恶心、但也比spi(rpc)要好些。还有一种是插件+框架组合在一起,部署成实例,但这对资源成本和技术中间件有很大挑战。当然依赖平台方又是一回事,这样的依赖是稳定的。

逻辑判断的场景。商品系统有很多逻辑判断的条件分支,原先我们依赖很细的品类,现在只要能依赖更大粒度的产品类型做、就依赖产品类型(产品类型如团购,品类如丽人/美甲)。能做黑名单、就不要做白名单。大部分场景用黑名单去屏蔽特殊逻辑,少量场景用白名单做入口的控制、发放特权。总之,能写大逻辑就不要写小逻辑,能做粗、就不要做细。

我们要想尽一切办法去做到LNP。要有意识,配置也是一种很昂贵的成本。

#做万能胶水、要有全局观#

什么叫全局观呢?我做商品,但要知道商品的上下游依赖,不仅仅做到与CRM、审核、营销、搜索、广告等的数据与功能连接,至少还能向上跳一步。理想状态是,拓展新业务、营销标准能力默认就有了,搜索能力就有了、用户搜关键词就能定位到商品,猜你喜欢可以推荐更多符合用户喜好的商品。。。。。

向上跳一步,平台方至少要做到与其它合作方站在同一频道理解业务价值。最早我们做平台,以为做到与其它平台的连接就够了,我们之间的对接是标准化的。我们事较少、都标准化,但对其它平台却还要排期、开发,也许只要半天工作量,流程大法走下来、一两个月就没了。平台方要以终为始,有共同的价值观、全局观,就容易出来全局最优解的方案。我快你慢、两方都极差、不是取平均的。

向上跳两步,大家可以站在用户角度去理解业务价值。譬如我做商品、接入营销,就要思考什么行业、产品形态商家会有诉求、会有什么诉求。想通了、跟营销平台方做连接,大家就更容易选出更合适的方案。

什么又叫万能胶水?万能胶水让人想起python、脚本语言。胶水的本质是连接、再创造,说的实在一点就是一个平台与另一个平台做连接、总会有一个主动方。譬如线上商品交易系统,更合适以商品为中心、驱动售前场景,让数据流通于在线营销的各个场景。这个时候商品中心就要有万能胶水的担当,得要为营销定制大量适配接口,得要为搜索定制大量适配接口。大商品交易系统,以商品系统和交易系统为两个轴心,就把核心及周边系统都驱动起来了。

万能胶水会有很大的开发与维护成本,是脏活、累活,一旦做好了、一大片的平台能力就有了一个中心做驱动,效率可以几倍、十几倍的提升。全局的看万能胶水,就是一定要找好一两个中心,承担连接其它中心的职责。

#方法论、工具化及生命力#

方法论比较虚,你相信它、琢磨它、用它,就会有经验、有心得。过去四年软件架构的方法论,我只记住了“SOLID原则”,像DDD这些我都反对;

更简单点,“高内聚、低耦合”;再简单点,“边界”。

这里第一点讲方法论是因为,希望大家少一点方法论、多一点实践。理论跟实践不冲突,技术有很多被炒得很热的概念,大家要尽量去理解本质。理解不了没关系,一步一步做实践。怎么实践呢?只持有几条方法论,譬如SOLID、GRASP,或者“简单性”、“边界”,就几个词,其实一辈子就够用了。关键在于用。

工具化。工具化网上谈的比较多,譬如元数据、配置化、组件化及拼接、模块化、服务化、规则引擎、流程引擎、UI工具、前端模板等等。具体细节不多聊,想讲的是关于工具的本质是什么?本质是改善效率、提高生产力。能让代码写代码的、就不要让人写,能工具化替代人的、都将被工具所替代,这也是UNIX哲学之一。

生命力。最后一点想谈的是平台系统的生命力,人、动物、植物都有生命,但机器冷冰冰的、代码冷冰冰的、都没有生命力。阿里业务中台副总裁玄难在《面向不确定性的软件设计几点思考》中,提及阿里的平台系统已经完成了工具化阶段,现在要往内核思维走。本质在谈什么?

电商有很多平台,用户中心、商品中心、营销中心、交易中心、财务中心等等。有了这些中心,前台层的接入方还是很痛苦,貌似功能都很全、却用起来巨复杂,就像小白去华强北组装一台电脑,cpu是什么、主机是什么;接入平台的复杂度可能比接入方自建还要高。这么多中心怎么协同呢?所以提出内核思维。

我来解读下内核思维吧。我最早接触操作系统,以为POSIX标准接口是内核最great的地方,本质就是跟用户态空间的标准通讯接口,但这几年细想下来这还只是大家看到的一层皮。标准通讯接口解决不了操作系统能力的实质。

UNIX有很多哲学,摘了如下两条,我总结成一句话:整体大于部分之和”(亚里士多德)。UNIX是Micro kernel(微服务),LINUX是Monolithic kernel(单体),但LINUX之所以采用Monolithic、也是因为“整体大于部分之和”。从这点上看他们有着共同的一些精随,这些平台如果孤立成插件、那他们就失去了统一指挥的能力,换言之,也就失去了生命力。

为什么最后是晚起来的LINUX统一了操作系统这块市场,而不是一开始就设计得很模块化、插件化、微服务的UNIX?这很值得深思。现在微服务热,很浮躁,要真正想清楚系统要提供的是什么。

比标准化更强大的,是这些平台形成统一的生命体。仅举一个例子,譬如有没有一个public envirnment去定一个新产品,所有的平台都能立马感知到了?感知到,立马这些平台能自动发起决策,系统之间沟通一下、新产品就创造出来了?现在方案、商品、交易、结算这些对产品概念的认识和变量名、值,都对不齐。

这要求的是紧耦合,更高层的抽象、统一指挥这些平台;但不一定要有统一的指挥官。整体大于局部之和,系统才能超越原子、超越还原论,让各平台系统活起来、富有生命力。应该还是要深入去看各个子系统抽象的概念细节,重着这些系统之间的强联系,是不是统一紧耦合的。

最后引用一段话来谈两个内核的哲学差异点:

The UNIX Programming Environment

Even though the UNIX system introduces a number of innovative programs and techniques, no single program or idea makes it work well. Instead, what makes it effective is the approach to programming, a philosophy of using the computer. Although that philosophy can't be written down in a single sentence, at its heart is the idea that the power of a system comes more from the relationships among programs than from the programs themselves. Many UNIX programs do quite trivial things in isolation, but, combined with other programs, become general and useful tools.

Program Design in the UNIX Environment

Much of the power of the UNIX operating system comes from a style of program design that makes programs easy to use and, more important, easy to combine with other programs. This style has been called the use of software tools, and depends more on how the programs fit into the programming environment and how they can be used with other programs than on how they are designed internally. [...] This style was based on the use of tools: using programs separately or in combination to get a job done, rather than doing it by hand, by monolithic self-sufficient subsystems, or by special-purpose, one-time programs.

Linus talk about Microkernels

https://www.oreilly.com/openbook/opensources/book/linus.html
When I began to write the Linux kernel, there was an accepted school of thought about how to write a portable system. The conventional wisdom was that you had to use a microkernel-style architecture.

With a monolithic kernel such as the Linux kernel, memory is divided into user space and kernel space. Kernel space is where the actual kernel code is loaded, and where memory is allocated for kernel-level operations. Kernel operations include scheduling, process management, signaling, device I/O, paging, and swapping: the core operations that other programs rely on to be taken care of. Because the kernel code includes low-level interaction with the hardware, monolithic kernels appear to be specific to a particular architecture.

A microkernel performs a much smaller set of operations, and in more limited form: interprocess communication, limited process management and scheduling, and some low-level I/O. Microkernels appear to be less hardware-specific because many of the system specifics are pushed into user space. A microkernel architecture is basically a way of abstracting the details of process control, memory allocation, and resource allocation so that a port to another chipset would require minimal changes.

So at the time I started work on Linux in 1991, people assumed portability would come from a microkernel approach. You see, this was sort of the research darling at the time for computer scientists. However, I am a pragmatic person, and at the time I felt that microkernels (a) were experimental, (b) were obviously more complex than monolithic Kernels, and (c) executed notably slower than monolithic kernels. Speed matters a lot in a real-world operating system, and so a lot of the research dollars at the time were spent on examining optimization for microkernels to make it so they could run as fast as a normal kernel. The funny thing is if you actually read those papers, you find that, while the researchers were applying their optimizational tricks on a microkernel, in fact those same tricks could just as easily be applied to traditional kernels to accelerate their execution.

In fact, this made me think that the microkernel approach was essentially a dishonest approach aimed at receiving more dollars for research. I don't necessarily think these researchers were knowingly dishonest. Perhaps they were simply stupid. Or deluded. I mean this in a very real sense. The dishonesty comes from the intense pressure in the research community at that time to pursue the microkernel topic. In a computer science research lab, you were studying microkernels or you weren't studying kernels at all. So everyone was pressured into this dishonesty, even the people designing Windows NT. While the NT team knew the final result wouldn't approach a microkernel, they knew they had to pay lip service to the idea.

Fortunately I never felt much pressure to pursue microkernels. The University of Helsinki had been doing operating system research from the late 60s on, and people there didn't see the operating system kernel as much of a research topic anymore. In a way they were right: the basics of operating systems, and by extension the Linux kernel, were well understood by the early 70s; anything after that has been to some degree an exercise in self-gratification.

If you want code to be portable, you shouldn't necessarily create an abstraction layer to achieve portability. Instead you should just program intelligently. Essentially, trying to make microkernels portable is a waste of time. It's like building an exceptionally fast car and putting square tires on it. The idea of abstracting away the one thing that must be blindingly fast--the kernel--is inherently counter-productive.

Of course there's a bit more to microkernel research than that. But a big part of the problem is a difference in goals. The aim of much of the microkernel research was to design for a theoretical ideal, to come up with a design that would be as portable as possible across any conceivable architecture. With Linux I didn't have to aim for such a lofty goal. I was interested in portability between real world systems, not theoretical systems.

发布了105 篇原创文章 · 获赞 12 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/Ture010Love/article/details/104194114