文章目录

  • 系统大致架构
  • 可扩展性
  • 负载均衡器与会话保持
  • 引入冗余增强系统可用性
  • 缓存减轻数据库压力
  • 异步处理
  • 参考

系统大致架构

当一个用户请求从客户端出发,经过网络传输,达到 Web 服务层,接着进入应用层,最后抵达数据层,它所途径的过程如下:

对应到系统设计的逻辑层:

运作机制如下:
1、客户端查DNS得到服务对应的IP地址,可能指向位于Web服务之前的负载均衡器,也可能是CDN,就近提供对象存储中的静态资源
2、发向Web服务的请求被负载均衡器(如反向代理)按照既定策略分给相应的Web服务器,进入应用层
3、请求到达应用层后,经过Service Discovery、Service Mesh等服务查询机制找到目标微服务,开始处理请求
4、数据请求会通过一系列读写操作转移到数据层,异步的操作还会进入消息队列排队,但最终都会抵达数据层
5、对热点数据的请求会被数据库之前的缓存层挡下,其余的落到数据库,可能是经过分库分表、反范式优化,并由复制机制保证数据一致性的SQL数据库,也可能是查询性能更好的Nosql数据库抑或是对象存储来保存数据。

接下来的系统设计主要就是围绕这几个关键的逻辑组件展开。

可扩展性

可扩展性,意味着能够通过向系统添加资源的方式应对不断增加的工作量。而加资源有两种方式:

  • 纵向扩展(Vertical scaling):即提升单机配置,对单台机器加内存、处理器、硬盘等硬件资源。投入足够多的预算,就能砸出一台配置豪华的服务器
  • 横向扩展(Horizontal scaling):即加机器,数量上从一台扩展到多台,多服务器形成拓扑结构。投入足够多的预算,就能拥有一个机房,甚至遍布全球的数据中心
    对于系统设计而言,可扩展性要求系统能够将加入进来的更多资源(如多核、多机)利用起来。
    机器由一台变成多台之后,面临的最大问题是资源分配,如何充分利用这些机器?即,如何均衡负载?

负载均衡器与会话保持

负载均衡器(Load Balancer)负责把用户请求分发到多个服务器上,具体的,公网 Load Balancer 根据路由规则分发入站 HTTP 请求,决定把数据包实际发送给哪个内网服务器。常见的策略是基于负载情况分发、轮流均分、基于资源依赖情况分发。不建议用 DNS 来充当负载均衡器,因为操作系统以及应用层的 DNS 缓存会破坏这种轮流均分的机制。另一方面,不同类型的服务对资源的依赖情况(带宽、存储、计算能力等)可能不一样,所以也可以采用专用服务器,并根据资源依赖情况分发,比如对 gif、jpg、image、video 等使用不同的专用服务器,并通过子域名等方式来区分
会话保持:
加一层 Load Balancer 解决了资源分配的问题,但又带来了一个新问题:前后两个请求可能被负载均衡器转发到不同的服务器上,如果这两个请求有关联(比如登录和下单),前置的状态就会丢失(用户刚登录完点击下单接着可能又要求登录)
一种解决办法是粘滞会话(Sticky sessions),把相关联的请求转发给同一台服务器:
比如在 Cookie 中带上服务器的标识信息,之后的一系列请求都转给那台服务器,但 Cookie 可能会被禁用,因此一般会综合使用多种方式来保持会话
另一种方案是把 Session“外包”出去,存放到公共的地方,供其它服务器共享访问:
每台服务器都包含完全相同的代码库,不在本地光盘或内存中存储任何与用户相关的数据,如会话或个人资料图片。会话需要存储在所有应用服务器都可以访问的集中数据存储中。
至此,我们增加了一些机器,并通过一个负载均衡器让多台机器共同分担运转起来了,看起来一切都很完美……那么,如果这个负载均衡器 down 掉了呢?

引入冗余增强系统可用性

