Grain 目录实现
概述和体系结构
Orleans 中的 grain 目录是一个键值存储,其中键是 grain 标识符,值是一个注册条目,指向(可能)承载 grain 的活动 silo。
虽然 Orleans 提供默认的内存中分布式目录实现(如本文所述),但 grain 目录系统设计为可插式。 开发人员可以通过实现 IGrainDirectory
接口,并将其注册到 silo 的服务集合,来实现他们自己的目录。 这允许使用不同存储后端或一致性模型的自定义目录实现,以便更好地满足特定的应用程序要求。 由于引入了新的强一致性目录,因此无需外部目录实现,但 API 仍保持向后兼容性和灵活性。 可以根据每种颗粒类型配置颗粒目录。
为了优化性能,目录查询被在每个孤岛中本地缓存。 这意味着,仅当本地缓存条目缺失或无效时,才需要潜在的远程目录读取。 此缓存机制可减少与粒度位置查找关联的网络开销和延迟。
最初,Orleans 实现了一个最终一致的目录,该目录的结构为分布式哈希表。 这被 Orleans v9.0 中的强一致目录取代,该目录基于两相 虚拟同步方法,并且结构化为分布式哈希表,但通过使用虚拟节点改进了负载均衡。 本文介绍后一种较新的粒度目录实现。
分布式谷物目录
Orleans 内的分布式粒目录提供很强的一致性、负载均衡、高性能和容错能力。 实现遵循基于 虚拟同步方法的两阶段设计, 与垂直 Paxos 相似。
目录分区有两种操作模式:
- 正常操作:分区在本地处理请求,而无需与其他主机协调。
- 查看更改:主机之间相互协调,以转移目录范围的所有权。
该目录利用 Orleans的强一致性集群成员系统,其中被称为“视图”的配置具有单调递增的版本号。 随着 silo 加入和离开群集,会创建连续视图,从而导致范围所有权的更改。
所有目录操作包括视图协调:
- 请求包含调用方的视图编号。
- 响应中包含分区的视图编号。
- 视图编号不匹配会触发同步。
- 在视图更改时,系统会自动重试请求。
这可确保所有请求都由目录分区的正确所有者处理。
分区策略
使用一致哈希值圆环对目录进行分区,并将范围分配给群集中的活动 silo。 对 grain 标识符进行哈希运算,以找到拥有与其哈希值对应的圆环部分的 silo。
每个活动 silo 都拥有预先配置的范围数量,默认为每个 silo 30 个范围。 这类似于 Amazon Dynamo 和 Apache Cassandra所使用的方案,其中为每个节点(主机)创建了多个“虚拟节点”(范围)。
分区的大小取决于分区的哈希与下一个分区的哈希之间的距离。 在视图更改期间,范围可以在多个孤岛之间拆分,这会增加视图更改过程的复杂性,因为每个分区必须与多个其他分区进行协调。
查看更改过程
目录分区(在 GrainDirectoryPartition
中实现)使用版本化范围锁,以防止在视图更改期间对范围进行无效访问。 范围锁是在视图更改期间创建的,并在视图更改完成后释放。 这些锁类似于虚拟同步方法中使用的“楔子”。
发生视图更改时,分区可以增长或收缩:
- 如果一个新的节点加入群集,那么现有分区可能会缩小以腾出空间。
- 如果 silo 已离开群集,则剩余分区可能会增长以接管孤立范围。
必须先将目录注册从旧所有者转移到新所有者,然后才能提供请求。 传输过程遵循以下步骤:
- 先前的所有者封闭了范围,并创建了其目录条目的快照。
- 新所有者请求并应用快照。
- 新所有者开始为范围的请求提供服务。
- 之前的所有者收到通知并删除快照。
恢复过程
当主机崩溃而不正确移交其目录分区时,后续分区所有者必须执行恢复。 这涉及:
- 查询群集中所有活动 silo 的 grain 注册信息。
- 重新生成受影响范围的目录状态。
- 确保没有重复的 grain 激活发生。
当群集成员身份发生快速更改时,也需要恢复。 虽然群集成员身份保证了单调性,但 silo 可能会错过中间成员身份视图。 在这种情况下:
- 快照传输已被放弃。
- 执行恢复,而不是正常的分区到分区切换。
- 尽管缺少中间状态,但系统仍保持一致性。
未来对群集成员身份的改进可能会通过确保所有 silo 都能看到所有视图来减少或消除这些情况。