写点什么

秒杀系统的架构解决之道

  • 2017-04-17
  • 本文字数:4221 字

    阅读完需:约 14 分钟

本文将会从三个方面来分别探讨如何设计应用架构以更好的支持“秒杀”类需求,包括秒杀带来的问题和挑战、产品架构解决之道、流量控制解决方案。

秒杀场景下带来的海量用户所造成的流量突增对系统冲击力可想而知,瞬时流量之高一方面造成的读写冲突,数据库锁会非常严重,另一方面应用服务器能否撑住也是一个问题。同时由于秒杀业务一般是各种活动带来,需要快速上下线,这在开发上也会提出更高的标准,快速支持需求而不出错。从系统上讲我们要做到高可用和高并发;从开发效率上我们要做到敏捷开发以支持产品快速迭代。接下来让我们从产品架构和流量控制这两个方面来讨论并解决这个问题。如果把解决秒杀问题看成一种武林秘籍,则产品架构是内功,流量控制是招法,上乘内力搭配制胜招法则无往而不利。

内功:产品架构解决之道

向一站式架构说"NO"

上图是一个典型的一站式架构,未经过良好的设计的系统随着时间的推移逐渐会转换成上图这样,一方面是产品业务的压力,另一方面也是先天的设计不足。一站式架构存在很多问题。

首先就是不易扩展,难以维护。随着业务的发展,对系统进行扩容难以避免,而一站式架构的可扩展性却令人堪忧,对其扩容则相当于对系统中的所有功能进行扩容,从代码确认到测试再到环境都是一项艰巨的任务。一站式架构中的扩容往往建立在“既然什么都没改,则运行应该正常”的假设之上,而扩容迁移中的各种 BUG 则隐藏在这种假设之中。系统所需的各种权限也随着规模而不断增多,连接的各种组件也越来越多,由此带来的维护性问题也会持续加重。

其次是代码难以理解,开发质量得不到保证。随着系统规模的扩大,即便是最初经过良好设计的代码,经过人员迭代,需求压力,也难免会逐渐走向混乱。渐渐的,各种跨层调用,不合适的封装,有副作用的函数等都会出现在代码中,这些设计侵入到代码中的每个角落,每个人都能见,而每个人都会选择性忽略,因为错综复杂的调用难以调整,也很难找到人员来进行整体测试。而这些都是 BUG 产生的温床。

最后在一站式架构下项目的可靠性是无法得到保证的,由于业务调整而修改一处逻辑,往往会影响到代码中很多功能的逻辑,而这些额外受到影响的功能则通常不会得到测试,只是在假定这些都是正常的,而这种假定也通常正确,直接潜在的问题爆发。该出错的总会出错,墨菲定律往往这时候是最有效的。

综上可以看出一站式架构设计与敏捷开发格格不入,持续开发,持续集成,持续部署也就只能变成空谈了。

微服务架构

上图是优化后的微服务架构,将整个系统拆分成订单、推送、折扣、产品、个人信息等各个微服务,每个服务都有自己的数据库和缓存等,并且不会互相交叉。各服务之间使用消息队列、RPC 调用等传输数据。目前大部分系统设计可能处于一站式架构和微服务架构之间,即上层应用可能已经服务化,但是数据库层面还是使用同一个库。但个人以为系统应该朝完全微服务化努力,隔离数据库层面的共用,以获得更高的系统可靠性。

微服务架构下的系统更加容易进行扩展,可以只针对需要扩容的系统来进行扩容,例如订单量增大,可以只扩容订单服务,而对于其他服务例如个人信息、折扣中心等都都不进行调整,这样一方面减少了系统扩容而对整体稳定性带来的变化,即只需测试新环境中的订单服务即可,随着微服务拆分的越细,这种优势也就越大。

在这种微服务架构下,开发人员可以更加集中精力,将重点放到少量的代码和明确的业务上,这样能够产出更加优雅的代码和良好的设计,在代码优化调整中,也不会由于到处调用而畏手畏脚。每个微服务可以安排 2-3 人的小组专门维护,这样也会减少一个微服务内部的沟通成本,而进一步提高生产力。每个微服务小组可以独立工作,无需过多协调即可实践新功能或想法。

随着技术的不断发展,项目所用的技术架构总会过时,在系统技术革新上,对于传统的一站式架构,甚至是之前提到的服务化架构在应用新技术上都会遇到不小的困难,牵一发动全身,技术改革往往除了推倒重来而没有其他办法。对于微服务架构,由于系统的完全拆分,公共组件依赖只剩下异步的消息队列,在新技术应用这方面则有了天然优势。微服务基于组件开发设计,提供了在开发过程中技术选型的最大灵活性,甚至是编程语言的变化都可以进行尝试。

