尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ScyllaDB 反熵机制全解:Hinted Handoff、Read Repair 与 Repair 如何保证数据最终一致

ScyllaDB 反熵机制全解:Hinted Handoff、Read Repair 与 Repair 如何保证数据最终一致 ScyllaDB 反熵机制全解Hinted Handoff、Read Repair 与 Repair 如何保证数据最终一致【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladbScyllaDB 是一套基于 Seastar 框架的 NoSQL 数据存储兼容 Apache Cassandra 与 Amazon DynamoDB。在副本架构下节点宕机、网络分区、写入超时等原因会让同一份数据的多个副本逐渐产生偏差本文围绕仓库中的 反熵Anti-Entropy架构文档系统讲解 ScyllaDB 为对抗数据熵而设计的三大机制——写路径上的Hinted Handoff提示移交、读路径上的Read Repair读修复以及周期性运维的Repair修复。读完本文你将掌握这三类机制的触发条件、完整工作流程、核心配置参数与 REST API 实操方法并了解它们在源码层的实现依据。什么是反熵Anti-EntropyScyllaDB 按最终一致性模型复制数据。从 CAP 定理的角度看ScyllaDB 把可用性Availability与分区容忍性Partition Tolerance置于一致性Consistency之上同时ScyllaDB 提供可调一致性tunable consistency允许用户通过每个查询的一致性级别Consistency Level, CL在可用性与一致性之间做权衡。然而随着时间推移多种原因会造成数据不一致数据熵节点宕机a down node网络分区a network partition写入丢失dropped mutations进程在刷盘flush之前崩溃process crashes before a flush副本因资源耗尽无法写入a replica that cannot write due to being out of resources文件损坏file corruption。为了消除数据熵ScyllaDB 借鉴 Apache Cassandra 的思路设计了反熵机制其目标是在所有副本之间比较数据、同步数据并最终确保每个副本都持有最新数据。反熵措施按发生时机分为三类写路径Hinted Handoff提示移交见 hinted-handoff 文档读路径Read Repair读修复见 read-repair 文档周期性运维Repair修复见 repair 运维文档。Hinted Handoff写路径上的反熵机制为什么需要 Hinted HandoffScyllaDB 的正常写入流程遵循故障容错Fault Tolerance文档中描述的场景。但当写入请求被发送到一个无响应的节点原因包括节点写入负载过重、网络问题甚至硬件故障时为了保证可用性与一致性ScyllaDB 实现了hinted handoff提示移交。其核心定义可以概括为一个公式Hint提示 目标副本 ID 变更数据Mutation也就是说ScyllaDB 会为发往宕机节点的写入保存一份“提示”副本等该节点恢复上线后再把这份写入重放给它。宕机场景下的写入流程当某个节点宕机时一次写入的完整过程如下协调节点coordinator确定所有副本节点基于复制因子Replication Factor, RF协调节点尝试向 RF 个副本节点写入写入流程参见故障容错文档如果其中一个节点宕机则只有两个节点返回确认ack如果一致性级别不要求所有副本都响应协调节点 V 就会向客户端返回写入成功同时为缺失的节点写下一份 hint 并存储宕机节点恢复上线后协调节点重放该节点的 hint在收到写入确认后删除该 hint。hint 的生成条件协调节点在以下条件下为某个目标存储 hint目标节点宕机down目标副本未在write_request_timeout_in_ms内响应。同时如果目标节点的宕机时间超过max_hint_window_in_ms协调节点将停止为该节点生成新的 hint一旦目标节点恢复hint 生成自动恢复。从源码看db/hints/manager.cc中的can_hint_for()会通过local_gossiper().get_endpoint_downtime(ep) _max_hint_window_us判断目标节点宕机时长是否仍在窗口内超窗则直接返回 false 拒绝生成 hint见 db/hints/manager.cc_max_hint_window_us由构造参数max_hint_window_ms * 1000换算而来见 db/hints/manager.cc。scylla.yaml 中的配置项Hinted handoff 由scylla.yaml中的以下配置控制默认值见 conf/scylla.yaml配置项作用默认值hinted_handoff_enabled完全启用/禁用 hinted handoff或按数据中心白名单枚举允许 hint 的 DC如DC1,DC2true向所有节点允许 hintmax_hint_window_in_ms目标节点宕机超过该毫秒数后不再为其生成 hint节点恢复后恢复生成108000003 小时hints_directoryhint 文件的存储目录$SCYLLA_HOME/hints示例注释为/var/lib/scylla/hints配置文件中还提供了相关的view_hints_directory物化视图更新 hint 的存储目录默认/var/lib/scylla/view_hints。从源码看db/hints/manager会在每个 shard 上维护独立的 hint 子目录构造时_hints_dir fs::path(hints_directory) / fmt::to_string(this_shard_id())见 db/hints/manager.cc启动时会创建并校验 hint 目录make()必要时还会调用rebalance_hints()对多 shard 间的 hint 进行重新均衡见 db/hints/manager.cc。提示也可能丢失为什么 hint 不能替代 repair需要特别强调的是hint 的存储本身也可能失败。因此启用 hinted handoff 并不能消除对 repair 的需求——用户仍然需要定期执行全量 repair才能确保集群各节点间的数据一致。Hinted handoff 只能缓解短时间宕机场景无法覆盖 hint 丢失、长时间停机或文件损坏等场景。Sync Point HTTP API等待 hint 重放完成ScyllaDB 提供了一种方式让用户可以等待指定节点的 hint 被全部重放这就是sync point同步点机制。同步点对应该节点上截至创建时刻累积的全部 hint同时覆盖普通 mutation hint 与物化视图更新的 hint。API 地址为http://{API_ADDRESS}:{API_PORT}/hinted_handoff/sync_point/其中{API_ADDRESS}对应协调节点即 hint 发送方的 API IP 地址。创建同步点POST向/hinted_handoff/sync_point发送 POST 请求即可创建同步点参数如下target_hosts同步点要覆盖的节点 IP 列表多个 IP 用逗号分隔例如127.0.0.2,127.0.0.3可选参数——不指定时ScyllaDB 视为未指定任何 IP即同步点面向集群中所有节点。成功后返回一个 JSON 字符串内容为创建的同步点 ID出错时返回报告问题的 JSON 对象。# 为 IP 为 127.0.0.2 与 127.0.0.3 的节点创建同步点 $ curl -X POST http://127.0.0.1:10000/hinted_handoff/sync_point?target_hosts127.0.0.2,127.0.0.3 Ay4AAADgR8IYRSM14vPuN232DLKSAQAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAA/CncIC5VDTA # 为所有节点创建同步点target_hosts 参数为空 $ curl -X POST http://127.0.0.1:10000/hinted_handoff/sync_point Ay4AAADgR8IYRSM14vPuN232DLKSAQAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAA/CncIC5VDTA # 非法请求无法解析的 host $ curl -X POST http://127.0.0.1:10000/hinted_handoff/sync_point?target_hostsinvalid_host {message: Failed to parse host address invalid_host: invalid_host, code: 400}等待同步点GET向/hinted_handoff/sync_point发送 GET 请求可等待之前创建的同步点参数如下id要等待的同步点 ID必填参数一次只能提供一个timeout整数表示 ScyllaDB 最多等待多少秒让对应 hint 发送完成若为负数则无限期等待可选参数——不提供时立即返回当前状态。数据库返回一个 JSON 字符串取值有两种DONE同步点对应的所有 hint 均已发送完毕IN_PROGRESS仍有部分 hint 尚未发送。出错时返回报告问题的 JSON 对象。# 同时提供 id 与 timeout 参数等待同步点 $ curl -X GET http://127.0.0.1:10000/hinted_handoff/sync_point?idAy4AAADgR8IYRSM14vPuN232DLKSAQAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAA/CncIC5VDTAtimeout2 DONE # 不提供可选参数 timeout等价于 timeout0立即查询状态 $ curl -X GET http://127.0.0.1:10000/hinted_handoff/sync_point?idAy4AAADgR8IYRSM14vPuN232DLKSAQAMAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAA/CncIC5VDTA DONE # 非法请求缺少必填参数 id $ curl -X GET http://127.0.0.1:10000/hinted_handoff/sync_point?timeout-1 {message: Missing mandatory parameter id, code: 400}注意如果在等待同步点时该节点恰好关机你会收到一个错误响应。待节点重新开机后应再次尝试等待该同步点。同步点的源码实现从源码看sync point 机制由 db/hints/sync_point.cc 实现同步点以 Base64 编码的二进制 blob 表示支持 V1/V2/V3 三种编码格式。V3 格式包含uint8_t版本号 经 IDL 序列化的sync_point_v3结构 uint64_txxHash 校验和见 db/hints/sync_point.cc。校验和用于防篡改——测试 test/rest_api/test_hinted_handoff.py 会逐字节修改同步点后发送 GET 请求验证损坏的同步点会被拒绝。sync_point_v3结构记录创建者host_id、shard_count以及针对每个目标 endpoint 在每个 shard 上的 hint 队列 replay position重放位置分别覆盖普通 hint 队列regular_sp与物化视图 hint 队列mv_sp。HTTP 层实现在 api/hinted_handoff.ccPOST 处理函数解析target_hosts参数调用gms::inet_address解析并映射为host_id解析失败抛出 400 错误随后调用proxy.local().create_hint_sync_point()创建同步点并返回其编码见 api/hinted_handoff.ccGET 处理函数解码id参数按timeout计算 deadline负数表示无限等待空串表示不等待立即返回调用wait_for_hint_sync_point()超时则返回IN_PROGRESS否则返回DONE见 api/hinted_handoff.cc。API 的 OpenAPI 描述见 api/api-doc/hinted_handoff.json接口文档见 hinted-handoff API 参考。Read Repair读路径上的反熵机制触发条件与运行模式Read repair 是读路径上的反熵机制在读取操作中ScyllaDB 会运行一个称为read repair的过程确保各副本被更新为最新数据。这种修复自动、异步地在后台运行。但需要注意如果在达到一致性级别之前就检测到 digest摘要不匹配该修复会转为前台foreground执行。正常的读取流程同样遵循故障容错文档。读请求阶段先请求 digest下图展示了数据不同步、后台 read repair 被触发的读取流程协调节点为 VRF3CLQUORUM协调节点 V向一个节点W已过期请求数据含 digest协调节点同时向最多与一致性级别数量相当的节点请求 digest本例中为 Quorum即 2 个节点包含节点 X如果所有副本的 digest 一致协调节点直接把读取的数据返回给客户端如果出现不匹配如上图所示则执行 read repair。从源码看digest 请求与数据请求分别对应不同的 RPC verbREAD_DIGEST与READ_DATA其中send_read_digest()通过ser::storage_proxy_rpc_verbs::send_read_digest()发送见 service/storage_proxy.ccScyllaDB 默认使用 xxHash 摘要算法见 service/storage_proxy.cc。读修复阶段全量数据请求与写回触发副本返回的 digest 不匹配见上节后协调节点 V向参与本次读取的同一批副本数量达到一致性级别发送全量数据请求对账Reconciliation协调节点 V 比较收到的全量数据集向过期的节点发送更新返回结果所有被更新的副本成功响应后协调节点将合并后的数据集返回给客户端附录中的完整时序图包含 digest 匹配与不匹配两条分支的详细交互如下值得注意的是源码中写回过期副本的更新本质上是一次内部写入storage proxy 的写入路径会为每个目标副本分别构造对应的 mutation源码注释明确提到 different mutation for each destination (for read repairs)见 service/storage_proxy.cc并按各副本的一致性要求统计确认数量_total_block_for db::block_for(...) pending_endpoints见 service/storage_proxy.cc。Repair周期性运维修复Hinted handoff 与 read repair 只能在写入或读取发生时顺带修复数据无法覆盖 hint 丢失、长时间宕机等场景因此 ScyllaDB 提供了repair作为周期性后台进程主动在节点之间同步数据确保所有副本持有相同数据详见 repair 运维文档。触发方式与频率建议可以手动执行nodetool repair或nodetool cluster repair命令对于同时存在 tablets 与 vnodes keyspace 的集群需要在集群每个节点上运行nodetool repair -pr并在任意一个节点上运行nodetool cluster repair建议定期执行如果删除数据频繁修复间隔应小于gc_grace_seconds默认 10 天例如每周执行一次在各节点上顺序执行nodetool repair -pr大多数情况下不同步的数据比例很小但若节点宕机一天以上差异可能变得显著更需按时修复。Row-level Repair行级修复ScyllaDB 采用行级修复row-level repair其优势体现在两方面最小化数据传输ScyllaDB 为每一行计算校验和并使用集合对账set reconciliation算法找出节点间的差异行只交换不一致的行消除网络上无谓的数据传输最小化磁盘读取数据只读取一次、保存在临时缓冲区中并利用缓存数据计算校验和并发送给副本。行级修复的源码实现位于 repair/row_level.cc 及其头文件 repair/row_level.hh相关的行哈希与同步边界定义见 repair/hash.hh 与 repair/sync_boundary.hh。Incremental Repair 与 Automatic RepairIncremental Repair增量修复基于行级修复与 Tablets 架构构建支持频繁、快速的修复详见 增量修复特性文档Automatic Repair自动修复基于增量修复构建将修复的调度与执行直接内置于 ScyllaDB无需外部进程参与详见 自动修复特性文档。三类反熵机制的协作与适用场景机制发生时机触发条件覆盖范围局限Hinted Handoff写路径目标副本宕机或未在write_request_timeout_in_ms内响应短时间宕机期间累积的写入hint 存储本身可能失败宕机超过max_hint_window_in_ms后不再生成 hintRead Repair读路径读取时副本 digest 不匹配被读取到的、不同步的数据只修复被读取的数据未被读取的数据不会被动修复Repair周期性运维手动nodetool repair/nodetool cluster repair或自动/增量修复全量数据行级修复按行对账需要按gc_grace_seconds周期执行属于后台维护任务总结ScyllaDB 的反熵体系由三部分组成写入时的Hinted Handoff让协调节点为宕机副本暂存写入并在其恢复后重放由hinted_handoff_enabled、max_hint_window_in_ms、hints_directory等 scylla.yaml 配置 控制并提供 sync point HTTP API 供外部等待重放完成读取时的Read Repair通过 digest 比对发现不一致数据并异步或在达到一致性级别前即检测到不匹配时前台修复副本周期性的Repair则以行级对账方式主动同步全量数据。三者共同作用让 ScyllaDB 在保持高可用性的同时持续将集群收敛到数据一致状态。深入源码可继续阅读 db/hints/manager.cc、db/hints/sync_point.cc、api/hinted_handoff.cc、service/storage_proxy.cc 与 repair/row_level.cc。【免费下载链接】scylladbNoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB项目地址: https://gitcode.com/GitHub_Trending/sc/scylladb创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表