关于java:支付宝架构师眼中的高并发架构真是绝了

41次阅读

共计 6609 个字符,预计需要花费 17 分钟才能阅读完成。

起源:blog.thankbabe.com/2016/09/14/high-concurrency-scheme/

什么是对立异样解决

高并发常常会产生在有大沉闷用户量,用户高汇集的业务场景中,如:秒杀流动,定时支付红包等。

为了让业务能够晦涩的运行并且给用户一个好的交互体验,咱们须要依据业务场景预估达到的并发量等因素,来设计适宜本人业务场景的高并发解决计划。

在电商相干产品开发的这些年,我有幸的遇到了并发下的各种坑,这一路摸爬滚打过去有着不少的血泪史,这里进行的总结,作为本人的归档记录,同时分享给大家。

服务器架构

业务从倒退的初期到逐步成熟,服务器架构也是从绝对繁多到集群,再到分布式服务。

一个能够反对高并发的服务少不了好的服务器架构,须要有平衡负载,数据库须要主从集群,nosql 缓存须要主从集群,动态文件须要上传 cdn,这些都是能让业务程序晦涩运行的弱小后盾。

服务器这块多是须要运维人员来配合搭建,具体我就不多说了,点到为止。

大抵须要用到的服务器架构如下:

  • 服务器
    • 平衡负载(如:nginx,阿里云 SLB)
    • 资源监控
    • 分布式
  • 数据库
    • 主从拆散,集群
    • DBA 表优化,索引优化,等
    • 分布式
  • nosql
    • 主从拆散,集群
    • 主从拆散,集群
    • 主从拆散,集群
    • redis
    • mongodb
    • memcache
  • cdn
    • html
    • css
    • js
    • image

并发测试

高并发相干的业务,须要进行并发的测试,通过大量的数据分析评估出整个架构能够撑持的并发量。

测试高并发能够应用第三方服务器或者本人测试服务器,利用测试工具进行并发申请测试,剖析测试数据失去能够撑持并发数量的评估,这个能够作为一个预警参考,俗话说知己自彼百战不殆。

第三方服务:

  • 阿里云性能测试

并发测试工具:

  • Apache JMeter
  • Visual Studio 性能负载测试
  • Microsoft Web Application Stress Tool

实战计划

通用计划

日用户流量大,然而比拟扩散,偶然会有用户高聚的状况;

场景:用户签到,用户核心,用户订单,等

服务器架构图:

阐明:

场景中的这些业务根本是用户进入 APP 后会操作到的,除了流动日(618, 双 11,等),这些业务的用户量都不会高汇集,同时这些业务相干的表都是大数据表,业务多是查问操作,所以咱们须要缩小用户间接命中 DB 的查问;优先查问缓存,如果缓存不存在,再进行 DB 查问,将查问后果缓存起来。

更新用户相干缓存须要分布式存储,比方应用用户 ID 进行 hash 分组,把用户散布到不同的缓存中,这样一个缓存汇合的总量不会很大,不会影响查问效率。

计划如:

  • 用户签到获取积分
    • 计算出用户散布的 key,redis hash 中查找用户今日签到信息
    • 如果查问到签到信息,返回签到信息
    • 如果没有查问到,DB 查问今日是否签到过,如果有签到过,就把签到信息同步 redis 缓存。
    • 如果 DB 中也没有查问到今日的签到记录,就进行签到逻辑,操作 DB 增加今日签到记录,增加签到积分(这整个 DB 操作是一个事务)
    • 缓存签到信息到 redis,返回签到信息
    • 留神这里会有并发状况下的逻辑问题,如:一天签到屡次,发放屡次积分给用户。

  • 用户订单
    • 这里咱们只缓存用户第一页的订单信息,一页 40 条数据,用户个别也只会看第一页的订单数据
    • 用户拜访订单列表,如果是第一页读缓存,如果不是读 DB
    • 计算出用户散布的 key,redis hash 中查找用户订单信息
    • 如果查问到用户订单信息,返回订单信息
    • 如果不存在就进行 DB 查问第一页的订单数据,而后缓存 redis,返回订单信息

  • 用户核心
    • 计算出用户散布的 key,redis hash 中查找用户订单信息
    • 如果查问到用户信息,返回用户信息
    • 如果不存在进行用户 DB 查问,而后缓存 redis,返回用户信息

  • 其余业务
    • 下面例子多是针对用户存储缓存,如果是专用的缓存数据须要留神一些问题,如下
    • 留神专用的缓存数据须要思考并发下的可能会导致大量命中 DB 查问,能够应用治理后盾更新缓存,或者 DB 查问的锁住操作。

