服务端高并发分布式结构演进之路

1. 常见概念

1.1 基本概念

应用(Application)/ 系统(System)

为了完成一整套服务的一个程序或者一组相互配合的程序群

模块(Module)/ 组件(Component)

当应用较为复杂时,为了分离职责,将其中具有清晰职责的,内聚性强的部分,抽象出概念,便于理解。

分布式(Distributed)

系统中的多个模块被部署于不同服务器之上,即可以将该系统称为分布式系统。如Web服务器与数据库分别工作于不同的服务器上,或者多台Web服务器被分别部署在不同的服务器上。

集群(Cluster)

把部署于多台服务器上的,为了实现特定目标 的一个/组特定的组件,整个整体被称为集群。比如多个MySQL工作于不同服务器上,共同提供数据库服务目标,可以称为一组数据库集群。

分布式 vs 集群

通常不用太严格区分两者的细微概念,细究的话,分布式强调的物理形态,即工作在不同服务器上并且通过网络通信配合完成任务;而集群更在意逻辑形态,即是否为了完成特定服务目标。

主(Master)/ 从(Slave)

集群中,通常有一个程序需要承担更多的职责,被称为主;其他承附属职责的被称为从。比如MySQL集群中,只有其中一台服务器上数据库允许进行数据的写入,其他数据库的数据修改全部要从这台数据库同步而来,则把那台数据库称为主库,其他数据库称为从库。

中间件(Middleware)

一类提供不同应用程序用于相互通信的软件,即处于不同技术、工具和数据库之间桥梁。

垂直扩展**(Scale Up)** vs 水平扩展**(Scale Out)**

垂直扩展 :性能提升是**"阶梯式跳跃"** 且边际效应递减的。比如从8核32G升级到16核64G,价格可能翻倍,性能提升80%;但再往上到32核128G,价格可能翻4倍,性能提升可能只有30%。而且顶级硬件的价格极其昂贵(如小型机、大型机)。

水平扩展 :性能提升是**"线性叠加"**的。增加一台普通PC服务器,吞吐量就几乎同比增加一份。用10台廉价PC组成的集群,总性能和性价比通常远高于1台同等级别的高端小型机。

有状态 vs 无状态:

  • 无状态服务(如Web前端、API网关) :做水平扩展非常简单,只需在负载均衡器后加机器即可,这也是互联网架构首选水平扩展的原因。

  • 有状态服务(如数据库、缓存、文件存储)

    • 垂直扩展在这里往往是**"救命稻草"**,因为数据库做水平扩展(分库分表)极其复杂,涉及数据分片、分布式事务和跨节点聚合查询。所以在业务量尚可时,DBA(数据库管理员)宁愿花大价钱买更好的服务器做垂直扩展,也不愿轻易做水平拆分。

    • 当垂直扩展再也撑不住(例如单机写入IOPS(每秒输入输出操作次数)达到物理极限)时,才被迫进行水平扩展(分库分表)

水平扩展时,随之而来的三大经典陷阱(Session共享、分布式日志追踪、配置同步)

1.2 评价标准(Metric)

可用性(Availability)

考察单位时间段内,系统可以正常提供服务的概率/期望。年化系统可用性=系统正常提供服务时长/一年总时长。平常所说4个9,即系统可以提供99.99%的可用性,平常只是用高可用这个非量化目标简要表达系统的追求

响应时长(Response Time RT)

指用户完成输入到四通给出用户反应的时长。通常需要衡量的是最长响应时长。平均响应时长和中位响应时长。这个指标原则上是越小越好,但很多情况下由于实现的限制,需要根据实际情况具体判断

吞吐(Throughput)vs 并发(Concurrent)

吞吐考察单位时间段内,系统可以成功处理的请求的数量。并发指系统统一时刻支持的请求最高量 。实际中,并发量往往无法直接获取没喝多时候都是用极短时间的吞吐量做平替。平时用高并发这个非量化目标简要表达系统的追求

2. 架构演进

2.1 单机架构

单机架构只有一台服务器,这个服务器负责所有的工作

现在计算机硬件发展速度非常快,哪怕只有一台主机,这一台主机的性能也是很高的,可以支持非常高的并发&非常大的数据存储

一台主机的硬件资源是有上限的:

  1. CPU
  2. 内存
  3. 硬盘
  4. 网络
  5. .....

服务器每次收到一个请求,都需要消耗一些资源,如果同一时刻处理的请求多了,此处就可能会导致某个硬件资源不够用

无论哪个方面不够用了,都可能会导致处理请求的时间变长,甚至处理出错

遇到服务器不够用的场景,怎么处理

  1. 开源(简单粗暴,增加更多的硬件资源)

一个主机上面能增加的硬件资源是有限的,取决于主板的扩展能力,如果一台主机扩展到了极限,还是不够,就只能引入多台主机了,引入主机后也需要在软件上做出相应的调整和适配,一旦引入多台主机,系统就可以称为"分布式系统"

  1. 节流 软件上优化

