专栏/B站「会员购」系统演进那些事

B站「会员购」系统演进那些事

2020年08月28日 07:11--浏览 · --喜欢 · --评论
粉丝:164文章:8

一、个人简介

    2017年5月加入B站电商技术部。

    2017年5月 - 2018年10月,团队高工,参与电商系统整体架构设计,负责商品、库存、营销、供应链、用户服务等系统从0到1搭建。

    2018年10月 - 至今,团队leader,负责商品、库存、履约、供应链、店铺、首页/商详页等业务开发。

二、写这篇文章背景

    1、基于过去3年的历史背景,记录下每个阶段的一些小故事,由衷感谢期间每一位"战友"。同时担心时间越久,自己记忆越模糊。

    2、对过去3年电商系统架构演进中,遇到的问题和踩过的坑,关于大促稳定性保障问题,做一些总结分享,希望对各位同学有所帮助。

三、开荒

1、电商组的成立

    我是17年5月初加入电商技术部,电商后端研发只有H哥和我俩人,H哥是我的leader,良师益友,前同事,5月我们临时支持了另外一个业务线开发,6月开始正式进行电商产品需求评审和开发。6月到7月间,我们俩边需求讨论、边开发、边招人,忙得不可开交,同时T哥(T哥是技术总监)要求我们50%+精力要花在招人上,否则肯定cover不住新业务研发。招人是个头疼事,因为候选人都会问目前团队规模,系统架构现状,我们的回答是“目前团队就俩人,系统目前还没有,业务前景很好,我们要快速搭建一套电商系统”,很多有经验的候选人可能觉得我们是“忽悠”,毕竟业务刚起步、公司体量也没法和大厂相比,背景稍好的候选人都没有选择我们。后来我们降低了招聘要求,结果有候选人还是觉得创业项目节奏快压力大,没有选择我们。

    6月15日,H哥高兴地给我介绍一位新同事:KB,KB入职的当天下午,就参加了电商第一个核心系统“商品中心”技术评审,当时我是这个系统owner,屋里坐了十几个人,包括产品、前后端研发、测试等同学,背后坐着H哥和T哥,评审内容比较“粗糙”,整个商品中心的数据结构和关系,大约15张表(因为技术方案设计时间不到1.5天),评审比我想象中顺利,整体方案基本没啥问题,结束前我特意问了下T哥有没有问题,T哥给了一个坚定的回答“没有问题”~。第二天我们3人分工开始了电商商品中心系统第一行代码的编写,2.5周完成电商商品后台系统开发和提测,感觉睡觉的时候都在敲代码,哈哈~

    6月底前后,入职了4位新同学,Q哥(技术大牛,前同事)、小胖和TL(团队开心果)、DH,电商组正式成立,7人组支撑了电商系统V1版本的所有开发上线,H哥、Q哥和我工作经验比较久,KB、小胖、TL、DH都是2年左右经验。

    继商品中心后,我们陆续开发了交易中心、供应链、UGC、营销、首页/列表页/商详页/下单等核心系统,后面长达9个月的时间里,电商所有大小项目都是倒排开发上线,那段时间压力还是非常大的,加班加班加班,因为大家知道活必须得干完,否则整个大部门就可能死了。

    11月1日,电商系统V1.0 正式上线对外开放。

2、电商V1.0技术架构

2.1 技术栈选型,高瞻远瞩

    最初在技术选型上,因为当时H哥和我都没Java经验,我对php比较熟悉,我们也在纠结Java还是php,H哥最终定了使用Java,当时对我们来说是啃了一些硬骨头。但是现在看来,H哥的决定高瞻远瞩,有利于之后人才引入,接入Java成熟生态框架等,避免了php/python改造为Java系统的成本。

2.2 电商系统V1.0 架构

H哥、Q哥和我,一起设计了整个电商系统V1.0 架构图。

Q1:UI服务层和基础服务层是否要增加 一层API网关?

A1:当时确实考虑到这个问题,考虑到发展阶段和研发人力,没有增加API层,如果当时再多5个人,可能会加这一层:)

Q2:店铺和仓储为什么在一个微服务系统呢?

A2:因为业务服务模块已有11个,中间件2个,研发是7个人,服务数量远比人多,再新增服务模块维护成本太高,当时shop代码很少,所以仓储写用这个服务模块开发上线了

