您当前的位置:首页 > 电脑百科 > 程序开发 > 架构

高并发架构都要考虑哪些方面?

时间:2022-11-17 11:48:36  来源:  作者:IT架构师联盟

从个人博客开始

相信很多朋友都搭建过个人博客之类的后端系统,这类系统的架构非常简单:

首先购买一台云服务器,并在上面安装 MySQL 数据库,然后部署一个 node.js 之类的 HTTP 服务器监听 80 和 443 端口,在 node.js 中连接数据库并实现业务逻辑。最后购买一个域名并配置 DNS 记录指向我们的服务器 IP 地址,这个网站就算搭建完成了。

随着不断的努力,我们网站的访问量越来越多。某天早晨当你美滋滋打开网站想要看一眼最新评论时,却发现网站打不开了。。。

登录服务器查看日志后发现因为访问人数过多,MySQL 已经无法及时响应所有的查询请求,看来有必要进行一波优化了。

缓存

在博客、新闻、微博、(短)视频、电商等大多数业务场景下读取请求的次数要远远大于写入请求的次数,且读取集中在少数热门数据上而长尾数据很少被访问。在这样的场景中我们可以通过加缓存的方式来提高网站处理读取请求的并发量。

redis 是一种比较常用的缓存系统,它是 Key-Value 结构的内存缓存。Redis 作为独立进程运行并通过 TCP 协议提供服务,这意味着不同服务器上的业务进程(如 node.js) 可以连接到同一个 Redis 实例并共享其中的数据。

由于数据在内存中 Redis 的访问速度要远远大于基于磁盘存储的数据库(单个 Redis 实例可以达到 每秒10万次读写,而 MySQL 只能达到每秒百次写入或千次查询)。但是内存的价格比 SSD 昂贵很多,可用的内存空间非常有限,这要求我们妥善设计缓存方案以及淘汰策略,在缓存命中率和内存消耗之间取得合理的平衡。

使用缓存是一种有效的提高系统吞吐量的方案,但要注意处理缓存一致性、缓存穿透、缓存雪崩等问题。

 

Redis 缓存更新一致性

 

Redis 官方提供了 Redis Cluster 作为集群解决方案,社区中也有 Codis 等优秀的代理式集群解决方案,AWS、阿里云、腾讯云等云服务商都提供了商业化的 Redis 集群。在单机版 Redis 吞吐量不够用时,我们可以方便的迁移到 Redis 集群上。

负载均衡

缓存抗住了大部分的访问请求,随着用户数的增长,现在并发压力主要落在单机的业务服务器上。

一种升级思路是提高单台服务器的配置比如4核8GB内存升级到8核16GB内存,这种思路称为纵向扩容;另一种思路是提高服务器的数量,使用多台服务器同时处理请求,这种思路称为横向扩容。相对于不断增加的访问量,单机性能的提升空间却极其有限,所以在实际工作中更多的采用横向扩容的思路。

我们使用反向代理软件 Nginx 代替业务服务器监听端口,在多台云服务器上部署业务服务器,并将这些业务服务器配置为 Nginx 的后端服务器组。来自用户浏览器的 HTTP 请求首先到达 Nginx, Nginx 根据我们配置的规则将请求转发给负载较低的一台业务服务器,在收到业务服务器响应之后将其返回给用户。

业务服务器的数量可以根据当前的访问量随时增加或减少,在高峰期增加服务器保证质量,低谷期减少服务器节约成本。

我们都知道在电脑 A 上「复制」一个文件是不能在电脑 B 上进行「粘贴」的,同理一个用户的第一次请求被路由到业务服务器 A 第二次请求被路由到业务服务器 B 也会产生类似的问题。抽象一点说,第一次请求改变了业务服务器 A 的状态,而第二次请求的正确响应依赖于业务服务器的状态,在「复制-粘贴」这个例子中「粘贴板」的状态决定了是否能够正确处理「粘贴」请求。

