程序员人生 网站导航

1号店交易系统架构如何向「高并发高可用」演进

栏目:框架设计时间:2016-07-01 15:41:59

轻量级电商的架构和痛点

图片描述

大家看上图,1个轻量级的电商网站利用架构就是这样的,比如说你现在想做1个电商网站,你是创业公司,两3个人开始做,估计架构就是这样的。前端有PC、App和H5,有表现层、业务逻辑层和数据访问层等。

重量级的电商网站利用架构是怎样重的呢?很简单,随着业务的扩大,业务量多了、代码量多了、数据量大了、并发量高了。1号店是1家电商网站,但严格来说其实不是百分之百的互联网公司,我们更多是业务驱动型而不是技术驱动型公司。由于技术是为业务服务的,反过来讲,技术也能够驱动业务,如果我们的技术能力支持不到1号店的业务体量的增长,支持不了那末高的并发量的话,网站很容易就挂了。

1些轻量级电商网站的架构痛点是甚么?

图片描述

首先说它的特点,业务高速发展,业务情势多样,人员范围爆增。这里所说的人员更多是技术人员,1开始是两3个人,多是面对面的,后来变成几10人、几百人乃至是几千人上万人的范围。固然它的要求量、并发量、数据存储量都非常的高。

痛点也很多,首先是代码耦合,1开始可能就1个人就全部弄定了。由于1开始就1、两个人,不需要那末多。但从业务真个增长来看,1、两个人进行业务支持就有问题了,业务响应慢,业务相互影响。还有在出现问题时定位很难,有的时候还会责任不清,遇到1些相互扯皮的情况,表现出来的就是系统不稳定。

表结构也非常混乱,今天来1个业务加1个,明天来个业务又加1个。数据库单点,也是我们非常大的痛点,1旦数据库挂了系统就完全崩溃了。

还有监控预警的问题,这是1个非常大的痛点。我们知道类似支付宝红包、微信红包等的监控预警乃至是秒级的,分钟级确切是不够用,不可能说发1个红包,1分钟还没有抢到,用户会1直不停地戳屏幕,对系统带来的压力反而更大。

图片描述

所以,这个时候我们就需要做1些扩大性的工作。最简单的就是按业务扩大,1个小公司大概到10个、几10个人左右,大概会做这样的工作。如网站上的表现层,1开始页面代码都耦合在1起,然后我们会把详情页、搜索页、团购辨别,包括域名也会辨别开。渐渐的业务多了以后,会把普通购物、团购、虚拟业务等剥离开来,从数据库层来讲,渐渐会把产品、用户、定单及其他1些业务数据等都进行分拆,主要是从物理上隔离开来。这个时候整体来讲,架构本身变化不大,只是简单的切分1下。固然这个时候产品、用户、定单等这个层面的划分要有1定的规则和边界。

电商网站演进之路

1个小网站变成1个大网站是1个架构演进的进程。举例子来讲,现在有1个老师,他讲课的时候有很多学生都在同1个教室,这边是1年级的,这边是2年级的,这边是3年级的,先给1年级讲课23年级的自己温习做作业,再给2年级的讲课13年级的温习做作业,在前期还能忙过来。但到了1定的时候,学生开始多了,教室坐不下了。业务也多了,我不光教语文、数学,我还要教体育、音乐、美术了,这个时候学校的范围大了。学校的范围大了以后,相干的配套设施就要随着上去。这个时候要有校长、主任、班主任、音乐英语老师…有后勤的,乃至是保洁阿姨,乃至还有食堂了,和大学1样了。

这个例子可以类比我们的架构变化。首先是业务变化,这相当于课程的变化;第2,架构变化,就相当于学校的范围大了以后,相干的配套设施都要跟上;第3个就是人员扩大了,就是我们的开发保护人员多了,这个时候我们不可能还像之前那样,几百号人在那里弄1个工程,你必须要进行分割剥离。

那末我们怎样把它做大?没有别的路,就是拆分扩大,而且扩大不能是简单的横向扩大,不能说来1个业务就简单地按业务来拆。由于可能1个业务量就非常的大,比如说我们的团购体量就非常大,仅仅团购业务的定单量已很大了,自己本身不能再扩了那怎样办?从我的总结来讲就是拆,把大的拆成小的,不断地拆。包括现在提到的微服务,固然现在微服务还没有明确的定义。这和我们的SOA架构是分不开的,只不过是1种情势而已。