引入负载均衡器之后,所有请求都要先经过负载均衡器,负载均衡器就成为了网络拓扑结构中脆弱的单点,一旦发生故障,身后的所有服务器就都无法访问了。
为了避免单点故障(Single Point of Failure),负载均衡器同样需要引入冗余(比如使用一对儿负载均衡器),一般有两种故障转移(Fail-over)模式:

  • 主动-被动(Active-passive):主动的工作,被动的备用,主动的 down 掉后被动的上
  • 主动-主动(Active-active):同时工作,一个 down 掉之后不影响
    无论采用哪种工作模式,引入冗余都能缩短宕机时间,提升系统可靠性与可用性

理论上,有了可靠的负载均衡机制,我们就能将 1 台服务器轻松扩展到 n 台,然而,如果这 n 台机器仍然使用同一数据库的话,很快数据库就会成为系统的性能瓶颈和可靠性瓶颈
如法炮制,我们可以扩展数据库的处理能力,多加几个库,即引入冗余,一般有两种模式:

  • 主从复制:主库直接读写,从库在主库收到查询时,执行相同的查询。如果主库 down 掉了,就在从库里面提升一个作为主库
  • 主主复制:都可以写,写操作也会被复制到另一个库中
    数据库引入冗余之后,甚至还能对多个从库进行负载均衡(尤其适用于读密集的场景):

    以及按内容特点分区存储(Partitioning):

    将姓名以 A-M 开头的数据存放到左边的几个数据库,N-Z 开头的存放到右边

同时,也可以通过分库分表(Sharding)、反范式化(Denormalization)、SQL 调优(SQL tuning)等方式优化查询

缓存减轻数据库压力

尽可能减少数据库操作,比如在 Web 服务与数据之间增加一层内存缓存,查询时优先走缓存,缓存中没有才从数据库中取。
一般有两种缓存模式:

  • 缓存查询结果
  • 缓存对象
    缓存所有查询结果最大的问题在于,数据发生变化后,很难判定缓存是否过期:
在缓存复杂查询时,很难删除缓存的结果(谁没有?)。
当一段数据发生更改(例如表单元格)时,需要删除可能包含该表单元格的所有缓存查询。

而缓存对象是指缓存根据原始数据组装出的数据模型(比如一个 Java 类实例),优势在于获知数据变化之后,能够丢弃与之具有逻辑关联的数据对象,从而解决缓存过期的难题。
至此,我们已经自下而上地讨论了包括硬件资源、数据库、缓存在内的可扩展性问题,那么,Web 服务自身应该如何扩展?

异步处理

对于 Web 服务而言,提升可扩展性的主要途径是将耗时的同步工作改成异步处理,从而允许将这些工作“外包”给多个 Worker 去做,或者提前完成能够预知的部分.

参考

1、http://gotocon.com/dl/goto-aar-2012/slides/MartinThompson_ItsAllANumbersGameTheDirtyLittleSecretOfScalableSystems.pdf
2、http://www.ayqy.net/blog/scalability-in-the-real-world/
3、https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md

