暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

一年三次大型重构:百万日订单的电商系统是怎么炼成的

勾勾的Java宇宙 2021-01-21
446

勾哥:智慧大佬风采不减当年!

小弟也来学习下,如何一步步将万级订单量的架构重构成能支撑百万日订单的复杂系统架构的

我经历了一个校园电商的互联网创业项目,这个项目在 2015 年的时候快速发展,一年之内进行了三轮融资,融资规模从几十万美元到几千万美元,系统也由一开始的一个较为简单的系统,在一年之内进行了三次架构重构,演化成一个较为复杂、功能较为齐全的系统架构。

一、万级日订单级别架构

这是一个真实的校园互联网电商系统的架构。在早期的时候,每天处理 1W 左右的用户订单,这时候的系统架构如图所示,还是比较简单的。

  • 应用端主要是移动端的应用,通过负载均衡访问 Web 服务器集群,也就是前端集群
  • 前端集群是两台 Nginx 服务器组成的,在 Nginx 再进行一次负载均衡,将用户请求分发到一组应用服务器集群
  • 应用服务器集群按照应用场景分为买家系统、卖家系统、供应链系统以及运营系统四个系统集群,每个系统集群又包含了若干台服务器,所有这些系统都连接到一台 MySQL 服务器上

这样的系统在几千订单的时候运行还算可以,但是在交易比较活跃、并发比较高的时候,系统就会出现各种问题。

在这个阶段,当时的市场总监说”我们的交易越忙,你们的系统越出问题,太邪门了!“

当时我们也没敢说什么,技术部悄悄对系统做了一次改进和重构,主要优化系统架构方面。

二、十万级日订单级别架构

主要优化点:

1. 在前端使用 CDN 服务。
这样用户请求的各种静态资源都通过 CDN 服务返回,而所有的商品图片,再通过一个分布式文件系统进行管理。商品图片的上传和浏览,都由分布式文件系统提供。
2. 在应用服务器集群上又加了一个 Redis 集群。

提升应用系统性能的第一个手段就是使用缓存。Redis 集群的使用,包括前面的 CDN 以及分布式文件系统,极大地缓解了系统在访问高峰期的访问压力。

3. 对 MySQL 数据库还做了一次主从复制的分离,构建了一个一主两从的分布式数据库。

两个从服务器中,一个用来给应用服务器用来做读操作服务,另一个做 SQL 数据分析,有时候也会通过 Sqoop 将数据导出到大数据平台上,做大数据计算。  

4. 搭建大数据平台。

在十万订单的时候,除了系统交易本身的压力比较大,公司对数据的处理的要求也比较高。除了各种各样的统计分析、竞对分析,还有各市场大区的绩效、具体到每个人的绩效都需要进行统计计算,所以专门搭建了一个大数据平台。

在大数据平台上,根据业务数据进行统计分析和运营预测,还根据运营数据进行绩效考核。大数据平台上的数据一部分来自于应用服务器,通过消息队列 Kafka 导入到大数据平台,另一部分数据是来自于 MySQL 从数据库导入到大数据平台。

通过这样一次系统重构,系统可以满足十万级日订单的访问压力。

三、百万级日订单级别架构

随着业务的进一步的发展,系统的订单量还在快速增长,这时候主要的挑战来自于两个方面。

  • 一个方面是,随着订单的增长,业务也变得越来越复杂,开发新的功能变得越来越困难,系统的基本功能维护也越来越困难。
  • 另一个方面是,虽然经过了主从分离以及部署了多种缓存以后,高峰期的数据访问压力也可以承受了,但是数据库的存储空间难以满足要求。

对于一个日订单百万级的系统,年订单量就是数亿,这样大的数据库存储对于 MySQL 而言是难以承受的。  所以我们对系统进行了进一步的重构。这次重构主要是两个方面,如下图。

1. 微服务拆分

做了一个微服务方面的重构拆分,将可复用的一些业务拆分为独立的微服务,进行分布式部署,供应用系统调用,典型的就是用户服务、商品服务、订单服务、红包服务等。

以前红包作为一个功能,在各个应用系统中可能都有涉及,买家需要使用红包,卖家要发放红包,而运营系统也可能发放系统级的红包,而这些红包的功能在各个子系统都存在。

所以对红包功能进行维护修改的时候,可能在很多个系统都要进行相关的代码变更和维护,产品经理需要跟几个系统开发团队进行合作,开发一个功能一不小心就可能会产生 Bug。  重构以后,红包服务作为一个独立的功能,独立部署,其他的所有系统都通过远程调用的方式访问红包服务。

红包的发放使用,以及红包的各种记录都通过红包服务进行管理,其他的应用只需要调用服务接口就可以了。

如果要修改红包服务相关的功能,进行业务变更,那么大多数情况下只需要修改红包服务就可以。这样使业务系统开发变得更加简单,因为红包功能相对比较集中,也更容易实施和落地。

2. 数据库冷热分离

对数据库在原来的主从分离的基础上又做了一次冷热分离。

因为经过主从分离后的数据库,读写访问压力已经可以接受,这时候,主要压力来自于订单的持续不断增长和数据表记录的不断扩展,带来的存储方面的压力。

而订单的一个特点是当订单已经完成,订单状态被关闭以后,订单就是只读的。

这个时候只需要能够对订单提供查询、读服务就可以了,无需为它提供事务性写操作,那么我们就可以从比较宝贵的 MySQL 数据库资源中,把这些已经关闭了的订单分离出来,存储到更容易进行分布式存储的其他的 NoSQL 系统上。  当时我们选择了 MongoDB 作为订单数据的冷存储。

每天夜里运行批处理任务,执行一个冷订单备份的迁移操作,将已经关闭一个月以上的订单数据,从 MySQL 数据库中迁移到了 MongoDB 中。

而订单服务在进行订单操作的时候,所有的写操作依然访问 MySQL 数据库。

对于读操作,如果要是查询一个月以内的订单,也还是访问 MySQL 从数据库,而如果是需要查询一个月以上的订单,那么就访问 MongoDB 数据库就好了。  通过这样一个冷热分离来设计数据库,只存储最近一个月的数据,存储访问的压力、数据存储的压力大大的减轻。

总结

软件架构就是关于整体与部分的关系设计以及关键细节的设计,通过这个电商系统架构,你可以看到整体与部分的关系究竟是如何设计的。



阅读推荐:

对号入座就能搞定架构设计:缓存需要考量啥?

高能的微服务架构设计:流控防控的常见场景与应对措施

下一代微服务架构凭什么要看Service Mesh

高可用必知必会:一次性说透「降级」

Java十年了,转行做视频能挣多少?


加我吧,世界变化快,只有我依然稳定更新


文章转载自勾勾的Java宇宙,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论