paint-brush
高效后端、卓越性能:深入探讨 Web 服务优化经过@sergeidzeboev
890 讀數
890 讀數

高效后端、卓越性能:深入探讨 Web 服务优化

经过 Sergei Dzeboev8m2023/11/21
Read on Terminal Reader

太長; 讀書

优化 Web 服务的后端不仅仅是改进代码和算法。提高服务效率的关键是优化数据库交互。这可以通过微调 ORM 查询、使用平面数据类、将数据正确分类为热、温或冷以及采用有效的缓存策略来实现。这些步骤将带来更高效、响应更快且高性能的 Web 服务。
featured image - 高效后端、卓越性能:深入探讨 Web 服务优化
Sergei Dzeboev HackerNoon profile picture
0-item


优化 Web 服务的后端始终旨在提高其性能,其中一个关键方面是加快数据处理速度。此过程包含许多重要的改进,旨在更有效地利用资源并最大限度地缩短系统对请求的响应时间。在本文中,我将分享几种经过验证的技术,可以显着加快您的 Web 服务速度。


需要重点改进什么?

许多程序员在寻求使应用程序更快的过程中,专注于优化代码和算法、选择合适的数据结构和最佳操作。这通常会提高性能,通常会提高优化代码的速度,但效果并不显着。


适度的增长是由于内存操作的固有速度造成的,除非原始代码效率非常低,否则不应期望有显着的改进。然而,某些耗时的操作应该优先进行优化,特别是输入输出操作。


无论是处理文件还是与数据库交互,与内存中操作相比,这些任务的执行时间总是很显着。您无法显着影响从文件读取数据的过程,但使用数据库是在您的直接控制之下。作为开发人员,您拥有显着改进这种交互的所有能力。


让我们探讨以下策略,以提高数据库的使用效率,从而显着提高后端服务的性能


优化查询

如今,很少有后端 Web 服务不利用对象关系映射 (ORM) 系统进行数据库交互。如果您的目标是获得一流的结果,请考虑自定义 ORM。尽管 ORM 高效且无错误,但它们是为一般用途而设计的。这种广泛的适用性往往是以牺牲高性能为代价的。


请记住,ORM 的创建是为了与各种数据库兼容,这可能意味着您会错过为项目选择的数据库的特定优势。例如,如此处所示,利用独特的数据库功能可以将数据库交互的速度显着提高多达 30 倍。


与其仅仅依赖于 ORM 提供的默认查询,不如创建自己的优化查询。自定义查询通常性能更好,特别是在涉及多个联接的场景中。


下面是 Spring JPA 中的一个简单示例,说明如何使用联接查询提高性能:

 @Transactional @Lock(LockModeType.PESSIMISTIC_READ) @Query(value = """ SELECT e FROM EmployeeRecord e LEFT JOIN DepartmentRecord d ON e.departmentId = d.id WHERE e.departmentId = :departmentId; """) List<EmployeeRecord> findEmployeesByDepartmentId(Integer departmentId);


使用扁平类

使用具有嵌套对象和深层层次系统的复杂类可能会导致系统性能的显着损失。通常没有必要在数据库中查询整个嵌套结构,特别是当结构中的所有类未得到充分利用时。


虽然延迟初始化有助于减少对嵌套对象的不必要查询,但当需要嵌套对象但不需要其所有数据时,就会出现挑战。解决这个困境的方法是使用平面数据类。


您应该创建一个类,旨在仅从数据库收集必要的字段数据。然后,通过包含所有必要联接的自定义数据库查询,仅选择那些真正需要的字段。


这种方法不仅可以提高查询速度,还可以减少从数据库到您的服务的数据流量。


例如,使用 Spring JPA 中的 NamedParameterJdbcTemplate,可以创建具有必要字段的平面类:

 public record EmployeeDepartment(Integer employeeId, String employeeName, String departmentName) { }


接下来,使用简单的脚本,仅从主表和连接表中收集必要的字段:

 public List<EmployeeDepartment> employeeDepartments() { return template.query(""" SELECT employees.employee_id, employees.employee_name, departments.department_name FROM employees LEFT JOIN departments ON employees.department_id = departments.department_id; """, new MapSqlParameterSource(), employeeDepartmentMapper); }


这种方法将显着减少负载并使数据处理更加高效。


定义热点数据