现在IT界有很多的概念,就好像敏捷1样,两个星期做1个迭代,之前是1个项目做好几个月。1开始我不太理解甚么是敏捷,有甚么变化呢?我觉得大概就是把大的拆成小的,之前是做两个月的,我们把它分成N个两个星期的,在两个星期的迭代当中,你该做的还是逃不了,你还是要做需求分析,做设计,做开发,做测试,做上线。这个进程没有变,只是说把任务给拆分小了。

在拆的时候,从表现层来看,可以从UI展现和UI逻辑上进行拆分。在逻辑层上,比如说你要提交定单,在提交定单后面的操作包括有定单的服务、接口,这是我们的后端业务逻辑控制层。拆的时候,原来业务逻辑和数据访问都在1层,大家知道,之前在JSP上可以在页面上直接去连数据库进行DB操作。 我们从业务逻辑层进行拆分,拆分成控制层和Service层及数据库操作层。Service层就触及到刚刚讲到的微服务,而Service层也分为复杂的Service和简单的Service。基础Service层相对来讲业务逻辑比较单1,但是又相对照较完全,聚合Service则包括了完全的业务逻辑。

我们的技术团队也是从1个小团队发展到上千人的范围,网站也经历这样1个变革,刚开始的时候就是1个简单的MVC架构,后来这个架构不适应业务的发展和人员范围了。在35百人的时候我们还是那个架构,很多人在保护1个大的工程项目,常常出问题。

而且刚刚开始的时候是没有没有线真个,无线端也是近几年才开始做起来的。

后来要做无线端,怎样办?把PC真个代码包复制1份给无线端用,这个时候问题就不断的来了,由于PC真个逻辑不可能完全符合无线真个要求。

架构演进的准备工作

图片描述

这样我们开始做比较大的架构层面的计划,最大的1个就是业务逻辑层的拆分-SOA服务化,另外一个是DB层的水平拆库。拆分以后,理论上它就具有了无穷的扩大能力,比如说定单库,我可以把它依照1定的维度,去拆成很多的定单库。

拆分和解耦是分不开的,1方面是代码和业务的解耦,另外一方面对人员和工作来讲也是1种解耦。一样还要做1些异步工作,由于之前业务特别重,下单流程非常长,操作步骤非常多,但是很多东西其实不是用户都要马上关注的。比如说下单给用户送积分,这个积分其实不是说下单的时候必须马上就要给到客户的,可以略微延迟几秒乃至是几分钟,它不应当影响下单业务。但是如果由于积分出现问题,致使下单出现问题那就是本末颠倒了。因此我们做了异步,它挂了,我们可以做补偿。

固然有1些是不能做异步的,比如说积分兑换商品的定单,下单时要去扣积分,由于积分就是钱,我们还有礼品卡支付,这个是不能做异步的。我记得之前有过1个例子,好像是1个网站用积分可以充话费,结果话费充成功了,积分没扣,就变成了可以无穷的充。现在是互联网时期,信息散布的很快,听说1两个小时就是几个亿的损失。还有读写分离,读和写是可以完全分开的。为了保证下单的流畅,我们把读和写分开,在不同的库里进行读和写,这样可以很大地减轻下单压力。

核心Service计划

图片描述

这张图是我们核心Service的计划。大家想象1下1个电商网站有哪些基本特点,哪怕你的网站上只有1个页面1个商品,比如说你只卖苹果手机或是小米手机,网站就1个页面显示这个商品,你点商品就能够直接进行购物。首先它要有商品的描写信息,第2是商品的价格,第3是商品的库存,固然库存数字你可以不显示,有就卖,没有就不卖,以上这些是商品基本的信息。

有了商品的信息,如果你想买这个商品,你要先注册用户,注册用户以后要登陆,这是用户信息;然后你就能够下单了,生成1个定单,定单以后是对定单进行相应的物流信息跟踪。同时也能够做线上支付,固然你也能够只做货到付款不做线上支付。

这是1个电商网站最基本的核心要素。1个是产品,第2个是用户&支付,再就是定单。这3大块构成了1个电商网站最核心的3个部份,这就是我们核心Service的架构计划,捉住核心是服务化的重要理念。从Service角度来讲,产品服务、价格服务相对来讲比较简单和单1,对产品的价格来讲用户主要是查;但是对定单来讲,我们把库寄存到定单这个层面来,而不是放到产品上,是由于库存和定单是息息相干的,生成定单的时候要扣库存的,库存不足的话,定单是没法完成的。

