架构训练营学习笔记之五技术选型(一)
技术选型(1):分布式缓存架构
1.1 缓存基本概念
缓存:存储在计算机上的一个原始数据复制集,以便于访问 – 维基百科
缓存( Cache )和缓冲 (Buffer )的分别?
缓存(cache):把常用数据存储到可以快速获取的区域(缓存区),以备重复利用,提高效率。
例如:从内存中读取数据时,先将常用的数据存放到缓存区,硬盘直接从缓存区读取。
缓冲(buffer):在数据流转过程中,不同层次数据速度不一致时,利用缓冲区来缓解上下层之间速度问题。增加速度。
例如:将数据写入到内存时,先写入缓冲区,内存则直接从缓冲区中读取写入,减少 IO 次数,增加速度,降低对磁盘的损耗
1.2 缓存的应用场景
CPU 缓存
L1/L2/L3
操作系统缓存
PageCache:Kafka/RocketMQ 持久化
数据库缓存
MySQL 5 查询缓存,注意 MySQL 8 已经彻底去掉了缓存
JVM 编译缓存
JVM 中 code cache(属于非堆内存)保存 JIT 编译的本地机器码、JNI 使用的本地方法代码
CDN 缓存
常见用法:静态资源放到 CDN,比如图片
代理与反向代理缓存
代理缓存
反向代理缓存:数据中心缓存
应用程序缓存
本地缓存,比如 google guava, caffeine, ehcache 等
分布式对象缓存
redis, memcached
1.3 缓存数据存储
典型:JDK HashMap 的数组+链表方式
1.4 缓存关键指标
缓存命中率
影响命中率的指标:
缓存键集合大小
缓存可使用内存空间
缓存对象生存时间
1.5 缓存方式
1.5.1 通读换出 read-through
通读缓存给客户端返回缓存资源,并在请求未命中缓存时获取实际数据。
客户端连接的是通读缓存而不是生成响应的原始服务器。
示例:代理缓存,反向代理缓存,CDN
1.5.2 旁路缓存 cache-aside
应用代码通常会询问对象缓存需要的对象是否存在,如果存在,它会获取并使用缓存的对象,如果不存在或已过期, 应用会连接主数据源来组装对象,并将其保存回对象缓存中以便将来使用。
示例:对象缓存,比如:
浏览器对象缓存
本地对象缓存
本地对象缓存构建分布式集群
互联网时代这种方式已被抛弃,数据重复浪费资源,数据同步浪费网络资源
分布式对象缓存
目前最常用
旁路缓存通常是一个独立的键值对(key-value)存储。
1.6 分布式对象缓存的一致性 hash 算法
参见白话解析:一致性哈希算法 consistent hashing
一般采用基于虚拟节点的一致性 Hash 算法,以便减轻集群扩容或是机器宕机的影响。
技术栈各个层次的缓存节省资源
只是一个粗略估计。
1. 7 合理使用缓存
缓存滥用的一些场景:
频繁修改的数据
一般说来,数据的读写比在 2:1 以上,缓存才有意义
没有热点的访问
若大部分数据访问不是集中在小部分数据上,那么缓存就没有意义
数据不一致与脏读
缓存雪崩
缓存预热 warm up
缓存穿透
解决:
方案 1:布隆过滤器
一般会采用 redis 的布隆过滤器,不过 guava 本身也实现了布隆过滤器,看使用场景
方案 2:将不存在的数据也缓存起来(其 value 值为 null),并设定一个较短的失效时间
技术选型(2):消息队列与异步架构
2.1 消息队列构建异步调用架构
点对点模型
发布/订阅模型
2.2 消息队列的好处
异步处理,提高性能
解耦
削峰填谷
伸缩性
失败隔离,自我修复
事件驱动架构
2.3 消息队列产品比较
可以将搜索引擎搜索结果作为项目活跃度的一个参考。
详情可以参考之前我整理的这篇文章: https://blog.csdn.net/evasnowind/article/details/109208079 此处就不展开说了。
2.4 引入消息队列的缺点
1. 系统可用性降低
系统引入的外部依赖越多,越容易挂掉,如果 MQ 出问题,整个系统可能挂掉。
2. 系统复杂性提高
可能出现如下问题:
消息重复消费
消息丢失
消息积压
如何保证消息传递的顺序性
如何保证消息队列的高可用
3. 一致性问题
A 处理完直接返回成功,但是 BCD 中,C 失败了,导致数据不一致。
技术选型(3):负载均衡
3.1 常见负载均衡服务器实现
HTTP 重定向负载均衡
DNS 负载均衡
反向代理负载均衡
IP 负载均衡
数据链路负载均衡
3.2.常见负载均衡服务器实现的优缺点
下面各种负载均衡的具体实现、详细内容可以参考《大型网站技术架构——核心原理与案例分析》“6.2 应用服务器集群的伸缩性设计”
3.2.1 HTTP 重定向负载均衡
存在安全问题:负载均衡服务器进行转发给内网服务器时,会暴露内网服务器的 IP,容易受到攻击
浏览器需要两次请求服务器才能完成一次访问,性能较差;重定向服务器本身的处理能力有可能成为瓶颈,整个集群的伸缩性规模有限;
使用 HTTP 返回码 302 重定向,有可能使搜索引擎判断为 SEO 作弊,降低搜索排名。
3.2.2 基于 DNS 的两层负载均衡
两层负载均衡,大型互联网系统基本必备
第一层:DNS
第二层:DNS 指向的是作为第二层负载均衡的服务器的 IP 地址
不同用户访问同一个 DNS,得到不同的服务器——CDN 的原理。DNS 中配置 A 记录,即可实现。
3.2.3 反向代理负载均衡
本地有走本地,没有则将请求转发给后面的服务器,转发时会进行负载均衡。
比较常见,适合规模比较小、服务器有几台、十几台的规模)的情况,大型网站用的很少,因为性能较低、效率比较差
因为是应用层协议,使用 HTTP 进行负载均衡,需要进行应用层的协议转化,收到一个 TCP 协议包还要等待、需拿到完整的请求包、响应包(TCP/UDP 攒成一个完整的 HTTP 报文)才能进一步操作
3.2.4 IP 负载均衡
在 IP 这一层进行负载均衡,拿到 TCP 数据包后,将数据包的 IP 立马修改为应用服务器的 IP;应用服务器返回响应也要返回给这台负载均衡服务器,负载均衡服务器再将响应数据包中目标地址 IP 修改。
计算压力比反向代理(HTTP 层)小,处理能力要大得多
问题:响应数据量
请求数据包一般比较小,但响应数据包可能会比较大(比如图片),负载均衡服务器的网卡带宽可能成为瓶颈
3.2.5 数据链路层负载均衡
使用 MAC 地址,负载均衡服务器不用处理
技巧:负载均衡服务器与应用服务器采用相同的 IP,虚拟 IP,负载均衡服务器不用修改 IP 地址、只修改 MAC 地址,改为应用服务器 MAC,响应数据不用经过负载均衡服务器、直接返回给用户
又被称为“三角模式”。
3.3 负载均衡算法
轮询:适合于所有服务器硬件都相同的场景。
加权轮询:根据应用服务器硬件性能的情况,在轮询的基础上,按照配置的权重将请求分发到每个服务器,高性能的服务器分配更多请求
随机:在许多场合下,这种方案都很简单实用,因为好的随机数本身就很均衡。如果应用服务器硬件配置不同,也可以很容易的使用加权随机算法。
最少连接:
不常见,因为意义不大
源地址散列
不常见,会话粘滞一般不会通过这个做
3.4 应用服务器集群的 session 管理
session 管理也是考虑负载均衡算法的因素
session 复制
问题:要复制给所有服务器,在实际应用几乎没人使用
session 绑定
session 源地址散列,实践中几乎不使用,因为互联网应用除了性能还会关注高可用,如果这台服务器宕机,会导致数据丢失、无法保证高可用
通过 cookie 记录 session
上下文记录 cookie,请求中包含 cookie,会话不用依赖服务器,问题 cookie 不大、只能记录少量数据,且有些场景会禁用 cookie,实践中较为常用
使用 session 服务器
应用服务器不记录 session,设置单独的共享 session 服务器,服务器宕机、扩容都不影响,最常见的 session 方案,应用服务器是无状态的,即无状态的应用服务器
参考资料
大型网站技术架构
版权声明: 本文为 InfoQ 作者【于成龙】的原创文章。
原文链接:【http://xie.infoq.cn/article/1d5967caf0a429f76a1e972ac】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论