2.2 应用数据分离架构

应用服务器,里面可能会包含很多的业务逻辑,可能会吃CPU和内存

数据库服务器,需要更大的硬盘空间,更快的数据访问速度,可以配置更大硬盘的服务器,甚至可以上SSD硬盘(固态硬盘)

2.3 应用服务器集群架构

单台应用服务器已经无法满足需求了,单机应用服务器首先遇到频颈,有两种解决方案

  1. 垂直扩展 / 纵向扩展

通过购买性能更优,价格更高的应用服务器来应对更多的流量。优势是不需要对系统软件做任何调整,劣势是成本高,硬件性能的提升是有明显上限的

  1. 水平扩展 / 横向扩展

通过调整软件架构,增加应用层硬件,将用户流量分担到不同的应用层服务器上,来提升系统的承载能力。成本低,提升的上限空间很大,劣势是带给系统更多的复杂性

用户的请求先到达负载均衡器 / 网关服务器

Round-Robin轮询算法。即公平地将请求依次分给不同的应用服务器

Weight-Round-Robin轮询算法。为不同的服务器(比如性能不同)赋予不同的权重(weight), 能者多劳。

⼀致哈希散列算法。通过计算用户的特征值(比如IP地址)得到哈希值,根据哈希结果做分发,优 点是确保来自相同用户的请求总是被分给指定的服务器。也就是我们平时遇到的专项客户经理服务。

负载均衡器对于请求的承担能力要远超于应用服务器的

在此架构里,无论扩展多少台服务器,这些请求最终都会从数据库读写数据,到一定程度之后,数据的压力称为系统承载能力的瓶颈。可以向扩展应用服务器那样扩展数据库服务器吗,答案是否定,因为数据库服务由特殊性:如果将数据分散到各台服务器之后,数据的一致性无法得到保证。

2.4 读写分离 / 主从分离架构

采用的解决方法是保留一个主要的数据库作为写入数据库,其他数据库作为从属数据库。从库的的所有数据全部来自主库的数据,进过同步后,从库可以维护与主库一样的数据,然后为了分担数据库的压力,可以将写数据请求全部交给主库处理,读请求分散到各个库中。

当然这个过程不是无代价的,主库到从库的数据同步其 实是由时间成本的,但这个问题我们暂时不做进⼀步探讨

2.5 引入缓存 ---冷热分离架构

随着访问量继续增加,业务中一些数据的读取频率远大于其他数据的读取效率。这部分数据称为热点数据,与之相对应的是冷数据。针对热数据,为了提升读取的响应时间,可以增加本地缓存,并在外部增加分布式缓存

2.6 垂直分库

随着业务的数据量增大,大量的数据存储在同一个库中显得力不从心,按照业务,将数据分别存储。比如针对评论数据,可按照商品ID进行hash,路由到对于的表中存储;针对支付记录,可按照小时创建表,每个小时表继续拆分为小表,使用用户ID或记录编号来路由数据。只要实时操作的表数据量足够小,请求能够足够均匀的分布到多台服务器上的小表,数据库就能通过水平扩展的方式来提高性能。

本来一个数据库服务器上有很多数据库,现在就可以引入多个数据库服务器,每个数据库服务器存储一个或一部分数据库

如果某个表特别大,也可以对表进行拆分

具体分库分表如何实践,要结合实际的业务场景展开

2.7 业务拆分---微服务

随着人员增加,业务发展,将业务分给不同的开发团队去维护,每个团队实现自己的微服务,然后互相之间对数据的直接访问进行隔离,可以利用Gateway、消息总线等技术,实现相互之间的调用关系。甚至可以把一些类似的用户管理。安全管理。数据采集等业务提成公共业务

引入微服务的代价

  1. 系统的性能下降

拆出来更多的服务,多个功能之间要更依赖网络通信,网络通信的速度很可能比硬盘还要慢

要想保证性能不下降太多,只能引入更多的机器,更多的硬件资源,随着硬件技术的发展,网卡现在有万兆网卡,读写速度已经超过硬盘读写,但是成本太高

  1. 系统复杂程度提高,可用性受到影响

服务器多了,出现问题的概率就更大了,需要一系列的手段来保证系统的可用性

微服务的优势

  1. 解决了人员问题

  2. 使用微服务,可以方便与功能的复用

  3. 可以给不同的服务进行不同的部署

3. 分布式系统总结

  1. 单机架构(应用程序+数据库服务器)
  2. 数据库和应用分离
  3. 引入负载均衡 应用服务器 →集群
  4. 引入读写分离,数据库主从架构
  5. 引入缓存,冷热数据分离
  6. 引入分库分表,数据库能够进一步扩展存储空间
  7. 引入微服务,从业务上进一步拆分服务器

所谓分布式系统就是想办法引入更多的硬件资源