系统设计 System Design -2-1-分布式系统、负载均衡、缓存

26 阅读6分钟

分布式系统的主要特征

可拓展性、可靠性、可用性、效率和可管理性

  • 可拓展性

    • 水平拓展:向资源池中添加更多服务器(CassandraMongoDB)通常不停机拓展
    • 垂直拓展:向现有服务器中添加更多功能(CPU、RAM、存储等)需要停机,且有上限
  • 可靠性

    • 分布式系统即使在一个或多个软件或硬件组件发生故障时仍能继续提供服务
    • 冗余是有成本的
  • 可用性

    • 系统、服务或机器在正常条件下保持运行的时间百分比
    • 可靠性:考虑到现实世界中可能发生的各种情况。可靠,则可用。但是,即使可用,也不一定可靠。
  • 效率:

    • 响应时间:系统节点全局发送的消息数量,无论消息大小
    • 带宽:表示数据交换量的消息大小
  • 可维护性或可管理性

    • 系统修复或维护的简易性和速度

    • 例如:减少或避免系统停机


负载均衡(LB)

平衡各层负载:

  • 在用户和 Web 服务器之间
  • Web 服务器和内部平台层(如应用程序服务器或缓存服务器)之间
  • 内部平台层与数据库之间。

image.png

负载均衡的好处:用户不用排队,避免瘫痪,流量预测+决策,减少设备压力

负载均衡方法:

  • 最少连接方法——此方法将流量导向活动连接数最少的服务器。用于当存在大量持久客户端连接且这些连接在服务器之间分布不均时。
  • 最少响应时间方法——该算法将流量引导至具有最少活动连接和最短平均响应时间的服务器。
  • 最小带宽方法- 此方法选择当前服务流量最少的服务器(以兆比特每秒 (Mbps) 为单位)。
  • 循环方法——此方法循环遍历服务器列表。用于当服务器规格相同且持久连接不多时。
  • 加权循环调度方法——每个服务器都被分配一个权重,权重较高的服务器会先于权重较低的服务器获得新的连接。
  • IP 哈希——在此方法下,计算客户端 IP 地址的哈希值以将请求重定向到服务器。

冗余负载均衡器

  • 每个负载均衡器都会监控另一个负载均衡器的运行状况,如果主负载均衡器发生故障,第二个负载均衡器将接管工作。


缓存

缓存是一个高速存储层,位于应用程序和原始数据源(例如数据库、文件系统或远程 Web 服务)之间

由于之前总结的缓存方式有重叠,非常抱歉,在自己复习检查中发现可以用更清晰的结构分层,以下为大模型帮我总结的,感觉很清晰:

  1. 客户端缓存 (Client-Side Cache)

    • 位置:用户的个人设备上(浏览器、手机App)。
    • 例子:浏览器缓存 (.js, .css, 图片)、App的本地存储。
  2. 网络中的缓存 (In-Network Cache)

    • 位置:在用户和你的服务器之间的网络路径上。

    • 例子

      • CDN 缓存:最典型的代表,位于全球各地的边缘节点上。
      • DNS 缓存:位于各级 DNS 服务器上。
  3. 服务器端缓存 (Server-Side Cache)

    • 位置:你自己控制的数据中心/服务器上。

    • 这个类别下面又可以按存储介质细分:

      • 内存缓存 (In-Memory Cache) :存在服务器的内存里。速度最快,但容量有限,断电即失。
      • 磁盘缓存 (Disk-Based Cache) :存在服务器的硬盘上。速度比内存慢,但容量大,可持久化。

缓存失效(考虑的方面)

  • 确保数据新鲜度:缓存和元数据的一致性
  • 保持系统一致性:多个缓存层间的一致性
  • 平衡性能和准确性:有效的缓存失效策略(例如,生存时间/TTL、手动触发、基于事件的失效)
  • 减少错误和不匹配状态:策略性地使缓存无效

三种缓存失效方案

  • 直写式缓存:同时写入缓存和相应的数据库

    • 优点:不因意外丢数据
    • 缺点:写入延迟高
  • 绕写式缓存:绕过缓存,直接写入永久存储

    • 优点:减少缓存被写入淹没
    • 缺点:读取会导致“缓存未命中”
  • 写回缓存:数据仅写入缓存,定时写入永久存储

    • 优点:为写密集型应用带来了低延迟和高吞吐量
    • 缺点:数据会因意外丢失

缓存失效方法

  • 清除:直接删
  • 刷新:替换
  • Ban:批量删
  • 生存时间 (TTL) 过期
  • Stale-while-revalidate:此方法用于 Web 浏览器和 CDN,即允许向用户快速提供过时内容,再进行更新缓存

缓存读取策略

  • 读取缓存(缓存是桥):缓存中不存在,缓存帮着找

    • 适用情况:逻辑简单,但不好个性化
  • 读取旁路缓存(缓存是一端):缓存不帮着找,后端自己找

    • 适用情况:希望根据特定的数据访问模式优化缓存使用率的情况

缓存驱逐策略

  1. 先进先出 (FIFO):缓存会逐出最先访问的第一个块,而不考虑之前访问的频率或次数。
  2. 后进先出 (LIFO):缓存首先逐出最近访问的块,而不考虑之前访问的频率或次数。
  3. 最近最少使用 (LRU):首先丢弃最近最少使用的项目。
  4. 最近使用 (MRU):与 LRU 相反,首先丢弃最近使用的项目。
  5. 最不常用(LFU):计算某项物品的需要频率。最不常用的物品会被优先丢弃。
  6. 随机替换(RR):随机选择一个候选项目并在必要时丢弃它以腾出空间。

联合总结:

线路一:通用读多写少场景 (90% 的选择)

读时查缓存,没有再查库; 写时先操作,完事删缓存。

  • 战术核心:Cache-Aside + 主动删除
  • 关键词:读走旁路,写后即删。
  • 适用:绝大多数 Web 应用、内容平台、电商网站。

线路二:高频写入、性能压榨场景

写入闪电般,只管怼内存; 后台慢慢写,丢点不要紧。

  • 战术核心:Write-Back
  • 关键词:内存先行,异步刷盘。
  • 适用:计数器、日志、监控数据上报等对写入延迟极度敏感,且能容忍少量数据丢失的场景。

线路三:金融级、强一致性场景

写入必须稳,两边一起等; 缓存数据库,一步都不能省。

  • 战-术核心:Write-Through
  • 关键词:同步双写,绝对一致。
  • 适用:银行交易、支付状态、核心订单等绝对不能出错或丢失数据的场景。