最后要提到的,就是系统稳定性和可用性方面的考虑。在业务需求的持续推动下,持续部署不可避免,在线系统随时都需要进行上线。随着业务的增长、系统的复杂,系统部署时造成问题的潜在可能性会大大提高。而微服务在这方面极大的提高了系统的可靠性。由于微服务的划分,故障天然被隔离,某个服务的故障,不会造成系统的整体瘫痪。而发布的时间由于只需要发布更新相关的服务而大大缩短,这也提高了整体系统的稳定性。当面临问题需要回滚时,也只需要回滚更新相关服务即可,而这在一站式架构中将会是一个灾难。

良好的架构可以更好的支持快速迭代。高内聚的设计将开发人员精力集中到相对集中的领域以设计更优雅的代码实现。随着技术的演进,项目架构也可以跟着一起迭代升级。也可以更好的支持持续集成、持续部署。总之,微服务可以渗透到开发中的每个领域为业务迭代提供更好的支持。微服务这方面建议可以参考 Spring Cloud 和 Docker。

招法:流量控制解决方案

内功的修炼固然重要,不过并非一朝一夕可成,是需要长期的努力和不断的沉淀。在武学中固然有高神内力,同时也存在一些致胜招法,一旦练成即可功力猛进,下来就让我们看一下支持秒杀业务中的一些致胜招法:流量控制解决方案。

流量控制解决总览

如上图所示,在项目的整个架构中,流量要做到逐层减少。在每层中都可以使用一些方法来减少流量。

前端流量控制

前端流量控制,页面可以设计为动静分离,将尽可能多的数据使用 CDN 进行缓存,以减少到自己服务器上的流量。同时可以加入验证问题,拉长用户下单时间并防止刷单。对较核心逻辑担心用户破译验证方式,可以再增加服务器端的用户 ID 访问限制,例如同一用户 5s 内只能触发 1 次相关操作等。

反向代理流量控制

反向代理(Nginx)流量控制,很多页面或者接口响应数据都可以进行静态化处理,应用侧(Tomcat)可以定时生成这些资源,发到内容分发服务上,内容分发服务可以将这些静态化资源分发到所有的反向代理上。这些数据可以根据需要按照一定时间间隔进行更新。同时,也可以利用 Nginx 中的缓存配置功能,对热点接口进行缓存。

借助 Nginx 中 Nginx-lua 插件的功能,一些简单逻辑在 Nginx 中直接实现会比较容易,使用恰当,能够大幅减少到应用服务器的请求。例如倒计时,取系统当前时间等逻辑就非常适合在 Nginx 中使用 Lua 实现。对于存在缓存中的商品数量等信息也可由 Nginx 直接访问缓存返回,而不将请求再转发给应用服务器。

访问数据分析流量控制

在秒杀中,令人头疼的问题不只是正常流量突增。由于秒杀活动一般都带有优惠性质,恶意访问也会增多,对于恶意请求在 Nginx 层也可以做很多工作,进行一次拦截。Nginx 配置中有限制用户访问频率的配置可以根据需要进行配置。同时,也可以使用 nginx-lua 完成一些简单的封禁逻辑,例如调用接口可以封掉指定 IP 或者 UA 的访问请求。之后利用日志分析程序,对访问日志进行分析,将需要封掉的 IP 或者 UA 等信息调用 Nginx 上提供的接口进行封杀。

应用服务器流量控制

经过之前的处理,能够到达应用服务器的流量已经少了很多。对于秒杀活动这类的需求,可以准备专门的活动服务器,专门处理相关逻辑。可以使用不同域名进行分流,或者按照一定 URL 规则在反向代理服务器上进行分流。同时,对于到数据库进行操作的请求可以使用阻塞队减少到数据库的访问以减少行锁等。对于明显超出处理范围的请求可以直接返回秒杀已经结束。例如商品总量 300,剩余量 100,每台应用服务器上待处理的值超过总量的值则可以直接返回秒杀结束。剩余量可以存入缓存服务中,剩余量可以不那么精确,确保缓存中的剩余量 >= 实际剩余量即可。超出剩余量的请求也可以直接返回秒杀结束。

缓存存储多点部署以提高系统的整体可用性,避免缓存问题导致系统出错的情况。Redis 会是一个目前比较好的选择,主从自动切换等功能可以更好的增强系统整体可用性。对于使用单点 Memcached 等系统,建议可以配置 Keepalived,使得发生机器故障时,IP 可以自动转移到另外一台健康 Memcached 服务器上,虽然数据不可恢复,但是缓存组件依然可用。宕机的组件对系统造成的影响往往是不可预料的,尤其是在未良好设计的系统中,整体架构中应任一组件完全宕机的可能性。

对于秒杀活动需求,可能是一系列的活动,相关逻辑可以判断是否可以做到一个专门活动库中,并进行读写分离设计。有条件的情况下,数据库中间件会完成其中一部分工作。在没有相关条件的时候,即使没有数据库中间件,相关逻辑也可以直接在代码中实现。

