【分布式架构设计理论1】架构设计的演进过程
文章目录
- 一. 分布式架构要解决的问题
- 二. 架构设计的演进过程
- 1. 应用与数据一体
- 2. 应用与数据分离
- 3. 添加缓存:突破数据库(IO)瓶颈
- 4. 服务器集群处理并发
- 5. 数据库读写分离:释放读性能
- 5.1. 问题分析
- 5.2. 解决方案:读写分离
- 6. 反向代理和 CDN
- 6.1. 反向代理的作用
- 6.2. CDN进一步加快静态资源的访问
- 7. 分布式数据库与分表分库
- 7.1. 分库分表
- 7.2. 数据库中间件
- 8. 业务拆分:引入服务通讯与协调
- 9. 分布式与微服务
一. 分布式架构要解决的问题
- 为了应对请求的高并发和业务的复杂性,需要对应用服务进行合理拆分,将其从原来的大而集中变成小而分散;
- 要想让这些分散的服务共同完成计算任务,就需要解决它们之间的通信与协同问题;
- 和服务一样,负责存储的数据库也会有分散的情况,因此需要考虑分散存储;
- 所有的服务、数据库都需要硬件资源作为支撑,所以需要对资源的管理和调度;
- 软件系统上线以后,还需要对关键指标进行监控。
二. 架构设计的演进过程
本章主要讨论:架构设计经历了哪些阶段,以及每个阶段分别解决了哪些问题,又引出了哪些新问题。
1. 应用与数据一体
应用与数据库都部署到一台机器上,比如网页浏览、OA 等,访问人数有限,单台服务器就能轻松应付,利用 LAMP(Linux、Apache、MySQL、PHP)技术就可以迅速搞定。
2. 应用与数据分离
随着业务的发展,用户数量和请求数量逐渐上升,服务器的性能便出现了问题。
- 应用服务器由于需要处理大量的业务请求,因此对 CPU 和内存有一定要求;
- 数据服务器因为需要对数据进行存储和索引等 IO 操作,所以更多地会考虑磁盘的转速和内存。 简单的做法就是应用和数据库部署在不同的机器上。
3. 添加缓存:突破数据库(IO)瓶颈
背景:数据库成为瓶颈,即使增加服务器的数量,也不能解决。数据增加对某些数据请求量特别大。获取这些信息的方式是依靠数据库,因此会受到数据库IO性能的影响,久而久之,数据库便成为了整个系统的瓶颈。
这时可以引入缓存技术:
- 加入缓存技术后,系统性能得到了提高。这是因为缓存位于内存中,而内存的读取速度要比磁盘快得多,能够很快响应用户请求。特别针对一些热点数据,优势尤为明显。
- 在可用性方面也有明显改善,即使数据服务器出现短时间的故障,在缓存服务器中保存的热点数据或者核心数据依然可以满足用户暂时的访问。
缓存技术分为:客户端浏览器缓存、应用服务器本地缓存和缓存服务器缓存
。
- 客户端浏览器缓存:
当用户通过浏览器请求应用服务器的时候,会发起 HTTP 请求。如果将每次 HTTP 请求都缓存下来(how),就可以极大地减小应用服务器的压力。- 应用服务器本地缓存:堆
这种缓存使用的是进程内缓存,又叫托管堆缓存。 由于它运行在内存中,对数据的响应速度很快,因此通常用于存放热点数据。当进程内缓存没有命中时,会到缓存服务器中获取信息,如果还是没有命中,才会去数据库中获取。- 缓存服务器缓存:例如redis
就是进程外缓存,由于缓存会占用内存空间,因此这类服务器往往会配置比较大的内存,通常部署到专门的机器。
用户请求访问数据的顺序为
客户端浏览器缓存→应用服务器本地缓存→缓存服务器缓存。如果按照以上次序还没有命中数据,才会访问数据库获取数据。
4. 服务器集群处理并发
随着用户请求量的增加,另外一个问题又出现了,那就是并发,即会出现多个用户同时请求应用服务器。这里可以通过部署多台应用服务器来分担单台的负载压力。
负载均衡器说明:
- 单台应用服务器中部署的应用服务并没有改变,在用户请求与服务器之间加入了负载均衡器,以便将用户请求路由到对应的服务器中。注意负载均衡器采用的均衡算法要能保证
a. 用户请求均匀地分布到多台服务器上
b. 请求的状态问题:属于同一个会话的所有请求在同一个服务器上处理
c. 针对不同服务器资源的优劣能够动态调整流量
- 由于负载均衡器位于互联网与应用服务器之间,因此可以对用户流量进行监控,同时对提出访问请求的用户的身份和权限进行验证,即也充当了网关的作用。
5. 数据库读写分离:释放读性能
5.1. 问题分析
加入缓存可以解决部分热点数据的读取问题,但缓存的容量毕竟有限,那些非热点的数据依然要从数据库中读取。
数据库对于写入和读取操作的性能是不一样的。在写入数据时,会造成锁行或者锁表,此时如果有其他写入操作并发执行,就会出现排队现象。读取操作不仅比写入操作更加快捷,并且可以通过索引、数据库缓存等方式实现。
5.2. 解决方案:读写分离
设置主从数据库,主库(master)主要用来写入数据,然后通过同步binlog 的方式,将更新的数据同步到从库(slave)中。对于应用服务器而言,在写数据时只需要访问主库,在读数据时只用访问从库就好了。
利用读数据效率较高的优势,扩展更多的从库,从而服务于请求读取操作的用户。毕竟在现实场景中,大多数操作是读取操作。8:2。
读写分离技术要考虑的问题:
- 数据同步技术可以分为同步复制技术、异步复制技术和半同步复制技术,
- 读写分离架构设计也需要考虑可靠性的问题。例如,如果主库挂掉,从库如何接替主库进行工作;之后主库恢复了,是成为从库还是继续担任主库,以及主从库如何同步数据。
6. 反向代理和 CDN
之前讨论的架构,用户都是通过客户端直接访问应用服务器获取服务,这使得应用服务器暴露在互联网中,容易遭到攻击。比如:流量攻击,非法请求等。可以在应用服务器与互联网之间加上一个反向代理服务器,由此服务器来接收用户的请求,然后再将请求转发到内网的应用服务器。
6.1. 反向代理的作用
反向代理服务器的作用:
- 反向代理服务器只对请求进行转发,因此当有人攻击它的时候,是不会影响到内网的应用服务器,这在无形中保护了应用服务器,提高了安全性。
- 反向代理服务器也在互联网与内网之间起适配(让公网客户端也能访问到内部服务)和网速转换(哪些用户使用高速、哪些用户使用低速等)的作用。如下例子:
应用服务器需要服务于公网和教育网,但是这两个网络的网速不同,那么就可以在应用服务器与互联网之间放两台反向代理服务器,一台连接公网,另一台连接教育网,用于屏蔽网络差异。
公网客户端和校园网客户端分别来自公网与校园网两个不同的网络,由于两者访问速度不同(为了满足这两个客户端不同流量需求),因此会分别设置公网反向代理服务器和校园网反向代理服务器,通过这种方式将位于不通网络的用户请求接入到系统中。(添加反向代理器是为了让公网客户端也能访问到某些内部服务)
6.2. CDN进一步加快静态资源的访问
CDN,它的全称是 Content Delivery Network,也就是内容分发网络。
如果把互联网想象成一张大网,那么每台服务器或者每个客户端就是分布在这张大网中的节点。节点之间的距离有远有近,用户请求会从一个节点跳转到另外一个节点,最终跳转到应用服务器获取信息。跳转的次数越少,越能够快速地获取信息,因此可以在离客户端近的节点中存放信息。这样用户通过客户端,只需要跳转较少的次数就能够触达信息。
由于这部分信息更新频率不高,因此推荐存放一些静态数据,例如 JavaScript 文件、静态的 HTML、图片文件等。这样客户端就可以从离自己最近的网络节点获取资源,大大提升了用户体验和传输效率。
优劣势
CDN 的加入明显加快了用户访问应用服务器的速度,同时减轻了应用服务器的压力,原来必须直接访问应用服务器的请求,现在不需要经过层层网络,只要找到最近的网络节点就可以获取资源。但从请求资源的角度来看,这种方式也有局限性,即它只对静态资源起作用,而且需要定时对 CDN 服务器进行资源更新。
7. 分布式数据库与分表分库
7.1. 分库分表
当数据量非常大时,即使添加了索引、缓存以及读写分离时,查询速度也很慢。这时可以考虑分布式数据库方案:从业务和数据层面对数据库进行分配。如下例子:
- 对于表来说:
假设有 1000 万个会员记录,既可以将其分成两个 500 万,分别放到两张表中存储,也可以按照业务对表中的列进行分割,把表中的某些列放到其他表中存储,然后通过外键关联到主表。(注意:被分割出去的列通常是不经常访问的数据。)- 对于库来说:
每个数据库能够承受的最大连接数和连接池是有上限的。为了提高数据访问效率,可以根据业务需求对数据库进行分割,让不同的业务访问不同的数据库(有点微服务的味道了)。
如果将数据库资源分别放到不同的数据库服务器中,就是分布式数据库设计。
7.2. 数据库中间件
由于数据存储在不同的表/库中,甚至在不同的服务器上面,因此在进行数据库操作的时候会增加代码的复杂度。此时可以加入数据库中间件来实现数据同步,从而消除不同存储载体间的差异。
如图,将数据拆分以后分别放在表 1 和表2 中,两张表所在的数据库服务器也不相同,库与库之间还需要考虑数据同步的问题。因为数据的分散部署,所以从业务应用获取数据时需要依靠数据库中间件的帮忙。
有一些数据库中间件提供了最佳实践,例如 MyCat 和Sharding JDBC。此外,从数据库服务器管理的角度来看,需要监控服务器的可用性。从数据治理的角度来看,需要考虑数据扩容和数据治理的问题。
注意:数据库的分布式设计以及分表分库,会给系统带来性能的提升,同时也增大了数据库管理和访问的难度。原来只需访问一张表和一个库就可以获取数据,现在需要跨越多张表和多个库。
8. 业务拆分:引入服务通讯与协调
通过对前面几个阶段的学习,我们知道系统提升依靠的基本都是以空间换取时间,使用更多的资源和空间处理更多的用户请求。
如果说前面的服务器集群模式是将同一个应用复制到不同的服务器上,那么业务拆分就是将一个应用拆成多个部署到不同的服务器中。
此外,还有的是对核心应用进行水平扩展,将其部署到多台服务器上。应用虽然做了拆分,但应用之间仍旧有关联,存在相互之间的调用、通信和协调问题。由此引入了队列、服务注册发现、消息中心等中间件,这些中间件可以协助系统管理分布到不同服务器、网络节点上的应用。
9. 分布式与微服务
分布式与微服务的区别:
拆分目的不同:
- 分布式设计是为了解决单体应用资源有限的问题,一台服务器无法支撑更多的用户访问,因此将一个应用拆解成不同的部分,然后分别部署到不同服务器上,从而分担高并发的压力。
- 微服务是对服务组件进行精细化,目的是更好地解耦,让服务之间通过组合实现高性能、高可用、可伸缩、可扩展。
拆分方式不同:
- 分布式服务架构将系统按照业务和技术分类进行拆分(比如Hadoop中的HDFS和Yarn),目的是让拆分后的服务负载原来单一服务的业务。
- 微服务则是更细的拆分(服务下不同的模块),它将服务拆成更小的模块,不仅更专业化,分工也更为精细,并且每个小模块都能独立运行。
部署方式不同:
- 分布式架构将服务拆分以后,通常会把拆分后的各部分部署到不同服务器上。
- 微服务既可以将不同的服务模块部署到不同服务器上,也可以在一台服务器上部署多个微服务或者同一个微服务的多个备份,并且多使用容器的方式部署。
从实践的角度来看,分布式与微服务都是基于分布式架构的思想构建的。可以说微服务是分布式的进化版本,也是分布式的子集,所以它同样会遇到服务拆分、服务通信、协同、管理调度等问题。
参考:《分布式架构原理与实践–崔皓》