DAOS系统架构-RDB

发布于:2025-07-20 ⋅ 阅读:(19) ⋅ 点赞:(0)

1. 概述

基于Raft共识算法和强大的领导地位策略,pool service和container service可以通过复制其内部的元数据来实现高可用。通过这种方法实现具有副本能力的服务可以容忍少数副本中的任何一个出现故障。通过将每个服务的副本分布在容灾域中,pool service和container service可以容忍合理数量的targets出现故障。

 
 

2. 架构

一个复制服务(replicated service)是基于Raft复制日志( replicated log)构建的。该服务将RPCs转换成状态查询和确定性状态更新操作。在被应用于任何一个服务副本之前,所有状态的更新操作首先提交到副本日志中。由于Raft保证了日志副本之间的一致性,因此服务副本最终以相同的顺序应用相同的更新状态集,并经历完全相同的状态历史。

在一个复制服务的所有副本当中,只有当前领导者可以处理服务RPCs。一个服务的领导者就是当前Raft的领导者(即此刻任期数最高的)非领导者拒绝所有的服务RPCs,并尽其所知的将客户端请求重定向当前领导。客户端会缓存副本服务的地址以及当前的领导者。有时,客户端可能不会获得任何有意义的重定向提示,并且可以通过与随机的一个副本通信来找到当前领导者。
service_replication_modules
上图展示了构成一个服务副本的相关模块。service模块通过将RPCs转换成状态查询和确定性状态更新操作来处理RPCs。Raft模块通过与其他副本上的Raft模块通信,按照Raft协议来实现复制的日志。Raft模块为service模块执行状态查询和状态更新提供了方法。Storage模块(本例中是持久化内存和文件系统)用于存储service以及Raft状态。它使用VOS以原子方式更新存储在持久化内存中的状态。

 
 

3. RPC处理

当RPC请求到达领导者服务时,service模块的服务线程会接收该请求,并通过执行专门为此类型请求设计的句柄函数(handler function)来处理该请求。就副本服务而言,一个句柄包括:状态查询(比如读取存储池属性)、状态更新(比如写入一个新版本的pool map)、以及到其他服务的RPCs(比如发送请求到其他target服务)。一些句柄只涉及到查询,一些句柄会涉及到更新和查询,另外一些会涉及以上三种。很少见一种情况是,如果有的话,句柄只涉及到更新而不执行查询。

句柄必须将所有的更新操作组合到单个日志条目中,然后提交日志条目,并在将更新操作应用于服务状态之前要等待该日志条目成为可适应的。为每一个更新操作的RPC使用单个日志条目很容易使得每个更新操作的RPC在领导者服务出现崩溃或者领导者地位改变时具有原子性。如果在未来引入的RPCS不满足这些要求,则需要额外事务回复机制。领导者服务的状态始终表示该领导者到目前位置处理的所有已完成的更新操作的RPC的效果。

另一方面,查询操作可以直接从服务的状态读取,而无需通过复制的日志。然而,为了确保一个请求可以看到所有已经处理过的RPC的效果,该句柄必须询问Raft模块领导地位是否有变动。如果没有,那么到目前位置,针对该请求的所有查询都不是过时的。如果领导者失去了其领导地位,那么句柄会终止请求,并将客户端请求重定向到新的领导者。

针对到其他服务的RPCs这种情况,如果这些请求更新了目标服务的状态,则必须是等幂的。当领导地位发生变化时,如果客户端重新发送了服务端请求,那么新的领导者可能也要重新向其他服务发送RPCs。

句柄需要处理合理的并发执行操作。通常,在领导者服务上使用本地锁可以使RPC的执行线性化。一旦领导者地位发生变化,旧的领导者不再执行任何更新操作,这将导致所有的RPCs执行被终止。因此,新领导者上的RPCs与留在旧领导者上的RPCs的并不冲突。因此,不需要锁作为服务状态的一部分进行复制。


网站公告

今日签到

点亮在社区的每一天
去签到