vivo 全球商城:架构演进之路

Wesley13
• 阅读 916

本文讲述 vivo 官方商城从单体应用到具备综合能力电商平台的演进,系统架构往服务化、中台化的变迁历程。

一、前言

vivo官方商城,是vivo官方的线上电商平台,主营vivo手机及专属配件。经过几年发展,已经完成了从单体应用到具备综合能力电商平台的演进,整体系统架构也逐步往服务化、中台化变迁。我们在这条系统架构升级的道路中,实践出了一些系统架构经验。

通过本篇文章,可以让对电商感兴趣的小伙伴们,更为全面地了解最基础的电商业务模式,了解电商体系具备的技术和架构,了解系统在不同时期的架构演进。

二、架构变迁史

“冰冻三尺,非一日之寒”。任何一个电商系统的架构升级,都不是一蹴而就的,都需要一个稳步发展的过程,不同阶段业务发展的形态和体量决定着系统架构。下面从一张图开始,给大家描述下商城近几年架构变迁的历史。

vivo 全球商城:架构演进之路

(图1.1 vivo官方商城架构变迁历程)

2015年之前,vivo官方商城是外包项目,采用了市面上比较成熟的 ECStore(企业级开源网上电商系统)电商产品作为系统基础,主语言是PHP。

项目版本就是在此基础上进行二次开发迭代。

和大多数电商平台早期的发展一样,满足快速部署、快速上线。

同时弊端也很明显:

  • 性能很差,根本无法支撑稍大一点的运营活动。当有新品、大促活动,系统负载高,业务基本处于不可用状态,无法满足运营活动需求。

  • 需求沟通效率,研发效率低下,外包研发、产品异地办公,需求沟通困难。

  • 核心项目受制于人,vivo 官方商城必须掌握在自己手中。

为了解决这些问题,架构迫切需要升级、系统需要重构。

2.1 商城 v1.0 单体时期

2015年5月,vivo官方商城正式启动重构计划。vivo启用自己的研发团队,目标很明确,自研一套属于自己的vivo官方商城,为用户提供更好的购物体验。

在2016年1月,属于我们自己的vivo官方商城正式上线了。

商城v1.0以主流的 Java 作为开发语言,采用经典的 MVC 框架,开发出了一个囊括了各个业务模块的单体应用,整体业务模块如下图所示:

vivo 全球商城:架构演进之路

(图2.1 商城v1.0系统架构)

相比之前,这次重构最重要的指导思想就是“分层”。

业务上对各个模块进行逻辑分层。划分出了商品模块、订单模块、营销模块、结算模块等等,使得代码逻辑更为清晰。

架构上也进行分层解耦:

  • 【表现层】– 最贴近用户的一层,主要用来处理数据展示逻辑并渲染数据;

  • 【服务层】– 负责表现层与数据层之间的业务逻辑;

  • 【数据层】– 负责数据的落地存储,存储介质使用常用的Mysql和Redis;

单体应用的时期,vivo官方商城业务发展尚处于初期,业务复杂度不高。首页、商详页、结算页逻辑比较简单轻量。

v1.0的架构完全能够满足支撑日常的新品及活动运营,且版本迭代更为快速。相比于ECStore 性能提升了至少两个量级,所以商城v1.0的重构非常成功。

2.2 商城 v2.0  服务化

官方商城 v1.0 架构升级之后,平稳地度过了一段时间。近两年,vivo手机产品越来越多,线上业务开始迅猛发展。

随之而来的是用户量级的快速增长,商城v1.0的单体架构弊端也逐渐暴露:

  • 飞速增长的用户访问流量让性能再次出现瓶颈,单体的数据库和Redis难以抵挡。

  • v1.0 架构对业务模块进行了分层,分层仅限于代码模块级别的拆分,没有从物理上进行隔离,单体应用愈发臃肿。

  • 所有研发维护同一套代码,项目工程维护变得困难。快速迭代的版本让模块之间分层的界限变得模糊,代码腐化严重,开发效率变得低下。

基于以上问题,我们开始基于业务模块进行垂直的系统物理拆分。新的系统架构采用主流的SOA架构(Service Oriented Architecture,即面向服务的架构)。

商城 v2.0 从2017年开始,以服务化为核心稳步进行拆分独立。我们得保证既有的业务不受丝毫影响的情况下独立模块,有人形容这个过程为“高速换轮胎”,动作稍有不慎,对系统来说都是致命的。

最终在花了近一年半的时间,我们实现了活动、商品、订单、优惠券四大核心系统的拆分。拆分出来业务线开始各司其职,提供服务化的能力,共同支撑主站业务。