刚开始的时候我们没有服务化,定单有两个问题:第1个是写,生成定单。写的业务是很多的,比如说加购物车生成定单,充值是1种业务的定单,电子卡是1种业务的定单,都在写;第2个是读,定单写了以后,用户要来读、后真个客服商家也在读

读不是简单的仅仅读定单表,还有很多其他的关联表。比如说抽奖有抽奖系统有自己的很多表,抽完奖给用户发1个奖品,就生成1个定单,但抽奖系统要知道哪个用户是通过甚么样的方式取得这个定单、定单里有甚么东西,必定要关联查询。所以定单查询是非常复杂的,有没有数的点可以查,而且这个查询1定是有没有数张表可以关联查的,乃至是跨表、跨库的。

那末Service怎样做呢?如果说我把所有的定单相干表都关联起来,都纳入到Service范围的话,基本上可以把70%⑻0%的业务都纳入其中了。由于几近所有的业务都要围绕定单来转,所以Service化1定要有1个边界。边界是甚么?比如说我刚刚说的,你抽奖的信息我关不关心呢?如果说我关心的话,你的抽奖业务就纳入进来了。这就是1个边界,所以我只能只关心我的定单,这就是定单的边界。

图片描述

上图这句话我觉得说的非常好。1个出色的演讲1定要很短,1定也要很长。这对我们来讲是非常成心义的。这1块来说怎样样很短,怎样样又很长?

回到核心Service的规则。既要很短,又要很长,比如说定单的生成,它有很多的业务,要给客户积分,要生成定单表数据,要把抵用券扣掉,还有相干的支付信息,这些业务是不能剥离开来,必须要融会在1起,这当中要包括所有的能想到的业务场景,因此在定单生成业务上,我们要做到足够长,把所有的业务都包括进来。有1些是需要同步的,有1些是需要异步的,但是不管是同步还是异步的,我们都要纳入进来

但对查询来讲,业务是可以分开的,比如商品详情页,可能先是调商品的基本信息Service,然后再去调价格信息Service,然后再调用库存服务Service,生成1个页面需要很多的服务,这些服务可以是各自独立的,所以在查询Service上,我们可以做的很短。价格、库存等都可以做成独立的业务Service单元。

固然独立其实不1定是最简单,它也要有自己完全的业务逻辑。比如库存其实不是简单地看库存表里的数字是大于0还是小于0的问题,比如是说某1个地方销售不销售,或说我们虽然有库存,我们现在是不卖它的,这些都是库存,库存不是1个简单的数字,如果说这个商品暂时不卖,我就显示说无库存,但是我的仓库里是有实物库存的。

我理解所谓的微服务,在底层这1块更多像微服务,微服务是否是拆分的越多越好,也不1定。比如说库存,如果看这个商品有无库存,首先你调1个服务看这个商品是否是在这个区域里卖,再调1个服务看商品是否是上架,再调1个服务看库存是否是大于0,那就太多了。

举个例子,打开1个详情页会调用很多的服务,类目信息、商品信息、价格信息、库存信息、评论等等。这么多服务,怎样保证性能呢,如果拆的非常细的话,仅1个库存服务就能够拆成7、8个子服务,这样的话服务就要调78次,网络交互也是78次,单个Service性能再好又怎样样呢?哪怕你的服务性能到达1毫秒,够快了吧,你调用10次要10毫秒,调用100次要100毫秒,你的性能还是在降落,所以其实不是越微越好,这个长和短的粒度要划分好。记住两个关键词:边界和粒度

定单水平拆库

图片描述

接下来我们谈谈数据库。我们最早用的Oracle,很庞大,支持的量也很大,1般的业务量是没有问题的。但是甚么情况会出问题呢?1个是单点故障,数据库1挂了,全部网站就全挂了,另外不支持水平扩大,包括它的存储、性能、数据量,Oracle再利害,它不可能几百亿、几千亿的数据都放进去。所以我们后来选择了Mysql,对数据库进行了水平拆分,这样的话单点故障率会小1点,这么多的物理数据库,挂1个,其他的还可以运行,不至于影响全局。同时做了水平拆分以后,扩大能力非常强,从理论上来讲可以无穷扩大,由于它不过就是加服务器,你只要加1些硬件就能够了。