以上例子是一个绝对简略的高并发架构,并发量不是很高的状况能够很好的撑持,然而随着业务的壮大,用户并发量减少,咱们的架构也会进行一直的优化和演变,比方对业务进行服务化,每个服务有本人的并发架构,本人的平衡服务器,分布式数据库,nosql 主从集群,如:用户服务、订单服务;

音讯队列

秒杀、秒抢等流动业务,用户在霎时涌入产生高并发申请

场景:定时支付红包,等

服务器架构图:

阐明:

场景中的定时支付是一个高并发的业务,像秒杀流动用户会在到点的工夫涌入,DB 霎时就承受到一记暴击,hold 不住就会宕机,而后影响整个业务;

像这种不是只有查问的操作并且会有高并发的插入或者更新数据的业务,后面提到的通用计划就无奈撑持,并发的时候都是间接命中 DB;

设计这块业务的时候就会应用音讯队列的,能够将参加用户的信息增加到音讯队列中,而后再写个多线程程序去耗费队列,给队列中的用户发放红包;

计划如:

  • 定时支付红包
    • 个别习惯应用 redis 的 list
    • 当用户参加流动,将用户参加信息 push 到队列中
    • 而后写个多线程程序去 pop 数据,进行发放红包的业务
    • 这样能够反对高并发下的用户能够失常的参加流动,并且防止数据库服务器宕机的危险

附加:

通过音讯队列能够做很多的服务。

如:定时短信发送服务,应用 sset(sorted set),发送工夫戳作为排序根据,短信数据队列依据工夫升序,而后写个程序定时循环去读取 sset 队列中的第一条,以后工夫是否超过发送工夫,如果超过就进行短信发送。

一级缓存

高并发申请连贯缓存服务器超出服务器可能接管的申请连贯量,局部用户呈现建设连贯超时无奈读取到数据的问题;

因而须要有个计划当高并发时候时候能够缩小命中缓存服务器;

这时候就呈现了一级缓存的计划,一级缓存就是应用站点服务器缓存去存储数据,留神只存储局部申请量大的数据,并且缓存的数据量要管制,不能过分的应用站点服务器的内存而影响了站点应用程序的失常运行,一级缓存须要设置秒单位的过期工夫,具体工夫依据业务场景设定,目标是当有高并发申请的时候能够让数据的获取命中到一级缓存,而不必连贯缓存 nosql 数据服务器,缩小 nosql 数据服务器的压力

比方 APP 首屏商品数据接口,这些数据是公共的不会针对用户自定义,而且这些数据不会频繁的更新,像这种接口的申请量比拟大就能够退出一级缓存;

服务器架构图:

正当的标准和应用 nosql 缓存数据库,依据业务拆分缓存数据库的集群,这样根本能够很好反对业务,一级缓存毕竟是应用站点服务器缓存所以还是要善用。

动态化数据

高并发申请数据不变动的状况下如果能够不申请本人的服务器获取数据那就能够缩小服务器的资源压力。

对于更新频繁度不高,并且数据容许短时间内的提早,能够通过数据动态化成 JSON,XML,HTML 等数据文件上传 CDN,在拉取数据的时候优先到 CDN 拉取,如果没有获取到数据再从缓存,数据库中获取,当管理人员操作后盾编辑数据再从新生成动态文件上传同步到 CDN,这样在高并发的时候能够使数据的获取命中在 CDN 服务器上。

CDN 节点同步有肯定的提早性,所以找一个靠谱的 CDN 服务器商也很重要

其余计划

  • 对于更新频繁度不高的数据,APP,PC 浏览器,能够缓存数据到本地,而后每次申请接口的时候上传以后缓存数据的版本号,服务端接管到版本号判断版本号与最新数据版本号是否统一,如果不一样就进行最新数据的查问并返回最新数据和最新版本号,如果一样就返回状态码告知数据曾经是最新。缩小服务器压力:资源、带宽等.

分层,宰割,分布式

大型网站要很好撑持高并发,这是须要长期的规划设计

在初期就须要把零碎进行分层,在倒退过程中把外围业务进行拆分成模块单元,依据需要进行分布式部署,能够进行独立团队保护开发。

  • 分层
    • 将零碎在横向维度上切分成几个局部,每个部门负责一部分绝对简略并比拟繁多的职责,而后通过下层对上层的依赖和调度组成一个残缺的零碎
    • 比方把电商零碎分成:应用层,服务层,数据层。(具体分多少个档次依据本人的业务场景)
    • 应用层:网站首页,用户核心,商品核心,购物车,红包业务,活动中心等,负责具体业务和视图展现
    • 服务层:订单服务,用户治理服务,红包服务,商品服务等,为应用层提供服务反对
    • 数据层:关系数据库,nosql 数据库 等,提供数据存储查问服务
    • 分层架构是逻辑上的,在物理部署上能够部署在同一台物理机器上,然而随着网站业务的倒退,必然须要对曾经分层的模块拆散部署,别离部署在不同的服务器上,使网站能够撑持更多用户拜访

  • 宰割
    • 在纵向方面对业务进行切分,将一块绝对简单的业务宰割成不同的模块单元
    • 包装成高内聚低耦合的模块不仅有助于软件的开发保护,也便于不同模块的分布式部署,进步网站的并发解决能力和性能扩大
    • 比方用户核心能够宰割成:账户信息模块,订单模块,充值模块,提现模块,优惠券模块等

  • 分布式
    • 分布式应用和服务, 将分层或者宰割后的业务分布式部署,独立的应用服务器,数据库,缓存服务器
    • 当业务达到肯定用户量的时候,再进行服务器平衡负载,数据库,缓存主从集群
    • 分布式动态资源,比方:动态资源上传 cdn
    • 分布式计算,比方:应用 hadoop 进行大数据的分布式计算
    • 分布式数据和存储, 比方:各散布节点依据哈希算法或其余算法扩散存储数据

网站分层 - 图 1 来自网络

集群

对于用户拜访集中的业务独立部署服务器,应用服务器,数据库,nosql 数据库。外围业务基本上须要搭建集群,即多台服务器部署雷同的利用形成一个集群,通过负载平衡设施独特对外提供服务,服务器集群可能为雷同的服务提供更多的并发反对,因而当有更多的用户拜访时,只须要向集群中退出新的机器即可, 另外能够实现当其中的某台服务器产生故障时,能够通过负载平衡的生效转移机制将申请转移至集群中其余的服务器上,因而能够进步零碎的可用性

  • 应用服务器集群
    • nginx 反向代理
    • slb
    • … …
  • (关系 /nosql)数据库集群
    • 主从拆散,从库集群

通过反向代理平衡负载 - 图 2 来自网络

异步

在高并发业务中如果波及到数据库操作,次要压力都是在数据库服务器下面,尽管应用主从拆散,然而数据库操作都是在主库上操作,单台数据库服务器连接池容许的最大连贯数量是无限的

当连贯数量达到最大值的时候,其余须要连贯数据操作的申请就须要期待有闲暇的连贯,这样高并发的时候很多申请就会呈现 connection time out 的状况

那么像这种高并发业务咱们要如何设计开发计划能够升高数据库服务器的压力呢?

  • 如:
    • 主动弹窗签到,双 11 跨 0 点的时候并发申请签到接口
    • 双 11 抢红包流动
    • 双 11 订单入库

  • 设计思考:
    • 逆向思维,压力在数据库,那业务接口就不进行数据库操作不就没压力了
    • 数据长久化是否容许提早?
    • 如何让业务接口不间接操作 DB,又能够让数据长久化?

  • 方案设计:
    • 像这种波及数据库操作的高并发的业务,就要思考应用异步了
    • 客户端发动接口申请,服务端疾速响应,客户端展现后果给用户,数据库操作通过异步同步
    • 如何实现异步同步?
    • 应用音讯队列,将入库的内容 enqueue 到音讯队列中,业务接口疾速响应给用户后果(能够舒适提醒高峰期提早到账)
    • 而后再写个独立程序从音讯队列 dequeue 数据进去进行入库操作,入库胜利后刷新用户相干缓存,如果入库失败记录日志,不便反馈查问和从新长久化
    • 这样一来数据库操作就只有一个程序 (多线程) 来实现,不会给数据带来压力

  • 补充:
    • 音讯队列除了能够用在高并发业务,其余只有有雷同需要的业务也是能够应用,如:短信发送中间件等
    • 高并发下异步长久化数据可能会影响用户的体验,能够通过可配置的形式,或者自动化监控资源耗费来切换时时或者应用异步,这样在失常流量的状况下能够应用时时操作数据库来进步用户体验
    • 异步同时也能够指编程上的异步函数,异步线程,在有的时候能够应用异步操作,把不须要期待后果的操作放到异步中,而后持续前面的操作,节俭了期待的这部分操作的工夫

缓存

高并发业务接口少数都是进行业务数据的查问,如:商品列表,商品信息,用户信息,红包信息等,这些数据都是不会常常变动,并且长久化在数据库中

高并发的状况下间接连贯从库做查问操作,多台从库服务器也抗不住这么大量的连贯申请数(后面说过,单台数据库服务器容许的最大连贯数量是无限的)

