副本感知路由 (也称为粘性会话、粘性路由或会话亲和性) 会将相关请求路由到同一个 ClickHouse 副本。当您需要让临时表或命名会话状态在多个查询间保持可用、希望相关查询复用同一副本的本地缓存,或需要在写入及后续读取之间实现写后读一致性时,请使用此功能。
这是一种尽力而为的机制,并不保证隔离性。代理会将每个路由值映射到一个副本。只要副本数量不变,该映射便会保持稳定;服务扩缩容可能会使该值映射到其他副本。
需要 HTTP 接口副本感知路由使用 X-ClickHouse-Replica-Tag 请求头在 HTTP/HTTPS 接口之上的代理层实施。目前无法通过原生协议使用副本感知路由 (原生端口,例如默认使用原生模式的 clickhouse-go 驱动程序) 。原生协议客户端必须切换到 HTTP,并在每个请求中发送路由值。
- 你的服务需要有 2 个或更多副本。如果服务只有单个副本,就没有可固定到的副本。
- 该功能在进入 GA 后,Enterprise 默认可用。
- 此功能适用于标准 ClickHouse Cloud 服务。BYOC 暂不支持。
提交一个 support 工单,申请启用基于 HTTP 的粘性副本路由。请附上你的 service ID 以及需要启用它的原因 (临时表、会话状态、缓存复用或写后读一致性) 。无需重启。
要将工作负载固定到某个副本,请在 HTTPS 接口中发送 X-ClickHouse-Replica-Tag 请求头。代理会根据请求头的值进行一致性哈希,因此只要副本数量不变,具有相同请求头值的请求就会被路由到同一副本。不同的值会独立进行哈希,可能会落到相同或不同的副本,但您无法指定某个值映射到哪个副本。
使用现有服务的主机名即可,无需使用特殊的粘性主机名或更改 DNS。请求头的值可以是您选择的任意字符串,例如应用程序名称、用户 ID 或工作负载标签。不带该请求头的请求仍会使用常规负载均衡。
在每个请求中设置 X-ClickHouse-Replica-Tag 请求头:
对于 clickhouse-go (v2),设置 Protocol: clickhouse.HTTP,并通过 HttpHeaders 连接选项传入请求头。
X-ClickHouse-Replica-Tag 无需创建 ClickHouse HTTP 会话即可实现副本亲和性。并发请求可复用同一标签,不会触发 SESSION_IS_LOCKED。
在多副本服务中,在某个副本上写入的数据可能要等复制追赶完成后,其他副本才能看到。发送写入请求时添加 X-ClickHouse-Replica-Tag 请求头,然后在后续读取中复用相同的请求头值。代理会将两者路由到同一副本,因此即使其他副本仍未追赶上,您也能读到自己写入的数据。此模式适用于写入后立即读取相同数据的工作负载,例如交互式应用程序,或在继续执行前验证插入操作的 ETL 作业。
如需在所有副本之间获得更强的一致性保证,还可以在 ClickHouse Cloud 上将 select_sequential_consistency 设置为 1。
使用相同的 X-ClickHouse-Replica-Tag 值再次运行 SELECT hostName() 示例。只要副本数量不变,您应会获得相同的主机名。不同的请求头值可能会映射到不同的副本。
横向扩容或缩容会改变路由哈希环。共享同一路由值的请求可能会被路由到不同的副本。如果你依赖临时表或会话级设置,请准备在重新映射后重新创建它们。
粘性路由只决定请求由哪个副本来处理,但该副本仍可能同时承载其他流量。若需专用计算资源,请使用计算资源分离。
基于 HTTP 的路由在常规服务主机名上可与私有网络连接配合使用,无需额外添加 DNS 记录。
粘性路由基于 X-ClickHouse-Replica-Tag HTTP 请求头。原生二进制协议不携带这类可供 HTTP 代理计算哈希的值,因此原生协议无法使用副本感知路由。原生协议客户端若要使用此功能,必须将相关工作负载迁移到 HTTP 接口。
使用相同路由值的查询仍被路由到不同副本
- 确认每个请求均包含
X-ClickHouse-Replica-Tag 请求头。
- 确认每个请求使用的路由值完全一致。
- 启用后请稍候片刻,通常不到一分钟即可生效。
- 检查副本数量近期是否发生变化;扩缩容后发生重新映射属于预期行为。使用
SELECT hostName() 查找新的映射关系。