聪明的你可能会说:那么同一个用户的请求始终路由到同一台业务服务器就可以了?我们复习一下上面这句话:「业务服务器的数量可以根据当前的访问量随时增加或减少」,也就是说保存了用户状态的业务服务器可能会被我们回收掉,在高峰期某个用户可能会被分流到新的服务器。

这是一个非常难以解决的问题,所以业界通常的思路是解决问题本身,即:业务服务器无状态化。业务服务器应该像纯函数一样,输出完全由输入决定,自身不存储任何数据,也不维护任何状态。无状态的服务器可以随时启动和停止,服务器的数量也可以随时增加或减少。某台服务器故障后,它未完成的请求也可以转移到其它服务器上重试。当然业务服务器无状态不代表业务逻辑无状态,所有的状态都应存储在数据库

单台 Nginx 的性能虽然很高但仍是有极限的,同样的思路我们可以将负载分布在多台 Nginx 上。linux Virtual Server 是工作在 TCP 层(OSI 四层)的负载均衡器,是业界常用的 Nginx 负载均衡方案。

由于 LVS 是单机版的软件,若 LVS 所在服务器宕机则会导致整个后端系统都无法访问,因此需要有备用节点。可使用 keepalived 软件模拟出虚拟 IP,然后把虚拟 IP 绑定到多台 LVS 服务器上,浏览器访问虚拟 IP 时,会被路由器重定向到真实的 LVS 服务器,当主 LVS 服务器宕机时,keepalived 软件会自动更新路由器中的路由表,把虚拟 IP 重定向到另外一台正常的 LVS 服务器,从而达到 LVS 服务器高可用的效果

如果 LVS 也扛不住了呢?不用着急,在 DNS 服务器中可配置一个域名对应多个 IP 地址。DNS 服务器可以按照负载均衡策略将域名解析到其中一台 LVS 的 ip 地址,从此系统可自由的进行横向扩容:

在上面这张架构图中除了数据库外的组件都不是单机运行的,单台机器故障不会导致整个系统宕机,任何一个组件容量不足时都可以通过加机器迅速扩容。这是分布式系统中另一个重要的原则:消除服务器内单点。

数据库篇

经过缓存和横向扩容,我们的网站已经可以应对高并发的读请求以及业务逻辑计算的开销。但是我们写入的吞吐量仍然受限于单机数据库,那么有没有办法解决数据库的单点问题呢?

读写分离

包括 MySQL 在内的绝大多数主流数据库均支持主从复制,从库会监听主库的更新并将更新同步到本地,从而始终保持与主库的数据集一致。

从库除了作为备份之外也可以像缓存一样分担主库的读取压力,即数据更新写入主库而查询操作则在从库上进行,我们将这种技术称为读写分离。

一些复杂的查询会消耗数据库大量的 IO 和 CPU 资源,举例来说:我们将关注关系存储在 MySQL 中,而计算用户粉丝数的 select count 查询非常耗时,我们可以将这样的查询移到从库上进行,主库的资源则可以用来处理更多写请求。

分库分表

在读写分离一节中我们配置了多个用于处理读取请求的从库,但是处理写入请求的主库始终只有一个,主库仍然是制约整个网站的吞吐量的瓶颈。那我们能否像读库一样配置多个主库,以此来提升网站写入的吞吐量呢?

答案是肯定的,使用多个主库的核心问题在于如何决定某一条数据应该写入哪一个节点中。比如用户 A 发表了一篇文章我们将它存入了数据库 1,后续查询时我们却到数据库 2 中进行搜索,自然一无所获;又或者用户 A 的第一篇文章存入了数据库 1,第二篇文章却存入了数据库 2,在我们按时间查询用户 A 的文章时就不得不搜索每一个数据库然后费时费力的将结果重新排序。

决定数据写入哪个节点的策略我们通常称为分表的路由策略,选择路由策略的原则是尽可能的将需要一起使用的数据放到同一个数据库中,避免跨库带来的额外复杂度。比如在博客系统的场景中,我们通常会将同一个用户的文章放入同一个数据库。