后台系统可扩展性学习笔记(一)概要相关推荐

  1. 后台系统可扩展性学习笔记

    整理了一下笔记目录,将以前学习的一些知识串联起来了,比如cdn.负载均衡.中间件,以前只是各自了解了一点,现在大概理清了后台系统设计中他们各自的作用. 后台系统可扩展性学习笔记(一)概要 后台系统可扩 ...

  2. 后台系统可扩展性学习笔记(十四)异步机制与MQ

    对于 Web 服务而言,提升可扩展性的主要途径是将耗时的同步工作改成异步处理,从而允许将这些工作"外包"给多个 Worker 去做,或者提前完成能够预知的部分. 异步机制与可扩展性 ...

  3. 后台系统可扩展性学习笔记(十二)NoSQL

    文章目录 NoSQL定义 NoSQL种类 键值存储 文档存储 宽列存储 图形数据库 NoSQL 意味着什么 ACID vs. BASE SQL or NoSQL NoSQL定义 不同于关系型数据库,N ...

  4. 后台系统可扩展性学习笔记(十)Database Partitioning

    为了提升数据库的处理能力,我们把单库扩展成多库,并通过更新同步机制(即Replication)来保证多份数据的一致性.然而,在 各种复制方案下,每个数据库都持有一份完整数据,基于全量数据提供增删改查服 ...

  5. 后台系统可扩展性学习笔记(十一)Database Denormalization

    之前的两篇笔记中谈到了从单库扩展到多库以承载更多的请求量以及单库(表)拆分成多库(表),打破单库的性能瓶颈. 这都是为了应对大数据量下的措施. 然而,除却数据量外,还有一个极其影响单库性能的因素--数 ...

  6. 后台系统可扩展性学习笔记(七)Service Discovery与微服务

    文章目录 应用层 微服务架构 服务注册查询 Service Discovery 客户端 Service Discovery DNS-SD DNS-based Service Discovery 服务端 ...

  7. 后台系统可扩展性学习笔记(五)负载均衡

    文章目录 Load balancer(负载均衡器) 请求传输拆解 DNS 负载均衡 客户端负载均衡 OSI 七层模型回顾 2 层.3 层负载均衡 3/4 层负载均衡 7 层负载均衡 在 第一节谈到了系 ...

  8. 后台系统可扩展性学习笔记(十三)缓存

    文章目录 在哪儿加缓存 缓存什么内容 缓存原始查库结果 缓存数据对象 怎么查询缓存结果 预留缓存模式 直读模式 直写模式 回写式缓存 绕写式缓存 提前刷新模式 缓存满了如何处理 参考 读写分离.分库分 ...

  9. 后台系统可扩展性学习笔记(三)DNS机制原理

    文章目录 DNS概念梳理 域名基本概念 资源记录基本概念 路由策略 DNS 域空间结构 实现原理 复制机制 查询机制 缓存机制 参考 DNS概念梳理 DNS(Domain Name System)相当 ...

最新文章

  1. 基于LM567制作的反射式红外检测电路,用于节能信标检测电路
  2. 小米8的MIUI12系统预置应用正在恢复
  3. sphinx配置 + php
  4. Python List sort()方法
  5. 易语言 网页用什么编码_Plessey条码用的什么编码方式?
  6. fetch 另一种ajax解决方案
  7. mac好用的软件 小总结 Alfred
  8. 谈表单的设计 (一) 合理对表单进行布局
  9. Lan Xiang's Square nyoj 1099(已经四边形四点坐标 如何判断正方形)
  10. [openssl]centos version ‘libcrypto.so.10‘ not found
  11. single-spa
  12. 5254. 卖木头块 动态规划
  13. android桌面小部件开发
  14. python字母对照表_Python中的字母范围
  15. SpringBoot 接口数据加解密
  16. 23、动画及视野拓展
  17. STM32 cubeIDE 堆栈大小设置
  18. 堡垒机前戏:paramiko模块
  19. 社会保障计算机考试证书查询,便利查|打开电子社保卡可查询职业资格证书啦!...
  20. FFmpeg:常用命令小笔记

热门文章

  1. javaScript学习笔记之比较运算符||逻辑运算符||条件运算符(三目运算符)
  2. [Vulhub](WooYun-2016-199433)phpmyadmin反序列化漏洞
  3. mysql构建栋_【转载】这次拆库 应是微服务化的拆分方式
  4. python怎么改目录_如何查看文件,而不是使用Python进行更改的目录?
  5. mysql主从复制时间配置_MySQL主从复制配置
  6. 2.2 .this的绑定规则
  7. 精美的手机界面设计素材和线框图设计工具推荐
  8. Chrome不显示OPTIONS请求的解决方法2021版chrome90
  9. 移动端 flexible.js 布局详解
  10. 用递归方式判断字符串是否是回文