原文地址:https://newsletter.systemdesigncodex.com/p/8-strategies-for-reducing-latency
分布式后端系统的 “延迟”,等同于单体系统的 “宕机”
高延迟会使应用程序实际上无法使用,使用户感到沮丧,并对业务产生与服务不可用一样的负面影响。对现代用户来说,网站缓慢的速度甚至比不可用更具灾难性。
0 - TLDR;
你能学到什么
这是一篇介绍减少服务延迟基础技术的概览性文章,你将学到一些减少服务的基础概念和基础策略
你不能学到什么
- 对于新手入门可能有很大帮助,但是并不包含任何进阶内容
- 仅包括对于 基础概念和基础策略 的介绍,但并不包括任何实现细节
整体蓝图
- 缓存
- 内容交付网络(CDN):也是一种缓存策略
- 负载均衡
- 异步处理
- 数据库索引
- 数据压缩
- 数据预处理:也是一种缓存策略
- 使用 Keep-Alive 机制
1 - 缓存
缓存是分布式系统中用于提高性能和减少后端服务负载的基础技术。
缓存的主要目标是最大限度地减少昂贵的数据库查找,以及避免重复执行高延迟计算。
通过将经常访问的数据存储在缓存中,与从源(例如数据库或远程服务)获取数据相比,应用程序可以更快地检索数据。
缓存通常使用内存或快速存储系统(例如 redis)来实现,以提供对缓存数据的低延迟访问。
2 - 内容交付网络(CDN)
虽然缓存是提高性能和减少后端服务负载的强大技术,但可以通过利用内容交付网络(CDN)将访问延迟降低到一个新的水平。
CDN 是一个地理分布的服务器网络,它们协同工作,以高可用性和高性能向最终用户提供内容。
CDN 通过更接近最终用户的内容缓存来减少延迟。(即 CDN 本质上也是一种缓存技术)
当用户从使用 CDN 的网站或应用程序请求内容时,请求会被重定向到最近的 CDN 服务器而不是源服务器。
如果请求的内容已经缓存在 CDN 服务器上,则直接从缓存中提供,无需从源服务器检索。这减少了数据必须传播的距离并最大限度地减少了响应时间。
3 - 负载均衡
负载均衡是在多台机器之间分配工作负载的一项非常重要的技术。
通过使用负载均衡器在多个服务器之间分配请求流量,我们确保没有单个服务器变得不堪重负。换句话说,系统可以根据用户流量进行扩容和流量分配。
当客户端向分布式系统发送请求时,负载均衡器充当初始对接人,它接收传入的请求,并根据预定义的算法或策略智能地将其路由到可用的服务器之一。
常见的负载平衡算法包括:
- Round Robin:轮询
- Least Connections:最少连接
- IP Hash:IP哈希
4 - 异步处理
在分布式系统中处理长时间运行的任务时,考虑用户体验和整体系统响应能力非常重要。
实现异步处理是一种强大的技术,它允许系统在后台执行进一步处理的同时快速响应用户。
以下是它的工作原理:
- 在异步处理模型中,当用户启动长时间运行的任务时,例如生成复杂的报告或处理大型数据集,系统会立即确认请求并向用户返回响应。
- 立即返回给用户的响应表明已收到请求并正在处理中。
- 在后台,系统将任务排入队列系统,等待执行。
- 单独的后台进程池持续监控此队列,并在任务可用时拉取并执行它们。
- 工作进程异步执行长时间运行的任务,不会阻塞主应用程序线程以及影响系统的响应能力。
5 - 数据库索引
如果设计不当,数据库可能会成为数据库延迟的主要来源。
为了确保最佳的数据库性能和更快的查询处理,实现正确的索引,以及识别和重构慢速数据库查询至关重要。
索引在提高数据库查询效率方面起着至关重要的作用。
通过在经常访问的列或列组合上创建适当的索引,数据库可以快速定位和检索所需的数据,而无需扫描整个表。这减少了处理查询所需的时间和资源,特别是对于大型数据集。
6 - 数据压缩
通过网络传输数据时,尤其是在分布式系统中,考虑发送数据的大小是一件很重要的事情。
更大的数据会消耗更多的网络带宽、增加延迟并影响整体系统性能。
为了缓解这些问题,一种常见的技术是在通过网络发送数据之前压缩数据。
数据压缩涉及通过使用压缩算法来减少数据冗余、更加高效的进行数据表示。压缩数据有几个好处:
- 减少带宽使用
- 改进的延迟
- 有效利用资源
- 成本节约
7 - 预处理
预缓存是一种用于主动缓存数据以应对未来请求的技术。
这个想法是提前缓存被访问概率很高的数据,以便您可以在用户请求时更快地提供服务。
8 - 使用 Keep-Alive 连接
TCP 握手对于可靠地端对端数据传输是至关重要过程
但是,此过程在网络延迟和资源消耗方面可能代价高昂,因为它涉及客户端和服务器之间的多次往返。
为了优化与建立新TCP连接相关的开销,建议尽可能重用现有连接。
连接重用,也称为链接池,是一种允许通过同一传输控制协议发送多个请求的技术,减少了为每个请求建立新连接的需要。
注:Keep-Alive 请求头在客户端侧一般是自动携带的,在服务侧的使用取决于服务端使用的后端框架,一般不需要自行处理技术细节
- 对于 java 的 spring 技术栈,tomcat 是可以自动使用 Keep-Alive 机制的,当然可以通过调整配置参数来改变这一机制的性能;
- 对于 python 的框架,例如 flask、Django,是无法利用 Keep-Alive 机制的,所以需要前置网络服务器,例如 gunicorn 等