vivo 全球商城:架构演进之路

(图2.2 商城 v2.0系统架构)

下面将介绍各个系统拆分的整个过程。

2.2.1 活动系统独立

官方商城作为vivo的唯一线上官方渠道,承载着所有新品的线上活动需求。每次的新品发布会,都是由商城系统负责完成。大量频繁的活动需求,引起频繁的商城版本变更、上线,引发我们的思考。

相比电商的核心交易链路,活动系统本身比较独立,不应与主线交易耦合在一起。因此在2017年年中,将商城中的专题页配置,新品发布会,抽奖,预约功能剥离出来,独立出了商城活动系统。

2017年8月,活动系统独立上线。新的活动系统开始承接新品、大促等各种促销活动需求。随着活动系统不断迭代发展,目前已经成为电商平台一个重要组成部分。

2.2.2 商品系统独立

商品系统是支撑整个电商平台的核心,是电商系统中最重要的组成部分。商品连接着用户和平台,通过商品的详情页可以完美地向用户展示产品内容,诠释产品内涵。

商城 v2.0 服务化,商品是这次整改的重点。

我们在思考v1.0架构带来系统性问题的时候,也开始思考如何通过这次拆分来对应未来的业务增长。商城v1.0商品模块亟待解决的问题:

  • 商品的品类创建受限,只有垂直类的手机和配件,无法支持全品类。

  • 商品不支持店铺、品牌维度,比较单一。

  • v1.0商品模块的查询性能低下,单实例Redis无法满足高性能、高可用。

  • 历史 v1.0商品接口和模型已经渗透到各个模块,完整地剥离出来比较困难。

商品系统的独立是带着以上的问题和思考进行的,大的目标是划清业务边界,彻底和商城解耦。我们希望分离后的商品系统能够更好、更快速地承接未来全品类的扩展,全面服务化。为进一步服务好商城主体业务夯实基础。

2.2.3 优惠券系统独立

优惠券是业界内常用的营销手段之一,每到大促、节假日、新品,都会发放大量的优惠券。与外部广告商合作、内购福利、保值换新等也以优惠券的形式承载。

随着营销活动力度加大,优惠券使用场景增多,优惠券系统问题也逐渐暴露:

  • 海量优惠券的发放,达到优惠券单库、单表存储瓶颈。

  • 与商城系统的高耦合,也直接影响了商城整站接口性能。

  • 针对多品类优惠券,技术层面没有沉淀通用优惠券能力。

优惠券系统独立需要解决的就是以上问题,独立后优惠券存储能力提升,支撑未来5年内的优惠券发放量级。整体发券接口性能也得到提升,发券由原来的异步发券、异步到账,优化到同步发券、实时到账。同时提供平台级优惠券能力,面向全公司业务,提供通用的优惠券营销能力。

2.2.4 订单系统独立

订单系统也有与优惠券同样的问题,随着用户量级的爆发式增长,性能问题逐渐暴露:

  • 数据不断累积,快要达到单表存储瓶颈,导致订单的查询和修改速度很慢。

  • 单机MySQL处理能力有限,并发量上来时直接拖垮整个商城的所有业务。

订单系统的独立,首次引入了 ES,Sharding-JDBC 等技术组件,解决数据量和高并发的痛点。订单系统上线后,无论是订单的存储量级还是下单的并发量级,都提高了不止十倍,至少满足未来 5 年的业务高速发展。

至此,商城核心系统拆分完成,各系统提供统一标准化服务,具备更纯粹的业务基础能力,与商城主站解耦,迭代效率大幅提升。

2.3 商城 v3.0  业务系统拓展

商城 v3.0 是针对商城业务快速发展,进行的业务系统完善。

这一阶段由于商城业务渠道不断扩展,促销玩法不断增多,商城衍生出很多独立的业务子系统。其中包含代销系统、CPS系统、促销系统 3 大业务系统。

vivo 全球商城:架构演进之路

(图2.3 商城 v3.0系统架构)

2.3.1 代销系统:商城与代销商品纽带

为了丰富自身的商品品类,支撑起更多的运营玩法,我们开始探索代销的业务,尝试对接品类优质的平台方。很多平台方也都支持系统对接,采用以销定采的销售模式。

代销系统就在此背景下诞生了。我们希望代销系统能够成为外部平台方和vivo商城之间的“粘合剂”,并能够提供以下的主要功能:

  • 支持两个平台商品数据模型的转换,支持部分信息二次编辑,更加本地化。

  • 实时同步平台方商品库存、价格、订单正逆向信息的同步。

  • 支持vivo商城用户的商品浏览、以及下订单服务,满足用户购物的完美体验。

