本页面简要介绍了 Spanner 超出期限错误:它们是什么、为何发生以及如何进行问题排查和解决。
访问 Spanner API 时,请求可能会因 DEADLINE_EXCEEDED
错误而失败。此错误表示未在配置的超时期限内收到响应。
超出时限错误可能由许多不同的原因导致,例如 Spanner 实例过载、未优化的架构或未优化的查询。本页介绍了发生截止期限已过错误的常见场景,并提供了有关如何调查和解决这些问题的指南。
Spanner 的截止期限和重试哲学
Spanner 的截止期限和重试理念与许多其他系统不同。在 Spanner 中,您应指定超时截止期限,作为响应有效的最长时间。不建议仅为了立即重试同一操作而设置人为较短的截止期限,因为这会导致操作永远无法完成。在这种情况下,不建议采用以下策略和操作;它们适得其反,会破坏 Spanner 的内部重试行为:
设置的截止期限过短。这意味着,该操作无法对偶尔出现的尾端延迟时间增加情况进行弹性处理,并且无法在超时之前完成。请改为设置一个截止期限,即响应最晚可在多长时间内发挥作用。
设置过长的截止期限,并在截止期限到期之前取消操作。这会导致重试,并浪费每次尝试的工作。总体而言,这可能会给您的实例带来大量额外负载。
什么是截止日期已过错误?
当您使用某个 Spanner 客户端库时,底层 gRPC 层会负责通信、封装、解封装和强制执行截止期限。借助截止期限,您的应用可以指定在终止请求并返回“超出截止期限”错误之前,愿意等待请求完成的时长。
超时配置指南演示了如何在每个受支持的 Spanner 客户端库中指定截止期限(或超时)。Spanner 客户端库使用以下配置文件中定义的默认超时和重试政策设置:
- spanner_grpc_service_config.json
- spanner_admin_instance_grpc_service_config.json
- spanner_admin_database_grpc_service_config.json
如需详细了解 gRPC 截止期限,请参阅 gRPC 和截止期限。
如何调查和解决常见的截止期限已过错误
您可能会遇到以下类型的问题的 DEADLINE_EXCEEDED
错误:
Data Access API 问题
必须针对您的特定工作负载正确配置 Spanner 实例,以避免出现数据访问 API 问题。以下部分介绍了如何调查和解决不同的数据访问 API 问题。
检查 Spanner 实例 CPU 负载
当 CPU 利用率超过建议的健康阈值时,请求延迟时间可能会大幅增加。您可以在 Google Cloud 控制台中提供的监控控制台中查看 Spanner 的 CPU 利用率。您还可以根据实例的 CPU 利用率创建提醒。
解决方法
如需了解降低实例 CPU 利用率的步骤,请参阅降低 CPU 利用率。
查看请求的端到端延迟时间明细
当请求从客户端传输到 Spanner 服务器并返回时,需要进行多次网络跳转:从客户端库到 Google Front End (GFE);从 GFE 到 Spanner API 前端;最后从 Spanner API 前端到 Spanner 数据库。如果在上述任一阶段出现网络问题,您可能会看到超出截止期限的错误。
您可以捕获每个阶段的延迟时间。如需了解详情,请参阅 Spanner 请求中的延迟时间点。如需了解 Spanner 中出现延迟的时间点,请参阅确定 Spanner 中出现延迟的时间点。
解决方法
获取延迟时间明细后,您可以使用指标诊断延迟时间,了解延迟时间出现的原因并找到解决方案。
Data API 问题
Spanner 的 Data API 的某些非最佳使用模式可能会导致超出截止期限的错误。本部分提供了有关如何检查这些非最佳使用模式的指南。
检查是否有耗用大量资源的查询
如果尝试在客户端库中运行在配置的超时截止期限内无法执行的高成本查询,可能会导致超出截止期限的错误。一些开销较高的查询示例包括但不限于对大型表执行全表扫描、对多个大型表执行交叉联接,或对非键列使用谓词执行查询(也是全表扫描)。
您可以使用查询统计信息表和事务统计信息表检查耗时较长的查询。这些表会显示运行缓慢的查询和事务的相关信息,例如读取的平均行数、读取的平均字节数、扫描的平均行数等。此外,您还可以生成查询执行计划,以进一步检查查询的执行方式。
解决方法
如需优化查询,请参阅 SQL 查询最佳实践指南。您还可以使用通过前面提到的统计表和执行计划获取的数据来优化查询并对数据库进行架构更改。这些最佳实践有助于缩短语句的执行时间,可能会有助于消除超出截止期限的错误。
检查是否存在锁争用
Spanner 事务需要获取锁才能提交。以高吞吐量运行的应用可能会导致事务争用相同的资源,从而导致获取锁的等待时间增加,并影响整体性能。这可能会导致任何读取或写入请求超出截止期限。
您可以使用锁定统计信息表并参阅以下博文,找出导致读写事务延迟时间过长的原因。在锁定统计信息表中,您可以找到锁定等待时间最长的行键。
此锁冲突问题排查指南介绍了如何查找正在访问锁冲突中涉及的列的事务。您还可以使用“使用事务标记进行问题排查”指南了解哪些事务涉及锁定冲突。
解决方法
请应用以下最佳实践来减少锁争用。此外,对于普通读取用例,请使用只读事务,以避免与写入发生锁定冲突。使用读写事务应仅限于写入或混合读写工作流。按照以下步骤操作应该可以缩短事务执行时间的总延迟时间,并减少超出截止期限的错误。
检查是否有未优化的架构
在为 Spanner 数据库设计最佳数据库架构之前,您应考虑要在数据库中执行的查询类型。运行某些查询时,不太理想的架构可能会导致性能问题。这些性能问题可能会导致请求无法在配置的截止期限内完成。
解决方法
最优的架构设计取决于对数据库进行的读写操作。无论架构具体如何,都应遵循架构设计最佳实践和 SQL 最佳实践指南。遵循这些指南有助于避免最常见的架构设计问题。导致性能不佳的其他一些根本原因包括:主键的选择、表布局(请参阅使用交错表提高访问速度)、架构设计(请参阅为提高性能优化架构),以及 Spanner 实例中配置的节点的性能(请参阅 Spanner 性能概览)。
检查热点
由于 Spanner 是一个分布式数据库,因此架构设计需要考虑到防止热点。例如,创建单调递增列会限制 Spanner 可用于均匀分布工作负载的分块数量。这些瓶颈可能会导致超时。此外,您还可以使用 Key Visualizer 排查热点导致的性能问题。
解决方法
如需解决此问题,请先参阅上一部分中检查未优化的架构中列出的解决方案。重新设计数据库架构,并使用交错索引,以避免可能导致热点的索引。如果按照上述步骤操作未能缓解问题,请参阅“选择主键以避免生成热点”指南。最后,避免采用不太理想的流量模式,例如可能阻止基于负载进行拆分的大量范围读取。
检查是否有配置错误的超时
客户端库为 Spanner 中的所有请求提供了合理的默认超时设置。不过,这些默认配置可能需要根据您的特定工作负载进行调整。不妨观察查询费用并调整截止期限,以适应您的具体用例。
解决方法
超时的默认设置适用于大多数用例。用户可以替换这些配置(请参阅自定义超时和重试指南),但不建议使用比默认超时更短的超时。如果您决定更改超时,请将其设置为应用等待结果的实际时间。您可以尝试配置较长的超时,但切勿将超时设置为短于应用等待的实际时间,因为这会导致该操作的重试频率更高。
Admin API 问题
与 Data API 请求相比,Admin API 请求是一项开销较高的操作。CreateInstance
、CreateDatabase
或 CreateBackups
等管理员请求可能需要几秒钟才能返回响应。Spanner 客户端库为实例和数据库管理员请求设置了 60 分钟的截止期限。这样可以确保服务器有机会在客户端重试或失败之前完成请求。
解决方法
如果您使用 Google Spanner 客户端库访问管理员 API,请确保客户端库已更新并使用最新版本。如果您要通过自己创建的客户端库直接访问 Spanner API,请确保您为实例和数据库管理员请求设置的截止期限不比默认设置(60 分钟)更短。
Google Cloud 控制台问题
从 Google Cloud 控制台 Spanner Studio 页面发出的查询不得超过五分钟。如果您创建的查询运行时间超过 5 分钟,则会看到以下错误消息:
后端会取消失败的查询,并且事务可能会在必要时回滚。
解决方法
您可以使用 SQL 查询最佳实践指南重写该查询。
Dataflow 问题
在 Apache Beam 中,读取操作的默认超时配置为 2 小时,提交操作的默认超时配置为 15 秒。与独立客户端库截止期限超时相比,这些配置允许进行更长时间的操作。不过,如果工作项过大,您可能仍会收到超时和超出截止期限的错误。如果需要,您可以自定义 Apache Beam 提交超时配置。
解决方法
如果在步骤 ReadFromSpanner / Execute
query / Read from Spanner / Read from Partitions
中发生超出截止期限错误,请查看查询统计信息表格,找出扫描了大量行的查询。然后,修改此类查询,以尝试缩短执行时间。
以下异常消息显示了另一个 Dataflow 超出截止期限错误示例:
exception:
org.apache.beam.sdk.util.UserCodeException:
com.google.cloud.spanner.SpannerException: DEADLINE_EXCEEDED:
io.grpc.StatusRuntimeException: DEADLINE_EXCEEDED: deadline exceeded after
3599.999905380s.
[remote_addr=batch-spanner.googleapis.com/172.217.5.234:443] at
org.apache.beam.runners.dataflow.worker.GroupAlsoByWindowsParDoFn$1.output(GroupAlsoByWindowsParDoFn.java:184)
出现此超时是因为工作项过大。在上面的示例中,以下两个建议可能有所帮助。首先,如果随机播放服务尚未启用,您可以尝试启用该服务。其次,您可以尝试调整数据库读取中的配置,例如 maxPartitions
和 partitionSizeBytes
。如需了解详情,请参阅 PartitionOptions
,尝试缩减工作项大小。如需查看实现方法示例,请参阅此 Dataflow 模板。
额外期限已超出问题排查资源
如果您在完成问题排查步骤后仍看到 DEADLINE_EXCEEDED
错误,并且遇到以下情况,请创建支持请求:
- Google Front End 延迟时间较长,但 Spanner API 请求延迟时间较短
- Spanner API 请求延迟时间较长,但查询延迟时间较短
您还可以参阅以下问题排查资源: