架构训练营——第五周学习总结
技术选型
分布式缓存架构
基本概念
缓存的定义
存储在计算机上的原始数据复制集,用于加快数据访问
缓存是介于数据访问者和数据源之间的一种高速存储,当数据需要多次读取的时候,用于加快读取的速度
Cache VS Buffer
Buffer:置于高速设备和低速设备的中间装置,用来处理不同设备的读写性能不匹配的问题,针对读/写场景均可以使用 Buffer
Cache:主要针对多次读取的场景,用于提升读性能
缓存的应用场景
系统维度
CPU 高速缓存(L1、L2、L3)
操作系统缓存
数据库缓存
JVM 编译缓存
架构维度
CDN 缓存
代理与反向代理缓存
APP 与浏览器缓存
应用本地缓存
分布式缓存
缓存的数据存储
Hash 表
缓存命中率
命中率是衡量缓存使用效果的关键指标
影响命中率的主要指标
缓存 key 空间大小
key 的空间越大,缓存被重用的概率就越小
要尽可能减少缓存 key 的数量,提升缓存命中率
缓存的可用空间(一般指内存)
一般来说,物理上能缓存的对象数量越多,缓存命中率越高
缓存对象的生存时间(Time To Live,TTL)
缓存对象的生成时间越长,缓存命中率越高
较长的 TTL 可能导致读取到过期数据,需要在命中率和数据一致性之间进行 trade-off
访问形式
通读缓存(read-through)
由通读缓存负责给客户端响应缓存数据,并且在缓存未命中时查询数据源
客户端不会直接访问数据源
旁路缓存(cache-aside)
旁路缓存通常是一个独立的缓存服务
当客户端请求缓存失效时,会由客户端主动向数据源发起访问
应用场景
代理缓存
与用户部署在一起
代理用户上网
反向代理缓存
代理整个数据中心的服务
多层反向代理缓存
CDN
提供用户就近访问的能力
CDN 也可以同时代理静态资源和动态请求
浏览器对象缓存
本地对象缓存
远程分布式缓存
缓存越前置,就可以节约越多的资源,对性能的提升就越显著
一致性 Hash 算法
基础的 Hash 取余算法,一旦涉及服务的扩缩容,就会造成大量的缓存 key 映射关系发生变化,从而导致缓存大量失效,因此引入一致性 Hash 算法
0~(2^32-1) 个点,组成 Hash 环
服务器节点位于 Hash 环上
对 key 进行 Hash 操作,得到的 hashCode,在 Hash 环上顺时针找到第一个命中的服务器节点
问题
服务器节点在 Hash 环上分布不均匀,导致服务器负载压力不均衡,数据倾斜
添加服务器节点后,对负载的分摊不均衡
基于虚拟节点的一致性 Hash 算法
每个物理服务器节点,对应多个虚拟的 Hash 节点,均匀散落在 Hash 环上
缓存是性能优化的大杀器
缓存的数据通常来自于内存,访问速度远高于磁盘
缓存数据是最终结果,不需要中间的计算过程,减少了对 CPU 的消耗
缓存降低了数据库、磁盘、网络带宽的压力,使得这些 IO 设备可以获得更好的响应特性
使用缓存的注意事项
数据频繁修改
缓存只适用于读多写少的场景
读写比至少要高于 2:1 ,缓存才有意义
数据无明显热点
数据无明显热点,就会导致缓存刚构建好就被淘汰了,缓存命中率不会很高
缓存淘汰算法
LRU
LFU
FIFO
数据不一致与脏读
合理设置缓存过期时间
源数据更新后,删除缓存
缓存雪崩
缓存预热 warm up
在高并发场景下,服务启动前,对热点数据进行缓存预热,避免服务冷启动
缓存穿透
缓存空值,并设置较短的过期时间
Redis VS Memcached
Redis 支持丰富的数据结构
Redis 支持 IO 多路复用
Redis 支持主从复制高可用
Redis 支持原生集群和 Share Nothing 集群模式
消息队列架构
缓存主要用来优化读性能,而消息队列异步化主要用来优化写性能
同步调用 VS 异步调用
基于消息队列构建异步调用架构
消息队列
消息生产者
消息消费者
消息模型
点对点
发布订阅
消息队列的优势
实现异步处理,提升写性能
更好的伸缩性
削峰填谷
失败隔离和自我修复
解耦
事件驱动架构 EDA
请求/响应耦合表面积
负载均衡架构
负载均衡的意义:使用集群分摊负载,提升整体吞吐量
实现策略
HTTP 重定向负载均衡
部署独立的重定向服务,为用户请求返回 ResultCode=302,并且在响应头中增加重定向的 IP 地址
优势
实现简单
劣势
每次请求都要经过一次重定向,增加网络通信压力,效率低、性能差
直接暴露应用服务器的公网 IP,存在安全隐患
DNS 负载均衡
在域名解析阶段,为用户返回不同的应用服务器 IP 地址
优势
可以方便地实现一个域名下注册多个 IP 地址
不再需要自己部署负载均衡服务器
本地会缓存路由表,无需每次请求都去做域名解析
双层负载均衡架构
外层通过 DNS 负载均衡,将用户请求的域名解析为内网反向代理服务器的 IP 地址
内层基于反向代理负载均衡,返回内网具体应用服务器的 IP 地址
大型互联网公司广泛采用
反向代理负载均衡
七层负载均衡
负载均衡服务器装了两块网卡,一块连接外网用于处理用户请求,另一块连接内网用于代理应用服务器集群
使用反向代理服务器,代理整个应用服务集群
优势
实现简单,搭建方便
广泛应用于小规模集群
劣势
反向代理服务器需要转发完整的 HTTP 请求和响应,对性能有一定影响(应用层协议通常比较重)
不适用于大规模集群
IP 负载均衡
三层负载均衡
直接修改用户请求的 TCP/IP 数据包
将源地址改为负载均衡服务器的地址
将目标地址改为具体一台应用服务器的地址
转发 TCP/IP 数据包
不需要对应用层协议进行处理,性能较高
当响应包过大时,负载均衡服务器的带宽会达到瓶颈
数据链路层负载均衡
二层负载均衡
应用服务器通过虚拟 IP 连接外网,与用户直接交互
直接修改 MAC 地址
由应用服务器直接响应请求,无需经过负载均衡服务器,减少了负载均衡服务器的压力,提升响应性能
是大型互联网公司广泛采用的负载均衡策略
负载均衡算法
round-robin
轮询,适用于所有服务器配置都相同的场景
weighted-round-robin
加权轮询,可以为性能较高的服务器设置更高的权重,让其分摊更多请求
random
随机,实现简单,且更容易实现负载的均衡
least-connection
最少连接,将新的请求分配给当前连接数最少的服务器,也是最符合负载均衡定义的算法
需要额外的计算器实现,性能有一定损失,且容易出现计算不准确的问题
ip-hash
源地址散列,同一个 IP 的请求始终转发到同一台服务器,可以实现会话粘滞
分布式 Session 管理
Session 复制
每个 Session 都在每台应用服务器上都复制一份
优势
实现简单
劣势
Session 的同步会造成额外的网络通信压力
每个 Session 保存多份,数据存储压力大,浪费空间
性能差、伸缩性不好
Session 绑定
将请求源 IP 的 Session 固定绑定到一台服务器上
优势
实现简单
节省空间
劣势
可用性低,一旦某台服务器宕机,则上面保存的 Session 会全部丢失
使用 Cookie 记录 Session
将 Session 完整地保存在请求的 Cookie 里
优势
不需要依赖应用服务器
劣势
Cookie 大小有限
某些场景下 Cookie 会被禁止
当 Session 数据较少时,是一种不错的方案
分布式 Session 服务器
使用专门的 Session 服务器集群管理 Session
优势
可以对 Session 集中管理
实现应用服务器的无状态
高可用
高可扩展
Share Nothing 架构的可扩展性是最高的
是目前应用最广泛的方案
评论