那末水平拆分怎样拆?要斟酌哪些因素?

图片描述

比如说定单,你第1要斟酌业务场景,查询定单是哪些用户:其1是前真个用户;其2是后真个用户商家和客服。

第2,它的存储量,定单的数据量是非常大的。但对商品和库存来讲,它是有1定的范围的,不会无穷的大,由于1个网站或1个商店,你卖的SKU数量是有限的。1个大超市多是几万个SKU,1个小门店多是几百个,它不会无穷扩大的。

数据增量也是如此,1个大超市卖的SKU也就是几万个,电商平台多是百万级千万级,但是它也不是无穷增长的,这更多取决于商家的体量,所以它的数据量即便有增长也是非常缓慢的。这和定单不1样,定单是几何式的增长。

再看读和写,定单、库存的读和写频率都很高。但是对商品、价格来说,读肯定是很高的,由于不停地在阅读,但是写是很少的,改价格的机率很低,不停地改商品信息的机率也是很低的。

另外是事务的1致性。对定单和库存1定是要保持1致性,商品信息写的话比较少,不太触及到事务,除非是批量修改,相对来讲事务性1致性略微弱1些。

还有缓存,库存可以有缓存,但是缓存的时间是很短的,库存的缓存时效不多是以天、以小时为级别的,几分钟级别已是不错了。很多时候前端显示还是有库存,后面可能已没有了,所以库存有时效性的要求。但为了减轻数据库压力,在前端展现会有库存的缓存,比如有时候大家会遇到,在阅读的时候发现它是有库存的,但是下单就没有了,那就是由于前端是缓存的,但是下单的是实时的库存,已没有了。但对商品和价格信息来讲,缓存时效就能够长1些,可以通过缓存技术减轻数据库的压力。

热门数据也是1样的。数据库的水平拆分怎样拆,从哪些维度去拆,比如说定单,可以有几个维度,你可以根据定单号去拆,根据产用户、商家去拆。对响应速度来讲,用户要求响应速度是最高的;而对商家来讲,用户下完定单以后,略微延迟1会儿他也能接受。

如果依照用户去拆,热门数据的几率就很低,很难出现1个用户1下子出现几千个几万个定单;但是如果按对商家来拆,有1些大的商家,1个双101可能几个小时就有上千万的单,这个量就非常大。

而对商品信息来讲,如果说你的量没有像天猫、淘宝级别的话,并且主要是靠缓存来读,1般的电商网站,是不需要拆分的。

拆库时怎样做压测

在做定单水平拆库的时候,不可能网站停下来去做这个项目,所以我们说是飞机开的时候换发动机,在汽车跑的时候换轮胎。我们在做数据库拆库的时候要做压测。怎样做压测呢?

Oracle改Mysql的时候,当时我们对性能是没有绝对的信心的,由于Mysql的硬朗性没有Oracle强大,有1次1个badsql直接把我们的1个mysql数据库给弄挂了,对性能要求特别高,但是在业务层,我们很难去摹拟。我们可以在Service或sql上1步1步的分析,1步1步的优化,但是毕竟有很多业务场景是摹拟不出来的。

图片描述

当时我们做了Tcpcopy压测,原理就是把线上要求的包抓下来,放到测试环境中,测试的数据库尽可能保持和线上1致,保持环境1致。压测会动态调剂流量,把原来的流量比如说1小时千万级的提升到亿级的,提升了很多倍,主要是测试看能不能把数据库压垮,会不会出现问题。

固然这个场景也不可能完全覆盖我们的现实利用场景,由于在线上抓包的时候,我们抓了1天,但这1天中数据库的数据是不断变化,不断有insert和update,而线下的测试数据是1个静态的数据,所以还有1些业务场景我们是摹拟不到的。因此摹拟结果和线上还是有1定的差距,但还是给我们吃了1颗很大的定心丸。

SOA中间件

图片描述

我刚刚说了两个,1个是Service化做了技术架构上的拆分,1个是做了数据库的水平拆分。这是刚刚提到的准备工作,Service化和水平拆库的同时,我们的很多中间件技术也发展起来了,由于你的量上来了、架构调剂了,配套设施也要上来,不是说简单的教室1拆分就完了,学校没有保安,要上体育课没有操场是不行的,因此没有相应的中间件没有是不行的。