接下来的事情就是如何将用户 ID 映射到某个表上了。最简单的方法是 hash(user_id) % db_num, 但实际场景中节点的数量会发生变化(即扩缩容),此时几乎所有数据的 db_id 都会发生改变,在扩缩容过程中需要迁移大量的数据。因此,在实际使用更多的是一致性哈希算法,它的目标是在数据库节点数量变化时尽可能的减少需要迁移的数据量。

无论如何选择分表路由策略我们都无法完全避免进行跨表读写,这时有一些额外的工作需要处理,比如将多个数据库返回的结果重新进行排序和分页,或者需要保证跨库写入的 ACID (事务)性。此时就要使用诸如 MyCat 这样的数据库中间件来帮我们处理这些麻烦事了。

和单机数据库一样,分库分表架构下同样可以为数据库节点配置从库,一是可以用作备份,二是用来实现读写分离。

NewSQL

MySQL 以数据页为单位进行存储,每个数据页内按主键顺序存储着多行数据。在写入新数据时首先需要读取主键索引找到对应的数据页,然后将新的数据行插入进去。必要时还需要要将原来一页中的数据转移到其它数据页上才能满足页内按主键顺序排列的要求。这种由于一次数据库写入请求导致的多次磁盘写的现象被称为写放大,随机读写和写放大是制约 MySQL 写入性能的主要瓶颈。

 

本文描述基于 MySQL 默认的 InnoDB 存储引擎, InnoDB 同时也是 MySQL 中应用最广的存储引擎。本文不强调 MySQL 和 InnoDB 的区分。

 

LSM-Tree 是一种日志式的存储结构,对数据的增删改都是通过在日志尾部追加一条新记录实现的。由于不需要寻找数据页和维护页结构只需要进行顺序写,日志式存储结构的写入性能大大优于 MySQL 这类面向页的存储结构。

LSM-Tree 结构数据库的经典代表是 RocksDB 和 LevelDB, 很多新一代的数据库(NewSQL)的底层均使用 RocksDB 或 LevelDB 作为存储引擎。比如大名鼎鼎的 TiDB 便是以 RocksDB 作为存储引擎,在其上通过 Multi-Raft 协议构造高一致性、高可用、支持快速扩缩容的分布式数据系统。

 

图片源自 tidb 官网:https://docs.pingcap.com/zh/tidb/dev/tidb-storage

 

直接使用 TiDB 之类的分布式数据库可能是比自行分库分表更简单高效的方案。除了 TiDB 外还有各类 NewSQL 活跃在业界解决着传统关系型数据库难以解决的问题,比如用于进行复杂统计查询的 Hive、用于进行模糊搜索的 ElasticSearch、用于存储和分析海量日志的 ClickHouse 等时序数据库、用于计算共同好友等场景的 Dgraph 等图数据库…… 这些新型数据必将极大的提高开发效率和系统性能。

消息队列

消息队列在应对高并发上也是一种非常有用的技术,这里消息队列有两种用途:第一是用作限流,用户请求先进入消息队列排队,然后慢慢送到业务服务器进行处理,起到削峰填谷的作用,可以用来应对秒杀等瞬间峰值的场景;第二是异步处理任务,比如订单创建成功后立即返回,通知发货等逻辑通过消息队列进行异步处理,从而减少请求处理时间。

总结

应对高并发

我们从最简单的单服务器+单数据库架构开始,通过缓存和读写分离技术提高读取吞吐量,通过横向扩容提高业务服务器容量,通过使用分库分表技术提高数据库写入能力。最后兼具高性能、高一致性的新一代的分布式数据库系统 ———— TiDB。

缓存、横向扩容、通过 MQ 异步执行是在业务开发中最常用、成本最低的提高吞吐量的方案。新一代的分布式数据库系统替我们解决了传统关系型数据库单点运行、吞吐量有限、难以横向扩容、应用场景局限等问题,各大厂商正在越来越多的将 NewSQL 应用于生产环境中, 学习使用新一代数据库技术必将极大的提高开发效率和系统性能。

走向分布式系统

在本文中我们应对吞吐量不足的核心思路是将单机系统改造为分布式系统,很多同学一提到分布式系统便想到 CAP 理论、Paxos 算法、Hadoop 等吓人的名词,然后就没有然后了。