代销系统是我们对接外部系统,引入外部商品售卖的一次尝试。代销的通用能力被我们完全沉淀了下来,能够持续支撑后续其他平台商品接入。

2.3.2 CPS系统:商城返利平台

CPS 系统的定位是 vivo 官方商城体系下的推广返利平台系统。商城的业务不断扩展,商城的业务群体也开始向外拓展。主要针对一些带货能力强的大V以及一些外部推广平台,以返佣的形式,最大限度发挥其带货能力。

随着用户群体以及推广平台接入,CPS 系统逐渐沉淀一些基础能力,目前支持 toB、 toC 通用接入能力。

2.3.3 促销系统:商城营销百花齐放

促销系统是商城的促销中心,承载着商城所有的营销玩法。

促销系统的独立,源于商城v2.0 架构无法满足不断增加的活动玩法,它解决了商城原有促销的以下痛点:

  • 繁杂的活动堆砌,没有严格活动优先级关系。

  • 新的活动需求的加入,改动量和影响点范围广,无法准确评估。

  • 促销性能无法满足活动量级,往往会影响商城主站的性能。

促销系统独立,与商城解耦,提供纯粹的商城营销活动玩法。促销系统还包括:商品计价与商品价格监控基础能力。

三、国际化

随着经济全球化日益加深,国产品牌纷纷布局海外,印度作为海外最大单一市场,拥有非常广阔的市场前景,顺应当地市场的需求,上线印度版官方商城提上日程。

2017年12月,印度vivo官方商城正式上线运营。

印度官方语言共有22种,目前已登记的语言超过1600种,支持多语言是国际化进程中首要课题。传统的 i18n 方案,能够解决基本的文案配置问题,但是项目需要走发布流程,维护成本非常高。

多语言文案系统标准化了文案需求的提出、翻译、测试、发布等流程,极大地提升了发布效率和文案质量。

vivo 全球商城:架构演进之路

(图3.1  多语言文案中心)

2020年11月,泰国 vivo 官方商城也正式上线运营。

与国内电商相比,海外电商业务需要覆盖多个国家/地区,每个地区都有自己的语言、时区、货币等等,如何使用一套代码同时支持多个地区,是我们必须要面对并且解决的问题。

经过3年时间的摸索和打磨,我们打造出了一套通用的全球化解决方案,包括多语言文案系统、多时区通用组件、多国家隔离框架、多机房域名部署方案等等,已经能够较好的支撑当前业务的发展需要。

vivo 全球商城:架构演进之路 vivo 全球商城:架构演进之路

(图3.2  多时区通用组件)

vivo 全球商城:架构演进之路

(图3.3  多国家隔离框架)

上述方案,抽象公共配置的思想以及相应的隔离技术点,即使是在非国际化场景中,也具有较大的参考价值。

海外市场复杂多变,语言文字、文化差异、地区标准、法律法规等不尽相同,地区发展阶段和基础设施成熟度也有较大差异。

挑战与机会并存,我们既要全力支撑业务发展,也要优先完成合规整改要求;我们既要提炼一套通用的国际化架构,也要满足本地化定制需求;我们既要合理应用发达地区高网速,也要兼顾欠发达地区页面加载性能优化。

“more local more global”,随着全球化进程的加深,我们会继续锤炼全球化架构,锻造出更加健壮的国际化/本地化产品。

写在最后,本篇主要是简要的介绍vivo官方商城这5年来的一些大的架构历史变迁,不做过多的技术解读。

这里的介绍只是商城技术背后的冰山一角,后续我们会出更多相关系列文章,去详细介绍每个系统的架构与核心技术。

作者:vivo 官网商城开发团队

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
vivo 全球商城:从 0 到 1 代销业务的融合之路
代销是vivo商城已经落地的成熟业务,本文提供给各位读者vivo商城代销业务中两个异构系统业务融合的对接经验和架构思路。一、业务背景近两年,内销商城业务的发展十分迅速,vivo商城系统的架构也完成了从单体往分布式的演进。我们在vivo商城服务化方向做了很多的努力,基础服务的能力逐渐沉淀下来。2019年我们也开始在产品功
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
vivo 全球商城:订单中心架构设计与实践
一、背景随着用户量级的快速增长,vivo官方商城v1.0的单体架构逐渐暴露出弊端:模块愈发臃肿、开发效率低下、性能出现瓶颈、系统维护困难。从2017年开始启动的v2.0架构升级,基于业务模块进行垂直的系统物理拆分,拆分出来业务线各司其职,提供服务化的能力,共同支撑主站业务。订单模块是电商系统的交易核心,不断累积的数据即将达到单
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这