那么咱们在这种高并发的业务接口要如何设计呢?

  • 设计思考:
    • 还是逆向思维,压力在数据库,那么咱们就不进行数据库查问
    • 数据不常常变动,咱们为啥要始终查问 DB?
    • 数据不变动客户端为啥要向服务器申请返回一样的数据?

  • 方案设计:
    • 数据不常常变动,咱们能够把数据进行缓存,缓存的形式有很多种,个别的:应用服务器间接 Cache 内存,支流的:存储在 memcache、redis 内存数据库
    • Cache 是间接存储在应用服务器中,读取速度快,内存数据库服务器容许连接数能够撑持到很大,而且数据存储在内存,读取速度快,再加上主从集群,能够撑持很大的并发查问
    • 依据业务情景,应用配合客户端本地存,如果咱们数据内容不常常变动,为啥要始终申请服务器获取雷同数据,能够通过匹配数据版本号,如果版本号不一样接口从新查问缓存返回数据和版本号,如果一样则不查问数据间接响应
    • 这样不仅能够进步接口响应速度,也能够节约服务器带宽,尽管有些服务器带宽是按流量计费,然而也不是相对有限的,在高并发的时候服务器带宽也可能导致申请响应慢的问题

  • 补充:
    • 缓存同时也指动态资源客户端缓存
    • cdn 缓存,动态资源通过上传 cdn,cdn 节点缓存咱们的动态资源,缩小服务器压力

面向服务

  • SOA 面向服务架构设计
  • 微服务更细粒度服务化,一系列的独立的服务独特组成零碎

应用服务化思维,将外围业务或者通用的业务性能抽离成服务独立部署,对外提供接口的形式提供性能。

最理想化的设计是能够把一个简单的零碎抽离成多个服务,独特组成零碎的业务,长处:松耦合,高可用性,高伸缩性,易保护。

通过面向服务化设计,独立服务器部署,平衡负载,数据库集群,能够让服务撑持更高的并发

  • 服务例子:
    • 用户行为跟踪记录统计

  • 阐明:
    • 通过上报利用模块,操作事件,事件对象,等数据,记录用户的操作行为
    • 比方:记录用户在某个商品模块,点击了某一件商品,或者浏览了某一件商品

  • 背景:
    • 因为服务须要记录用户的各种操作行为,并且能够反复上报,筹备接入服务的业务又是外围业务的用户行为跟踪,所以申请量很大,高峰期会产生大量并发申请。
  • 架构:
    • nodejs WEB 应用服务器平衡负载
    • redis 主从集群
    • mysql 主
    • nodejs+express+ejs+redis+mysql
    • 服务端采纳 nodejs,nodejs 是单过程(PM2 依据 cpu 核数开启多个工作过程),采纳事件驱动机制,适宜 I / O 密集型业务,解决高并发能力强
  • 业务设计:
    • 并发量大,所以不能间接入库,采纳:异步同步数据, 音讯队列
    • 申请接口上报数据,接口将上报数据 push 到 redis 的 list 队列中
    • nodejs 写入库脚本,循环 pop redis list 数据,将数据存储入库,并进行相干统计 Update,无数据时 sleep 几秒
    • 因为数据量会比拟大,上报的数据表按天命名存储
  • 接口:
    • 上报数据接口
    • 统计查问接口

  • 上线跟进:
    • 服务业务根本失常
    • 每天的上报表有上千万的数据

冗余,自动化

当高并发业务所在的服务器呈现宕机的时候,须要有备用服务器进行疾速的代替,在应用服务器压力大的时候能够疾速增加机器到集群中,所以咱们就须要有备用机器能够随时待命。最现实的形式是能够通过自动化监控服务器资源耗费来进行报警,主动切换降级计划,主动的进行服务器替换和增加操作等,通过自动化能够缩小人工的操作的老本,而且能够疾速操作,防止人为操作下面的失误。

  • 冗余
    • 数据库备份
    • 备用服务器
  • 自动化
    • 自动化监控
    • 自动化报警
    • 自动化降级

通过 GitLab 事件,咱们应该反思,做了备份数据并不代表就十拿九稳了,咱们须要保障高可用性,首先备份是否失常进行,备份数据是否可用,须要咱们进行定期的查看,或者自动化监控,还有包含如何防止人为上的操作失误问题。(不过事件中 gitlab 的开放性姿势,踊跃的解决形式还是值得学习的)

总结

高并发架构是一个一直衍变的过程,冰洞三尺非一日之寒,长城筑成非一日之功。打好基础架构不便当前的拓展,这点很重要。

近期热文举荐:

1.1,000+ 道 Java 面试题及答案整顿(2022 最新版)

2. 劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4.Spring Boot 2.6 正式公布,一大波新个性。。

5.《Java 开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞 + 转发哦!

正文完
 0