电商系统V1.0 架构图:

2.3 研发规范

    用H哥的话,是Q哥把团队从“游击队”变成了“正规军”,包括搭建spring cloud全家桶、业务服务代码架构规范、阿里Java编码规范等。

3、第一次BNJ大促抢购交学费

    18年初的一次电商BNJ大促抢购,面对热情的用户,电商核心流程出现了故障,包括首页、商详页到交易都出现了不同程度的故障,交了一次昂贵的学费。当时我们做了一些稳定性保障准备,压测QPS:详情页1w、结算1000、下单400,后来复盘后,现有系统架构、活动保障准备工作,都远远不够。组内做了详细的case study,那段时间H哥和团队压力都非常大。

3.1 总结   

  • 研发首先要保证系统稳定性,不能只关注业务功能开发快跑。大促前,充分完成稳定性   

  • 保障工作,保障高并发下电商核心流程用户体验。

  • 和大厂非常强大的基础架构/中间件不同,公司的基础架构在持续搭建和完善中,我们需要考虑有时中间件不稳定的情况下,对系统增加容错降级,最大程度保证用户体验。

  • 从0到1搭建系统,从未知风险到预知消除风险的转变,被现实无数次毒打后,不得不这样做,现在的大促系统稳定性都是血和泪换来的。

4、2018年Q2-Q4 卧薪尝胆 系统打磨

    18年BNJ后的两次大促活动,包括日常功能迭代,我们还是会出现一些线上事故,有一段时间我们几乎每周都会有线上问题。因为组织架构调整,L哥做了我的老板,我也开始担任团队leader,期间我owner的一次白天压测出现了较大的线上事故,L哥帮我挡了很多压力,和我们一起做了case study,一起通宵压测,一起战斗。同时感谢L哥当时对我的包容和信任。期间的技术优化工作,请参考下文 “电商架构&核心系统优化”。

5、2019年FD了"BNJ抢购BOSS”

    18年12月初,我和L哥说这次BNJ活动比较早,我们是不是早点准备BNJ抢购稳定性保障工作,12.7 BNJ稳定性保障小组成立,我担任组长。因为之前几次电商大促抢购都出现了各种大小问题,而且面对比第一次BNJ抢购更热情的用户,预估QPS会提升2倍以上。那两个月,是我在公司心里压力最大的两个月。

    19年的BNJ抢购在情人节晚上,当天运营、产品、技术各部门同事都很紧张。离抢购开始还有3个小时,运营大佬突然找我,问我“今晚万一系统挂了,可能的故障原因有哪些呢?我们要提前准备事故公告和RP讨论”,当时我心里一万个“CNM”,不过还是提供了 3个可能发生的故障原因。最终BNJ商品在22:33准时上架开抢,系统接口QPS监控飙升,8秒内锁定5000个库存,系统非常稳定,我们顺利FD了"BNJ抢购"这个BOSS(当时的感觉 就像当年WOW里FD最终BOSS 拉格纳罗斯),

    电商组所有小伙伴和我的压力一瞬间都释放了,之前几次通宵压测和大量系统优化工作都没有白费,准备好的事故公告也不用发了。那天事业部老板当面表扬了我们~。从19年2月的BNJ抢购活动后,电商核心流程系统再没有发生过较大事故。

6、电商架构&核心系统优化(2018年Q2 - 2019年Q1)

6.1 首页/商品详情页优化

6.1.1 背景

  • 首页和详情页是用户流量入口,需要保障可用性。

  • 18年初的BNJ大促抢购,首页服务出现不可用,性能不满足大促要求且缺乏快速降级能力。详情页出现redis热key,未按真实场景压测(真实场景上万个用户id,压测只有500个用户id)。

    6.1.2 解决方案

  • 首页接口:多层降级缓存,hystrix熔断器,redis降级缓存、本地降级缓存、客户端降级缓存,保证首页可用性100%。

  • 商详页对商品热key进行hash拆分打散到redis集群各实例,解决热key问题。

  • 商详页强依赖商品和库存数据。对弱依赖数据,比如评论、商品推荐服务,设置调用限流,超过限流阈值请求走降级数据,因为抢购时用户只关注价格、库存,下单按钮,不会关注评论和推荐。