处理数据的下一个重要步骤是定义数据类型,主要类型是热数据。


热数据是服务实时处理的数据。无法缓存此数据,因为 Web 服务响应的相关性取决于其即时响应能力。因此,该数据必须始终是最新的。该服务始终与热数据配合使用,不断记录新值并提取信息以便及时更新。


为了尽可能高效地处理热数据,确保存储热数据的表保持尽可能紧凑至关重要。


  • 保留尽可能少的列

    您的表应仅包含主动使用的字段,并将所有其他数据存储在单独的表中,仅保留相关行的 ID。这种方法允许您在需要时访问所有未使用的字段(例如出于报告目的),而不会因为这些数据而使主表负担过重。


  • 保留尽可能少的行

    不要存储不再需要的行。相反,将它们移至存档表。这种方法允许您的查询更快地找到所需的行,同时保留存档中的所有历史数据。通过简单的工作自动执行此过程可以最大限度地减少您对数据归档的参与。


  • 保持索引更新

    记得建立索引。索引对于快速数据搜索至关重要,但经常被程序员忽视。正确的索引可以显着减少数据库的搜索时间和内存消耗。确保为连接中涉及的条件和列构建索引,包括复合索引。


  • 放弃使用外键

    使用外键会给数据库带来额外的负载,需要确保该键存在于关联表中,这会减慢数据操作的速度,尤其是在写入数据时。别误会我的意思;在这样的表中存储外键是可能的,有时甚至是必要的,但最好将键简单地存储为纯值。


这些简单的方法将使您能够最大限度地提高桌子的效率和实用性。


定义温数据

温数据是用于准备响应的数据,尽管其相关性不会产生重大影响。示例包括产品说明或可用配件列表。在存储此类数据时,不再需要密切监视表的大小。但是,重要的是不要忽视在这些表上创建索引,因为它们经常用于连接。


  • 缓存热数据

    温数据的一个关键优势是它的可缓存性。一旦发出请求,就可以将数据存储在内存中,从而减少数据库调用次数并加快计算速度。但是,请记住缓存需要定期更新。


  • 设置合理的TTL(生存时间)

    设置正确的生存时间 (TTL) 以确保正常运行。通常,大约 90 秒的 TTL 就足够了,与用户在网站上做出决定和下订单所需的平均时间一致。请始终根据您的服务要求调整 TTL。


  • 使用较小的类来存储暖数据

    对于缓存,请使用紧凑类。即使进行了完整的查询并收集了表中的所有数据,也要避免将所有内容存储在缓存中。仅存储必要的数据。这种方法显着减少了后端服务的内存消耗。


设置温数据不需要太多时间,最终您将获得切实的成果。


定义冷数据

冷数据是指很少变化但响应所需的数据。此类数据的示例包括商店的名称或地址。该数据很少发生变化,并且对响应的相关性影响最小。


  • 缓存冷数据或将其存储在文件中

    应始终缓存此数据类型。如果由于此类数据较大而无法将其装入内存,请考虑将其从数据库中卸载并以随时可用的格式存储在文件中。将其分为几类并仅选择最常用的将有助于减少内存使用量。此外,与从数据库获取数据相比,这种方法显着提高了速度,因为它消除了通过网络工作的需要。


  • 触发时更新缓存

    此类缓存的生存时间 (TTL) 通常设置为 24 小时。要保持缓存更新,您应该计划一个任务或创建一个触发器来监视此数据的更改并启动缓存更新。例如,如果调用端点来发布或更新冷数据,则应激活触发器来更新缓存。


有效管理冷数据也是优化响应效率、从而提升系统整体性能的重要组成部分。


结论

总之,优化 Web 服务的后端不仅仅取决于代码和算法的优化。增强数据库交互将提高服务的效率和整体性能。实施微调 ORM(对象关系映射)查询、利用平面数据类、准确定义数据类型以及采用缓存策略等技术可以显着提高服务性能。通过这些措施,网络服务最终将实现效率、响应能力的提高和整体功能的增强。


关键步骤

  1. 优化数据库查询并避免仅仅依赖 ORM 实现。
  2. 使用平面类可以减少内存使用并提高响应速度。
  3. 通过将数据类型分类为热、温或冷来定义数据类型。
  4. 采用针对每种定义的数据类型量身定制的特定策略。