前言
2017双11大促刚刚过去,苏宁易购交易系统的请求量和订单量在双11当日呈现指数级的增长,更是实现了7秒破亿的最快破亿记录,苏宁易购交易系统在大促期间平稳运行,完美度过双11。作为苏宁易购交易系统负责人,我给大家介绍一下交易核心系统之一,库存系统的架构演进与实践,并介绍库存系统是如何筹备和应对双11的流量洪峰的。本文推荐架构师、技术经理、开发工程师、技术总监等群体阅读,希望能够让大家受益。
库存业务介绍及面临的挑战
首先介绍一下库存系统的定位,它主要为企业级的经营性可用商品库存获取应用,与平台商品目录紧密关联,定位为苏宁核心平台之一。平台级商品库存支持线上、线下销售渠道和营销活动对经营性可用商品库存的查询,支持平台商品库存锁定、解锁、增加、减少等库存核心服务,并为平台商户提供服务支撑。
库存作为电商交易的核心系统之一,它贯穿苏宁的整个业务价值链条,不论从采购线的采购、交货、调拨、退场、入库过账、实物盘点等环节,还是销售线的浏览、下单、发货、出库过账等环节,再到客服支撑、经营分析报表、预测补货、多平台销售支撑等大数据应用,都和库存系统紧密关联。
库存从业务模式上分为自营库存和C店库存。自营库存即苏宁自采自销的库存,C店库存即通过开放平台入驻的平台商户所销售的库存。
库存中心聚焦的是销售库存,即支撑苏宁销售和交易相关的所有库存服务。而苏宁的实物库存是在苏宁的物流平台进行管理的。两套库存的定位不一样,但两套库存之间具有一定的关联,且通过定期严谨的库存对账机制来确保两套库存数据的一致。如图1。
图1 系统上下文图
库存系统从业务架构上分为库存交易、库存管理、异常管理、运维管理四大组成部分。
库存交易部分分为销售锁定、销售解锁、交货锁定、交货解锁、数量查询、库存状态查询、状态下传、数量下传、活动预锁、活动预解锁、活动库存查询、活动管理等功能模块。库存管理部分分为采购、调拨、退厂、移库、盘点、对账、状态计算、销售过账、库存同步、多平台分货等功能模块。库存状态是指定义库存有货、无货的一种状态标识,通过实现库存状态,可大大减少外围系统对库存数量查询接口的调用,比如商品详情页只关注商品有无货,通过库存状态即可支持。业务架构如图2。图2 业务架构图
库存系统主要面临以下几个挑战:
1. 热点争抢
针对同一个商品,比如秒杀、团购、打折促销等活动商品,如何支撑高并发库存扣减服务。
2. 周转率
如何提升库存周转率,最大化利用企业资金,做到销售最大化。
3. 避免超卖
避免超卖是库存系统架构设计和系统实施的底线原则。
4. 系统扩展性
如何建设出可无限扩展的库存架构,在系统扩展过程中,各部署节点都需要具备无限扩展能力,而常见的瓶颈如数据库的连接数、队列的连接数等。
库存系统的架构演进
苏宁库存系统的架构演进主要划分为4个阶段:
阶段1: 2005-2012,线下连锁时代,电商初期架构,当时系统采用WCS/POS+SAP构成,库存属于SAP系统中的一个业务模块;
阶段2: 2012-2013,互联网O2O电商时代,当时系统进行了前台、中台、后台架构的分离,独立出SAP库存系统;
阶段3: 2013-2016,多平台销售战略时代,苏宁入驻天猫,当时系统采用“去商业软件,崇尚开源”思路,新建JAVA自研库存系统;
阶段4: 2016-至今,库存系统多活时代,分机房部署库存系统,基于大数据库存分货引擎实现多机房部署。
如图3。每个阶段库存架构的详细内容会在下面章节展开。
图3 架构演进图
电商初期-总体架构
线下连锁时代的电商初期总体架构,线下销售采用POS客户端系统,线上销售采用WCS (IBM WebSphere Commerce)(JAVA)系统,服务端采用SAP-R3商业软件。如图4。
图4 电商初期-总体架构图
电商初期-系统交互
线下门店POS系统和线上主站WCS(IBM WebSphere Commerce)系统调用SAP-R3提供的库存检查、库存锁定、库存解锁等服务,同时,为了减轻线上主站对后端服务系统的压力,SAP-R3会将库存数量的变化主动推送给WCS系统,在WCS系统本地暂存一份影子库存数据,WCS商品详情页加载商品信息时,先查询本地的影子库存,判断如果影子库存过了保鲜期(有效期),则进行库存懒加载,实时调用SAP-R3的库存数量查询服务,再更新本地影子库存;另外,主站搜索系统也是基于WCS本地的影子库存数据来创建和更新索引。系统交互关系如图5。
图5 电商初期-系统交互图
电商初期-架构分析
电商初期架构主要存在以下问题:
1. 订单、库存等核心业务集中运行在一个系统,耦合性太强,不易改造,业务扩展性很差;
2. 为了快速占有电商市场,业务快速上线,选型SAP/WCS商业软件,受制于厂商,软件维护能力薄弱;
3. SAP仅支持单数据库,架构不具备系统扩展能力,无法支持双线日益增长的交易处理。
为了解决上述架构问题,我们自然而然想到了进行业务系统的拆分。我们花了近两年时间进行了大刀阔斧的前、中、后台架构的分离。
前台、中台、后台分离架构
基于前台浏览、销售交易、销售履约&运营管理的业务划分和归类,我们对系统进行了前台、中台、后台的架构分离。前台由各个销售平台组成,比如易购主站、门店POS系统、电话销售,以及其他销售平台,负责用户体验和商品展示;中台是核心交易平台,提供库存、寻源、价格、商品、促销、会员等基础服务、以及提供云购物车、订单等组合服务,同时中台提供诸葛等一系列基于大数据的报表和应用,后台是提供苏宁自营(供应链、分账、记账、结算、发票、采购等)、商家运营(店铺、商品、库存、订单、价格、供应链管理等)的一套运营管理平台、还有大物流平台。如图6。图6 前中后分离-总体架构图
新建平台库存系统,平台库存由库存路由系统CIS(JAVA)、自营库存系统SIMS(SAP)、C店库存系统CIMS(JAVA)三个系统组成,浏览线的寻源系统调用平台库存的库存数量查询服务,交易线的订单中心调用平台库存的销售锁定、销售解锁、交货锁定、交货解锁等服务,SAP-ERP同步采购库存数据至自营库存系统SIMS,开放平台同步商户api或页面维护的C店库存数据至C店库存系统CIMS。平台库存将库存状态数据同步至寻源系统。如图7。
图7 前中后分离-系统交互图
前中后台架构分离后分析如下:
1. 将订单、库存等业务从SAP-R3拆分出独立系统后,解决了业务扩展性的问题,符合“高内聚、低耦合”的架构原则;
2. 自营库存系统SIMS还是采用的SAP商业软件,仍然受制于厂商,但库存路由系统CIS和C店库存系统CIMS是JAVA自研系统,软件具备维护能力;
3. SIMS(SAP)仅支持单数据库,自营库存系统SIMS仍然无法支持双线日益增长的交易处理,系统性能有一定的提升;
4. 针对抢购、团购类活动场景,容易造成库存热点,无法有效支持高并发的库存扣减。
针对以上架构问题,我们在架构上进一步提出优化思路:
1. “去SAP化”,去商业软件,实现自开发自营库存系统;
2. 搭建分布式架构,采用应用集群、数据库的分库分表、集中式缓存等技术提升系统处理能力;
3. 针对抢购、团购等活动库存场景,新建纳秒购系统来提供高并发、高性能的库存服务,和普通库存进行独立设计和分开部署。
自研库存架构
自研库存系统,将库存系统从职能和系统上划分为库存交易和库存管理。库存交易由库存路由系统CIS、自营库存交易系统GAIA、C店库存交易系统CIMS、抢购库存系统AIMS 四个系统组成。
库存路由系统CIS提供库存的统一服务路由、服务流控、服务降级、接口熔断等系统组件;自营库存交易系统GAIA和C店库存交易系统SIMS提供高性能的库存数量查询、销售锁定、销售解锁、交货锁定、交货解锁等库存服务,库存交易系统的数据由自营库存管理系统SIMS和商家库存管理系统SOP提供数据同步。苏宁库存可以在易购平台、天猫平台、当当平台等多平台上进行销售。基于大数据的智能分货引擎在库存管理系统SIMS中实现多平台分货。
抢购库存AIMS提供基于缓存的高并发库存服务,支撑爆款抢购、爆款预约、大聚会等活动场景。
如图8。图8 自研库存架构-总体架构图
新建GAIA系统(JAVA)替换 SIMS系统(SAP)自营库存的交易职能,新建独立的纳秒购库存系统以支撑抢购、团购等大促活动。纳秒购库存系统,基于“架构独立、库存预锁、数量缓存化”的思路进行搭建,提供高性能的库存服务。如图9。图9 自研库存架构-系统交互图
自研库存系统是基于苏宁技术体系搭建的一套高并发、可扩展的架构。
1. 库存系统通过使用苏宁自研的RPC调用框架(rsf)对外提供实时服务,通过使用kafka组件进行消息分发和消息订阅,对外提供数据服务和接收外部数据;
2. 应用使用wildfly standalone集群,数据库使用MySQL集群,数据库采用读写分离部署;
3. 运维人员的库存管理通过使用ES(Elastic Search)平台提供商品和商家等多维护的库存查询和管理服务,管理端对数据的抽取通过读vip访问MySQL读库。
见图10。
图10 自研库存架构-部署架构图
以自营库存交易系统GAIA为例,库存从数据架构上进行了水平和垂直拆分,分为公共库、业务库和日志库。
1. 公共库存放主数据及基础配置信息,包含分库分表规则、job配置、ATP检查配置、公共基础数据等,公共库为一主多从,可通过本地缓存、集中式缓存、扩展从库来减轻对主库的压力;
2. 业务库提供核心库存交易服务,存放核心数量表、销售锁定表、交货锁定表等业务数据,业务库按照商品编码hash取模进行分库分表,核心表分为1000张表;
3. 日志库存放各类接口的交易流水数据,记录各类服务的日志、审计及库存对账等信息,日志库按照外部单据号hash取模进行分库分表,核心表分为1000张表。
对于库存系统来说,发生一笔库存交易,通常需要同时写入业务库和日志库,这就需要解决分布式事务的问题。根据CAP(C(Consistency)、A(Availability)、P(Partition tolerance))理论,三者是无法同时满足的。我们舍弃了Consistency(实时一致性)特性,在满足分区容错性和可用性基础上,确保事务提交的结果最终一致。
为了最大化的提升库存交易的性能,我们采用“实时扣、异步加”的处理原则,对于库存数量的扣减采用实时处理的方式,而对于库存数量的加回采用异步的处理方式,因为库存数量的加回不存在业务上失败的可能,业务上一定能够确保成功,而库存数量的扣减是存在业务并发下失败的可能的。
数据架构见图11。
图11 自研库存架构-数据架构图
通常的抢购、团购、秒杀等活动业务对于库存业务来说具有以下挑战:
1. 瞬间流量巨大,造成库存热点的争抢;
2. 高并发下应用、数据库负载连接突然飙升;
3. 引起黄牛效应。
针对以上挑战,我们有以下应对方案来确保系统的稳定性:
1. 库存交易处理缓存化,避免数据库层面锁资源的争用;
2. 架构分离,对活动库存的业务进行隔离部署;
3. 通过构建基于IP/UA访问策略的WAF防火墙,通过应用层的业务流控和系统流控,通过风控(人机识别)等技术手段来应对黄牛的恶意流量。
抢购库存的系统构建:
1. 销售准备:活动营销系统创建活动时,先进行库存数量的预锁,将活动库存和普通库存逻辑分离;
2. 销售执行:活动商品详情页展示时,会进行活动库存数量查询,直接访问活动库存数量缓存;用户在提交订单时,会进行支付前检查,这时我们进行库存的临时锁定,系统通过缓存redis的lua(EVAL)原子命令执行扣减脚本以支持高并发的库存扣减服务,同时对db进行insert插入一条库存锁定记录,避免产生数据库锁资源的争抢;顾客在支付完成后,会进行库存的正式锁定,系统会更新用户提交订单时插入的锁定记录的锁定状态,通过异步进行db库存数量表的更新达到数据库的消峰目标。
通过库存数量缓存化、活动库存的部署分离、数据库数量表扣减更新的异步化,我们实现了高并发的活动库存系统架构。
抢购库存的实现示意,如图12。图12 抢购库存-系统架构图
自研库存架构实现了架构的完全开源自实现,并搭建了高并发的分布式架构,但在电商业务蓬勃发展,订单屡创新高的背景下,依然面临一些挑战:
1. 扩展痛点:受限于数据库的连接数瓶颈、Redis服务器的连接数瓶颈、队列服务器的连接数瓶颈等因素,导致应用集群无法无限扩展;
2. 机房容灾及机房容量:机房断电,电缆被挖,造成整个苏宁易购交易系统瘫痪;单个机房容量受限,无法创建更多的服务器;
3. 故障隔离:某数据库分片出现宕机,从而影响整个交易;某redis分片出现宕机,从而影响整个交易;
4. 热点瓶颈:虽然通过构建缓存化支持库存交易,但单个商品的并发扣减仍然存在上限
为了解决上述问题,我们开始开展库存的单元化和多活架构构建。
多活库存架构
为了解决扩展痛点、故障隔离、热点瓶颈等架构问题,我们先实现了库存交易系统的单元化部署。
系统单元化有以下几个原则:
1. 单元封闭
单次请求需要封闭在一个单元内完成,严谨跨单元操作;
2. 高可用
单元内的所有部署节点,也要遵循高可用的原则,不能出现单点故障;
3. 无限扩展
单元之间可以进行无限的扩展;
4. 对外透明
库存系统单元化部署对外部调用系统是完全透明的;
5. 服务熔断
单元化系统内提供的服务需要能够支持服务熔断,单元不会因为一个服务的问题导致整个的单元收到影响。
单元采用商家编号hash取模的维度进行单元的划分。多个单元组成一个单元组。跨单元的一些管理功能基于ES(Elastic Search)平台提供服务。
库存单元化示意图如图13。
图13 库存单元化示意图
库存服务属于竞争型的服务,不能在子机房之间实现数据共享,因此,我们基于大数据智能分货引擎在主机房进行库存数据的智能调拨和分货,能够基本实现交易单元中库存业务在本机房内提供服务,同时机房之间建立数据库的互相备份,当A机房出现故障,可由B机房完全接管。
如图14。图14 库存多活架构示意图
库存如何应对双11大促
对公司双11大促的 活动预告及销售目标进行详细评估和分解,转化成库存系统的核心服务的SLA,确定库存系统的核心服务的TPS目标。
基于容量预估出来的TPS目标,评估库存的机器是否需要扩容,比如jboss集群是否需要扩容,db是否能够支撑,db是否需要拆库拆表,db磁盘容量是否足够,服务器负载是否足够等。
所有交易接口需要设定合理的流控阀值,以确保系统不会挂死;梳理所有接口的调用系统和业务场景并明确业务的优先级,假设系统因为某服务导致性能出现瓶颈,根据业务优先级逐步调整流控阀值;业务流控或系统流控要实现用户的友好提示;对于后端依赖系统,如果出现超时或宕机,则定义降级策略,确保服务请求的快进快出。
大促前,我们会进行多轮的生产压测,最重要的是单系统的接口压测和端到端全链路压测。通过单系统服务接口压测,我们排除接口潜在的性能瓶颈并针对性的优化,能够清楚认识负责系统的单接口所能支持的并发上限;通过生产真实流量回放的端到端全链路压测平台,进行全链路的生产压测,发现真实流量下的系统压力情况,和资源情况,提前发现性能瓶颈和潜在的系统风险。性能测试是大促筹备最为关键的一环。
提前对系统的各方面进行全面的健康检查,比如db磁盘的容量、连接数、topsql,缓存的内存使用率、并发命令数和连接数,消息队列的连接数,各节点的cpu负载情况,排除单点故障,排除虚拟机的资源争用问题,排除高可用问题(同一物理机多应用节点)等。
大促前会进行生产重大版本的回溯,针对新提供的服务,新支持的业务或活动形式要重点关注,确保新增业务的服务可靠性和稳定性;大促前还会进行事故的案例回溯,回顾以往发生的生产事故,排除有类似的事故风险,确保问题不会重复的发生。
大促筹备的几大环节如图15。
图15 双11筹备示意图
出处:https://mp.weixin.qq.com/s/W3-jgzbck910OuEF9WO5wg
版权申明:本文为《程序员》12月双11技术决战专题的原创文章,未经允许不得转载。
-END-
架构文摘
ID:ArchDigest
互联网应用架构丨架构技术丨大型网站丨大数据丨机器学习
更多精彩文章,请点击下方:阅读原文