SOA中间件本身也是1个成心思的发展,包括散布式服务SOA中间件、数据库中间件、缓存平台、消息中间件、任务调度中间件和全局配置中心等。日志和监控系统也非常有必要,这都是系统稳定的基础。

还有实时的分析系统,比如说双101,大家都关注着淘宝的数字,那个数字是怎样出来的,1定是实时出来的,你不能说到了第2天才告知人家前1天晚上1点的时候是甚么样的数据,1定是刚过1点就马上就都出来了。

一样还要做灰度发布,甚么叫高可用,就是不出问题系统1直处于可用状态。但我们还要发布啊,发布的时候怎样办,所以灰度发布的价值就体现出来了,有了它我们的系统就有了100%可用的理论可能。

图片描述

这是我们的1个简单的架构图。提交定单的时候,可以同步也能够异步提交,异步走的是秒杀系统,它不是提交以后马上生成定单,而是要有排队系统进行排队的。我刚刚在前面还说过负载均衡,我们开发了自己的SOA中间件做负载均衡,它有自己的逻辑控制,购物流程到到定单服务是通过SOA中间件做负载均衡和调用的

同时我们还有数据库中间件,我们和数据库的交互怎样办?1个定单查询,如何定位到它所在的数据库。如果是根据用户维度拆库,用户来查询马上可以定位到相应的数据库,但是商家来查询怎样办?他的定单多是覆盖所有的数据库,这个时候需要做1些聚合、排序。这就要通过数据库中间件,它对前端是透明的,它去做1些排序等,利用层只须常规的写自己的SQL就好了。

一样,我们还有消息中间件,比如前面提到的下单后送积分,就能够通过消息异步处理。

图片描述

这是我们的核心交易架构,我们如何让它更完善1些,怎样让它的稳定性更高1些?我们有前台用户,前台用户作为普通消费者去下单、查询,同时也有很多后台的操作。

比如对消费者来讲,下完单后要做支付,固然他可能会定单取消,要把定单变成取消状态;再1个他会修改收货地址,也就是这些简单的几个update操作。而后真个,运营也好,客服也好,对这个定单是有很多的操作的。可能还有审核系统,还有发货、出库等等的系统都要对定单进行操作,因此我们后真个反而是更复杂的。后真个操作必定会影响到数据库,如果不注意也会出现很多的问题,把数据库夯住了,影响了前真个交易。

图片描述

Service层可以不断的拆,但从用户层角度来讲,还是要斟酌前端和后真个拆开。比如代码可之前端1套,后端1套,把它物理隔离开。我们主要目的是保前真个交易,后端系统略微延迟1点没有问题的,但是大家看到,前后端代码物理上虽然隔开了,但是DB还是在1起,后端写的代码把数据库弄挂了,前端还是照样挂,这是1个很大的问题。

多活机房架构

最后说1下多活,多活的架构比较大,可以专门作为1个主题来,我这里只是给大家引伸1下。

刚刚讲到,前端用户、后端用户虽然代码甚么的可以隔开,但是DB这1层还是在1起。因此我们也要想办法把DB分开,但这个时候,两个DB的数据要保持同步,固然我今天说的只是1个思路而不是解决方案。

图片描述

这是我在网上搜来的1张双活的图,想一想双活和多活实际上是1样的。我们可以有不同的机房,也能够在1个机房内部有多个独立的单元,多个机房或单元物理独立。这样的话,1定要有1个统1的数据中心,这两个数据要同步,由于前端用户下完单以后,商家在看定单的时候,不可能要看这边的定单到这个系统,要看那边定单到另外1个系统去看,因此必须要有数据中心。如果说我们有多个机房,多是3个5个,像淘宝的级别就是非常多的机房。我理解它1定要有1个数据中心把数据汇总起来。

固然我这是从利用层来讲,从利用隔离的角度去看的。多活的目的不是简单的隔离,它斟酌的是1旦产生地震、灾害等如何保证不出问题,这个时候数据中心对多活也是必要的。

但数据中心我是否是可以作为后端利用来使用呢?后真个利用走数据中心,由于它对数据的实时性要求相对不是特别高,而前端只保证核心交易业务,后端保证非核心交易业务,这是多活利用架构拆分的思路。

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