在本文中我们提到了两种分布式系统,第一种是在「负载均衡」一节中提到的无状态分布式系统,这类系统结构比较简单通常由负载均衡+业务服务器组成,由于无状态的特性可以随意扩缩容。第二种便是比较复杂的有状态分布式系统,具体的讲就是各种分布式数据库(包括内存数据库),幸运的是厂商准备好了开箱即用的方案,倒也不必为此花费过多心力。

本文中提到的「分库分表 + 主从复制」是大多数分布式数据库的基本思想,分布式数据库面临的主要难点是系统内的拓扑是动态变化的:现在数据库中有几个主节点在正常工作?这些主节点的地址是什么?那些节点发生了主从切换?分布式数据库需要让系统内所有节点对系统的拓扑结构的认知始终保持一致,否则便会出现应该写入节点 A 实际上写入了节点 B 这样的错误情况。



Tags:架构   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
李根 丰色 发自 凹非寺 量子位 | 公众号 QbitAI “Can Machines Think?”这是阿兰·图灵在1950年论文《计算机器和智能》中的经典提问,围绕着图灵的目标,软件和硬件开启...【详细内容】
2023-01-03  Tags: 架构  点击:(8)  评论:(0)  加入收藏
官方网站 www.itilzj.com 文档资料: wenku.itilzj.com单聊在众多的软件中,聊天功能是不可或缺的一个功能模块,或是用户和用户,或是用户和客服,都需要一个能够即时沟通的功能。那...【详细内容】
2023-01-03  Tags: 架构  点击:(0)  评论:(0)  加入收藏
不久前,腾讯QQ项目组发布预告,宣布采用全新架构的QQ for Linux新版本即将开启公测。现在,QQ for Linux 3.0正式版已经上架QQ官网,Linux用户可以直接下载进行尝试。据悉,此次的QQ...【详细内容】
2022-12-28  Tags: 架构  点击:(25)  评论:(0)  加入收藏
分享七牛云CEO「许式伟」对于这个话题的思考。 你好,我是许式伟。从今天起,我想和你一起来聊聊架构的话题。开始之前,我先来和你简单介绍下我自己。我是2000年开始工作的,曾经做...【详细内容】
2022-12-19  Tags: 架构  点击:(8)  评论:(0)  加入收藏
软件体系架构基于一组适用于各种软件系统的基本原则,有经验的架构师知道这些原则,并且能够在软件产品的正确位置实现特定的原则。下面我们快速浏览一下架构师日常遵循的基本原...【详细内容】
2022-12-13  Tags: 架构  点击:(0)  评论:(0)  加入收藏
企业越来越需要升级其应用程序和方法,以便为数百万人提供数字体验。一种这样的方法是无服务器。技术主管现在正在重新考虑他们的战略,以响应提高敏捷性和降低总运营开销和成...【详细内容】
2022-12-09  Tags: 架构  点击:(19)  评论:(0)  加入收藏
背景单体应用在向微服务化架构演进时,需要考虑如何解决服务认证授权的问题。如果处理不好,会引发架构的混乱,带来安全、性能、难以维护的问题。 以最典型的包含WEB页面的具备登...【详细内容】
2022-12-03  Tags: 架构  点击:(22)  评论:(0)  加入收藏
为什么要做个性化推荐回顾弹幕工程建设的发展历程,大致可以分几个阶段:1. 基础能力:在高并发、热点场景下,保证弹幕服务的稳定和高可用2. 负向治理:以管控为目标,通过删除、自检、...【详细内容】
2022-11-26  Tags: 架构  点击:(20)  评论:(0)  加入收藏
整理 | 苏宓出品 | CSDN(ID:CSDNnews)历经 26 天,马斯克终于停手了。11 月 22 日,据外媒 The Verge 报道,在 Twitter 的全体员工会议上,马斯克表示,Twitter 已经完成了裁员,并开启新...【详细内容】
2022-11-22  Tags: 架构  点击:(43)  评论:(0)  加入收藏
作者 | 褚杏娟近日,GitHub 前 CTO Jason Warner 在推特上表示,“我确信过去十年中,最大的架构错误之一就是全面使用微服务。”从单体应用到微服务的规划顺序,Warner 的建议是:单...【详细内容】
2022-11-18  Tags: 架构  点击:(50)  评论:(0)  加入收藏
▌简易百科推荐
李根 丰色 发自 凹非寺 量子位 | 公众号 QbitAI “Can Machines Think?”这是阿兰·图灵在1950年论文《计算机器和智能》中的经典提问,围绕着图灵的目标,软件和硬件开启...【详细内容】
2023-01-03  量子位     Tags:架构   点击:(8)  评论:(0)  加入收藏
官方网站 www.itilzj.com 文档资料: wenku.itilzj.com单聊在众多的软件中,聊天功能是不可或缺的一个功能模块,或是用户和用户,或是用户和客服,都需要一个能够即时沟通的功能。那...【详细内容】
2023-01-03  IT架构师联盟     Tags:架构   点击:(0)  评论:(0)  加入收藏
SpringBoot检验注解@Null 限制只能为null@NotNull 限制必须不为null@NotEmpty 只作用于字符串类型,字符串不为空,并且长度不为0@NotBlank 只作用于字符串类型,字符串不为空,并且...【详细内容】
2022-12-29  九天银河聊编程  今日头条  Tags:SpringBoot   点击:(8)  评论:(0)  加入收藏
官方网站 www.itilzj.com 文档资料: wenku.itilzj.comES 的集群模式和 kafka 很像,kafka 又和 redis 的集群模式很像。总之就是相互借鉴!不管你用没用过 ES,今天我们一起聊聊它...【详细内容】
2022-12-26   IT架构师联盟     Tags:Elasticsearch   点击:(0)  评论:(0)  加入收藏
背景部门中维护了一个老系统,功能都耦合在一个单体应用中(300+接口),表也放在同一个库中(200+表),导致系统存在很多风险和缺陷。经常出现问题:如数据库的单点、性能问题,应用的扩...【详细内容】
2022-12-17  闪念基因  今日头条  Tags:微服务   点击:(8)  评论:(0)  加入收藏
软件体系架构基于一组适用于各种软件系统的基本原则,有经验的架构师知道这些原则,并且能够在软件产品的正确位置实现特定的原则。下面我们快速浏览一下架构师日常遵循的基本原...【详细内容】
2022-12-13   IT架构师联盟     Tags:架构   点击:(0)  评论:(0)  加入收藏
这是个很尴尬的话题,为什么这么说呢?当我们在讨论卷和造轮子两个事情的时候,SpringBoot 的开发人员也正在做着同样的事情...回顾之前在 微服务-分布式链路 这篇文章中我介绍了...【详细内容】
2022-12-10  小小怪下士的架构攻略  今日头条  Tags:SpringBoot   点击:(45)  评论:(0)  加入收藏
背景单体应用在向微服务化架构演进时,需要考虑如何解决服务认证授权的问题。如果处理不好,会引发架构的混乱,带来安全、性能、难以维护的问题。 以最典型的包含WEB页面的具备登...【详细内容】
2022-12-03  儒雅程序员阿鑫  今日头条  Tags:微服务   点击:(22)  评论:(0)  加入收藏
作者 | 潘娟伴随着互联网应用场景逐渐深入到生活的各个角落,为了确保前端用户的使用体验,对互联网产品的后端架构性能提出了更高的需求。如今,开发以及运维人员正在将工作重心...【详细内容】
2022-12-02   InfoQ     Tags:Kubernetes   点击:(25)  评论:(0)  加入收藏
Kubernetes Prometheus简介在k8s平台上部署Prometheus监控有几种方式 老老实实写yaml部署脚本,这种方式部署太麻烦,细节太多,不建议 使用开源项目prometheus-operator部署 使...【详细内容】
2022-12-01  HemLeen哈哈  今日头条  Tags:K8S   点击:(39)  评论:(0)  加入收藏
站内最新
站内热门
站内头条