本页介绍了 Spanner 中的主要区域感知路由,以及如何使用它。Spanner 使用主要区域感知路由在双区域和多区域实例配置中动态路由读写事务,以缩短延迟时间并提高数据库的性能。默认情况下,主要区域感知路由处于启用状态。
适用于读写事务的 Spanner 路由
Spanner 会复制数据,以提供额外的数据可用性和地理局部性。在 Spanner 双区域和多区域实例配置中,双区域和多区域实例配置中的某个区域会被指定为主要区域,其中包含数据库的主要副本。当您使用双区域或多区域实例配置,并且客户端从非主要区域向数据库发出读写事务时,写入操作始终在主要区域中处理,然后发回非主要区域。因此,从非主要区域提交的读写事务需要多次往返主要副本才能成功提交。
主要区域感知路由是一种机制,可通过智能地路由读写事务来缩短读写事务的延迟时间。如果已启用主要区域感知路由,即使写入操作不是从主要区域发起的,会话创建请求也会路由到主要区域,以便将 Spanner API 前端与主要区域保持一致。此路由机制可以将非主要区域(客户端应用所在区域)与主要区域之间所需的网络往返次数减少到两次,从而缩短读写事务的延迟时间。
图 1. 已启用主要区域感知路由的 Spanner 路由的示例。
如果已停用主要区域感知路由,客户端应用会先将请求路由到客户端应用区域(非主要区域)中的 Spanner API 前端服务。然后,从客户端应用区域的 Spanner API 前端,向主要区域的 Spanner 服务器 (SpanServer) 进行三次或更多往返,以提交写入操作,从而增加延迟时间。系统需要这些额外的往返过程来支持二级索引、限制条件检查,以及读取您写入的内容。
图 2. 已停用主要区域感知路由的 Spanner 路由的示例。
使用场景
由于使用了主要区域感知路由,以下用例可从较低的延迟中受益:
- 批量更新:执行 Dataflow 导入或运行来自非主要区域的后台更改(例如批量 DML)。
- 灾难容错和提高可用性:在主要区域和非主要区域部署客户端应用,以便在从非主要区域发起写入操作时容忍区域级服务中断。
- 全球应用:在提交数据的全球广泛区域位置部署客户端应用。
限制
如果您的客户端应用部署在主要区域之外,并且您在未读取数据的情况下写入值(“盲写”),那么如果启用了主要区域感知路由,您可能会观察到延迟时间回归现象。这是因为,启用主要区域感知路由后,在非主要区域中的客户端应用与主要区域中的 Spanner API 前端之间会存在两次区域间往返(beginTransaction
和 commit
请求)。但是,在停用主要区域感知路由的情况下,不包含读取的写入操作只需要为 commit
请求进行一次跨区域往返(beginTransaction
在本地 Spanner API 前端进行处理)。例如,如果您将文件数据批量加载到新创建的表中,那么事务不太可能从该表中读取数据。如果您经常在应用中提交写入操作而无需读取,则可以考虑停用主要区域感知路由。如需了解详情,请参阅停用主要区域感知路由。
使用主要区域感知路由
默认情况下,Spanner 客户端库中启用了主要区域感知路由。
我们建议您在启用主要区域感知路由的情况下处理读写请求。您可以停用该功能,以比较性能差异。
启用主要区域感知路由
您可以使用 Spanner 客户端库手动启用主要区域感知路由。
C++
使用 RouteToLeaderOption
结构配置客户端应用,并启用主要区域感知路由:
void RouteToLeaderOption(std::string const& project_id, std::string const& instance_id,
std::string const& database_id) {
namespace spanner = ::google::cloud::spanner;
// Create a client with RouteToLeaderOption enabled.
auto client = spanner::Client(
spanner::MakeConnection(
spanner::Database(project_id, instance_id, database_id)),
google::cloud::Options{}.set<spanner::RouteToLeaderOption>(
spanner::true));
C#
使用 EnableLeaderRouting
配置客户端应用,并启用主要区域感知路由:
// Create a client with leader-aware routing enabled.
SpannerConnectionStringBuilder builder = new
SpannerConnectionStringBuilder();
Builder.EnableLeaderRouting = true;
Go
使用 ClientConfig
配置客户端应用,并启用主要区域感知路由:
type ClientConfig struct {
// DisableRouteToLeader specifies if all the requests of type read-write
// and PDML need to be routed to the leader region.
// Default: false
DisableRouteToLeader false
}
Java
使用 SpannerOptions.Builder
配置客户端应用,并启用主要区域感知路由:
SpannerOptions options = SpannerOptions.newBuilder().enableLeaderAwareRouting.build();
Spanner spanner = options.getService();
String instance = "my-instance";
String database = "my-database";
Node.js
使用 SpannerOptions
配置客户端应用,并启用主要区域感知路由:
// Instantiates a client with routeToLeaderEnabled enabled
const spanner = new Spanner({
projectId: projectId,
routeToLeaderEnabled: true;
});
PHP
使用 routeToLeader
配置客户端应用,并启用主要区域感知路由:
// Instantiates a client with leader-aware routing enabled
use Google\Cloud\Spanner\SpannerClient;
$routeToLeader = true;
$spanner = new SpannerClient($routeToLeader);
Python
使用 route_to_leader_enabled
配置客户端应用,并启用主要区域感知路由:
spanner_client = spanner.Client(
route_to_leader_enabled=true
)
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
Ruby
使用 self.new
配置客户端应用,并启用主要区域感知路由:
def self.new(project_id: nil, credentials: nil, scope: nil, timeout: nil,
endpoint: nil, project: nil, keyfile: nil, emulator_host: nil,
lib_name: nil, lib_version: nil, enable_leader_aware_routing: true) ->
Google::Cloud::Spanner::Project
停用主要区域感知路由
您可以使用 Spanner 客户端库来停用主要区域感知路由。
C++
使用 RouteToLeaderOption
结构配置客户端应用,并停用主要区域感知路由:
void RouteToLeaderOption(std::string const& project_id, std::string const& instance_id,
std::string const& database_id) {
namespace spanner = ::google::cloud::spanner;
// Create a client with RouteToLeaderOption disabled.
auto client = spanner::Client(
spanner::MakeConnection(
spanner::Database(project_id, instance_id, database_id)),
google::cloud::Options{}.set<spanner::RouteToLeaderOption>(
spanner::false));
C#
使用 EnableLeaderRouting
配置客户端应用,并停用主要区域感知路由:
// Create a client with leader-aware routing disabled.
SpannerConnectionStringBuilder builder = new
SpannerConnectionStringBuilder();
Builder.EnableLeaderRouting = false;
Go
使用 ClientConfig
配置客户端应用,并停用主要区域感知路由:
type ClientConfig struct {
// DisableRouteToLeader specifies if all the requests of type read-write
// and PDML need to be routed to the leader region.
// Default: false
DisableRouteToLeader true
}
Java
使用 SpannerOptions.Builder
创建与已停用主要区域感知路由的 Spanner 数据库的连接:
SpannerOptions options = SpannerOptions.newBuilder().disableLeaderAwareRouting.build();
Spanner spanner = options.getService();
String instance = "my-instance";
String database = "my-database";
Node.js
使用 SpannerOptions
配置客户端应用,并停用主要区域感知路由:
// Instantiates a client with routeToLeaderEnabled disabled
const spanner = new Spanner({
projectId: projectId,
routeToLeaderEnabled: false;
});
PHP
使用 routeToLeader
配置客户端应用,并停用主要区域感知路由:
// Instantiates a client with leader-aware routing disabled
use Google\Cloud\Spanner\SpannerClient;
$routeToLeader = false;
$spanner = new SpannerClient($routeToLeader);
Python
使用 route_to_leader_enabled
配置客户端应用,并停用主要区域感知路由:
spanner_client = spanner.Client(
route_to_leader_enabled=false
)
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
Ruby
使用 self.new
配置客户端应用,并停用主要区域感知路由:
def self.new(project_id: nil, credentials: nil, scope: nil, timeout: nil,
endpoint: nil, project: nil, keyfile: nil, emulator_host: nil,
lib_name: nil, lib_version: nil, enable_leader_aware_routing: false) ->
Google::Cloud::Spanner::Project
后续步骤
- 了解单区域、双区域和多区域配置。
- 了解复制。
- 了解如何修改数据库的主要区域。