首页多级降级缓存


6.2 依赖资源部署隔离

6.2.1 背景

    18年初的BNJ大促抢购,UGC的DB QPS达到45000+,DB物理机CPU使用率达到3000%,32核中UGC占用了20+核。UGC的流量突增导致部署在同一台DB物理机的商品、交易服务性能大幅度降低,如何做到非核心业务挂掉,不影响电商主流程。

6.2.2 解决方案

  • 服务分级,物理隔离,保证非核心服务流量突增或挂掉,不影响核心服务可用性。

  • L0:商品、交易,L1:营销、供应链,L2:UGC、活动、消息中心。

  • 按服务分级,核心服务物理隔离部署。

6.2.2.1 电商系统db架构优化

 6.2.2.2 电商系统redis架构优化

6.3 多层限流方案

    限流是高并发流量下,防止核心系统崩溃的首要方式。因为没有对接口设置限流,或者限流值设置不精准,我们也踩过几次坑。目前交易核心流程相关接口,一般我们按照压测QPS上限的70%-80%设置限流。

6.4 核心交易流程性能优化

6.4.1 背景

    db库存扣减操作遇到单行行锁性能瓶颈,交易也没有做分库分表,对数据库压力是巨大的,也满足不了19年BNJ抢购活动性能要求。调研了下行业解决方案,也参考了事业部另一个技术团队的解决方案,最终决定使用异步下单,QPS提升了3倍。

6.4.2 解决方案

    通过异步批量下单,批量扣减库存、批量插入订单数据,下单接口QPS提升3倍。

7、活动稳定性保障工作

7.1 电商全链路压测

7.1.1 背景

    常规压测都是单个接口维度压测,比如单独压商详页,但是真实场景是用户流量会打到核心流程的所有接口。同时公司对用户体验要求很高,我们曾经因为活动开始延迟了几秒发公告向用户道歉。

7.1.2 解决方案

  •  核心流程接口并发压测,根据历史大促流量预估核心流程各接口占比,并发压测,如果这个情况下扛得住,可以提升大促极限情况下系统稳定性。

  •  不要遗漏交易正逆向流程任何一个流程接口,漏掉的往往会出线上性能问题。

  •  模拟真实场景,比如压测访问详情页几万到几十万用户id、用户等级分布、商品限购设置、活动策略在商详页或是购物车,购物车热门商品数量等。

  •  核心用户体验校验,比如定时开售、各种营销活动、优惠券生效等时效性体验。比如风控答题,用户是否可以接受题目内容,因为题目太难也会被用户投诉,甚至产生舆论风险。

四、初探

1、混沌工程 - 故障演练

    公司早期中间件大都使用开源版本部署线上环境,在不断建设和完善过程中,我们也遇到过了一些中间件如redis、mq不稳定的情况,,对线上业务和用户体验都造成了损失。最早期我们是通过在测试环境,人工改业务系统配置,重启服务来制造故障,同时拿个手机观察各故障类型下APP端表现,曾经一位同学花了周末一整天来做这件事,成本很高。我们在想能否通过系统化方式提升故障演练效率,我们参考了netflix的chaosmonkey、《混沌工程:NETFLIX系统稳定性之道》设计理念,目标是通过故障演练系统,覆盖更多业务和接口,提供更多故障类型能力,提升演练效率。在线上出现各类故障情况下,实现自动降级或最快速度恢复,提升用户体验,减少线上损失。

故障演练实验场景举例: 

  • 各个业务系统接口超时或异常下,交易核心流程接口表现是否符合预期,比如预期ugc、营销服务异常,不影响详情页打开、交易下单等,比如预期商品服务异常,详情页可以打开,详情页出降级商品数据,但是无法下单。

  • redis超时或异常下,交易核心流程接口表现是否符合预期。

    目前我们在开发故障实验平台,方案:测试环境容器内部署chaosblade制造故障,借助QA团队自动化测试平台校验系统接口稳定性,故障实验平台会记录演练结果数据。故障实验平台目标是业务方可以自助使用平台化故障演练工具,自助查看故障演练实验结果数据,方便业务方做系统优化。

  • 故障实验流程


2、全链路追踪系统 - Skywalking

    公司业务线和技术栈较多,公司的全链路追踪系统基于golang搭建,我们对接后,发现对java支持有一些偏弱,因此我们决定自建全链路追踪系统。调研行业内开源产品,如zipkin、cat、skywalking、pinpoint。我们选择了skywalking,skywalking优势是接入端无代码侵入、UI功能较强、已加入apache孵化器。搭建过程还比较顺利,一个季度完成了skywalking-server和电商所有子系统的接入完成上线,并且我们做了故障演练和压测,保证skywalking异常下对业务系统无损。电商skywalking上线后,有其他BU同学慕名而来,主动联系我们要求接入Skywalking,我们也帮助他们顺利完成了接入。

  • 电商系统拓扑图

  • 接口Trace追踪

3、通用对账平台

    微服务分布式架构下实现数据一致性始终是有挑战的问题,电商微服务数量50+,数据库15+。目前行业内大部分都采用最终一致性方式来解决该问题,每个系统开发对账较分散,开发和管理成本也较高。为了降低对账开发成本,统一管理电商对账任务,我们开发了“通用对账平台”,后端同学自学了vue框架,业务方开发groovy对账脚本,就可以完成对账任务开发,大大降级了对账任务开发成本。新增对账任务半小时就可以开发上线。比如配置db和es数据对账,熟悉平台流程后,10分钟即可完成配置上线。

  • 对账平台架构图

  • 通用对账平台界面 - 创建对账任务

4、分布式事务框架 - Seata

    通用对账平台解决了最终一致性问题,但是类似于金融行业对金额要求强一致性是支持不了的。 针对交易部分场景需要强一致性,我们调研阿里开源分布式框架Seata,在生产环境搭建了Seata-server,目前在电商几个业务场景里实验应用,解决分布式长事务强数据一致性问题。

  • Saga模式状态示意图


五、小结

    1、系统架构演进都是基于业务发展阶段、团队规模和能力、公司基础架构等综合因素,需要一步步脚踏实地搭建并逐渐完善。时刻关注系统架构是否满足业务的快速发展,持续调研行业内适合目前发展阶段的前沿系统架构和技术,应用到自己开发的系统,可以使用开源,也可以基于开源方案和思路自研。

    2、对线上系统保持敬畏之心,做好每次大促前的稳定性保障工作,提前发现系统潜在风险并优化解决。

  • 分享一段阿里资深技术专家崮德写的文章:

    我觉得一个工程师,一定要敬畏手头的工作,因为如果自己的一个疏忽,可能就会导致一个硬件或者软件事故,影响很多很多的用户。但是工程师的工作是千头万绪,有很多很多问题需要解决,那该怎么找到其中的关键点呢?我觉得吧,一定要时不时的停下手头的工作,环顾下自己的工作,看看里面哪些问题是只要自己个人投入足够时间就可以解决的,哪些问题是需要多方协调,需要其他资源投入才可以解决的,特别是对于第二种情况,一定要有危机感,一定要有警惕性和前瞻性,因为这种问题,可能就是我说的关键点,需要提高优先级来解决。

    可以在睡觉前,上班途中,下班路上,多回顾下自己平时的工作,移除掉细枝末节,然后把几个大的功能块提出来好好思考下,他们互相有什么关联,需要什么前置工作,会调用哪些资源,有什么表面风险,注意,我这里提到的是表面风险,因为,深层次风险是很难仅仅通过大脑思考就能暴露的,他需要在你具体工作中才会暴露,这个也就是凸显了这样的思考重要性,因为你通过思考,可以有强烈危机感,可以 sense 到表面风险,然后 focus 在这些问题解决中,不断挖掘深层次风险,及早排除地雷。

    一个优秀工程师和一个平庸工程师的最大区别就是,谁有火眼金睛及时识别到问题在哪里,危机在哪里,及时提前准备解决这些危机,而不是在问题发生后,不知所措,两眼一抹黑,自乱阵脚,毫无解决思路。

求贤(哔哩哔哩专栏求点赞,求关注,求推荐):     

    B站电商也称「会员购」,是哔哩哔哩的二次元电商平台。我们是B站多元化商业收入的重要航道之一,同时也是B站增长最快的潜力业务。我们寻找志同道合的伙伴一起寻找我们的One Piece。

投诉或建议