对于数据库行锁问题,如有需要可以进一步优化,例如上图,将行锁问题通过拆分具体商品,增加分配 ID 标志,去掉行锁。这个变动的缺点是可能对现有业务逻辑影响较大。不过优点也很明显,在数据库层面消除了行锁。

流量控制总结

一图胜千言,以上讨论的流量控制总结方案可以总结到一张图上:

总结

结合微服务架构,我们最终的架构图可以是这样的:

以上供大家参考。

技术选型简介

平台应用构建技术选型如下,供大家参考:

  • 反向代理层 Nginx 推荐使用阿里开源的 Tengine,Tengine 中增强了 Nginx 中的很多功能并简化了配置。
  • 在虚拟化方面,可以按照物理机 -> 虚拟机 ->Docker 三层架构来实现虚拟化,在物理机上按照应用实例、缓存实例、消息队列实例等建立虚拟机,再分别在虚拟机上启动不同实例的 Docker。
  • 在应用构建方面,推荐使用 Spring Cloud 解决方案(由于历史原因,目前还保留部分 Dubbo 接口)。
  • 消息队列选型目前比较广泛,这里推荐一下阿里开源的 RocketMQ,目前已经捐赠给 Apache。我们内部也针对 RocketMQ 开发了一套易用 client,当然也在开源计划之中,相信不久就会和大家见面。目前我们系统每分钟接口请求量高峰在几十万左右,系统整体支撑再多的访问量相信也没有问题,各层、各服务根据需要都可以进行横向扩容以支撑更高的访问量。

参考资料

2017-04-17 17:018278

评论

发布
暂无评论
发现更多内容

lrc下载安装 图像处理软件Lightroom Classic 2023 mac中文激活版

mac

图像处理软件 苹果mac Windows软件 lrc2023 Lightroom Classic

Footprint Analytics 为 Layer2 公链提供数据支持,助力新兴项目发展

Footprint Analytics

区块链 公链 layer2

不知道该选公有云还是私有云?这些客户请选私有云

青椒云云电脑

桌面云 云桌面

Vue 和 React 前端框架的比较

高端章鱼哥

Vue React

腾讯云 CODING 入选“数智影响力”数字化转型创新典型案例

CODING DevOps

议题征集|Flink Forward Asia 2023 正式启动

Apache Flink

flink

软件测试/测试开发丨使用ChatGPT自动进行需求分析

测试人

人工智能 程序员 软件测试 需求分析 ChatGPT

高校云桌面的“正确打开方式”是什么?

青椒云云电脑

云桌面 云桌面方案

从构建者到设计者的低代码之路

树上有只程序猿

软件开发 低代码

Footprint Analytics 团队参与 Token 2049,为多场活动以及演讲提供数据支持

Footprint Analytics

区块链 公链

基于Vue3前后端分离的低代码开发框架

互联网工科生

Vue 软件开发 低代码 JNPF

Footprint Analytics 为 ABGA Web3 Gaming Summit 提供支持,助力 Web3 游戏行业发展

Footprint Analytics

英特尔产品组合针对多规模AI模型性价比优势明显

E科讯

对齐管理后台中账户体系的四种方法

FN0

单点登录 账户体系

云桌面怎么选,好产品的标准是什么

青椒云云电脑

桌面云 云桌面

Ask Milvus Anything!聊聊被社区反复@的那些事儿 Ⅰ

Zilliz

非结构化数据 Milvus 向量数据库 deepdive

9月24日,线下见个面?

MatrixOrigin

数据库 分布式 MatrixOrigin MatrixOne

什么是网络营销?做网络营销怎么用代理IP?

巨量HTTP

IP

多场景PAI-Diffusion中文模型家族大升级,12个模型、2个工具全部开源

阿里云大数据AI技术

人工智能 阿里云

企业高管IT战略指南——为何要落地平台工程

York

容器 DevOps 云原生 敏捷 平台工程

大模型的东风中,看雄安的数字飞翔

脑极体

数字化

为什么越来越多的学校使用云桌面?

青椒云云电脑

桌面云 云桌面

INFINI Easysearch 与兆芯完成产品兼容互认证

极限实验室

easysearch 兆芯 国产适配

一文读懂私有云、公有云和本地化部署

青椒云云电脑

公有云 私有云

用AI提高代码质量,同事对我的代码赞不绝口~

SoFlu软件机器人

产教融合 | 力软联合重庆科技学院开展低代码应用开发培训

力软低代码开发平台

代码混淆和加固,保障应用程序的安全性

雪奈椰子

在对接自有账户体系时,FinClip 是怎么做的?

Onegun

用户 账户管理 账户体系

百度智能云千帆社区上线有礼,助力开发者开启大模型之路!

科技热闻

HiAI Foundation助力端侧音视频AI能力,高性能低功耗释放云侧成本

HarmonyOS SDK

huawei HarmonyOS

秒杀系统的架构解决之道_语言 & 开发_胡因可_InfoQ精选文章