文章目录
Introduction
FaRM可以在提供ACID分布式事务的情况下保证strict serializability,high availability,high throughput,low latency。
FaRM实现以上保证基于的是两个硬件趋势:
- 快速的RDMA
- 非易失性DRAM(通过写入SSD实现)
这些减少了存储和网络的瓶颈,但暴露CPU瓶颈,因此FaRM协议使用下面3个方法降低CPU瓶颈:
- 减少消息数量
- 使用单边的RDMA进行读写,而不使用消息
- 高效利用并行化
FaRM可以支持事务和数据跨越多个机器,其基本设计原则如下:
- 它不使用Paxos,而使用vertical Paxos减少消息传输数量
- 使用primary-backup replication,coordinator不进行备份并可以直接与primaries和backups通信。
- 使用4PC协议(lock, validation, commit backup, commit primary) + 乐观锁进行并发控制。
FaRM使用了RDMA网络进行消息传递,无需CPU的参与,因此传统的基于CPU的failure recovery失效,需要确定新的failure recovery protocol:
- precise membership:
- FaRM servers不能根据租约过期而拒绝请求,因为这个判断需要CPU参与,现在请求直接通过网卡处理,CPU无法干预。
- 使用precise membership保证所有节点同意当前的成员配置,并只向已有成员发送单边RDMA操作。
- reservations:
- FaRM不能再依赖于传统的2PC协议中,prepare阶段需要participants对资源进行锁定,然后在commit阶段进行提交,因为此时servers写logs的时候不再经过CPU了。
- 使用reservation保证在事务提交之前,所有需要提交的记录都有足够的日志空间用于提交和截断
FaRM实现了非常快速的并行failure recovery protocol:
- 快速故障检测可通过fast network来交换高频率的心跳包实现,并且使用priorities以及pre-allocation来避免误报
- 快速恢复:
- 受到failure影响的事务,只需要等待lock recovery阶段结束即可访问数据,时间是毫秒级的
- 没有受到failure影响的事务,可以继续无阻塞运行
Hardware trends
Non-volatile DRAM
使用分布式不中断电源供应系统(Distributed UPS)保证数据不丢失,当外部电源损坏时,该系统利用电池中的电力,将数据保存到SSD中。
RDMA networking
FaRM使用单边的RDMA操作,可以不使用远程节点的CPU。相比RPC,不仅节省CPU时间,还节省了消息传输数量(因为RPC,尤其是基于可靠通信的RPC需要应答)。
Programming model and architecture
FaRM提供集群全局的地址空间,所有的应用访问这个全局的地址空间。应用可以通过FaRM API接口透明化访问 local和remote objects。应用线程可随时启动一个事务,并成为事务的协调者。事务中可执行读、写、分配空间、释放空间操作,事务结束时,线程通知FaRM来提交事务。
事务使用乐观并发控制,任何事务提交前,数据被缓存在本地,只对成功提交的事务可见,提交产生冲突时提交失败。
FaRM保证事务的串行化隔离执行:
- 单独对象的读取是原子的
- 只读取最新的已提交数据
- 对于单独对象的read only transaction,提供了lock-free read。
- 多对象读取不保证原子性,但保证事务的执行是严格串行化的
- 采用乐观并发控制,在提交时检查冲突
FaRM架构如上图所示,其中包括:
- CM节点(配置管理器),负责租约、检测错误、协调和恢复
- 数据节点,分为2层:
- Application层
- FaRM层:数据存于NVRAM中,包括Region,TX Log和Msg Queue。
- Coordination service:
- 使用ZooKeeper达成配置共识
- 配置存储格式为
<i,S,F,CM>
,i
为配置id,S
为属于该配置组的machine集合,F
为machine到failure domain的映射(如某个machine属于某个data center),CM
为配置管理器。
FaRM将全局内存划分为不同的Region,其具体内存管理机制如下:
- Region管理:
- 内存以2GB进行划分,称为一个Region。一个Region分布在一个主副本,f个备副本上 。
- Region存储在DRAM中且可以通过RDMA读取
- 所有的读都落在主副本上,通过访问本地内存(若数据在本地)或者RDMA(若数据在远程节点)实现。
- Region到其所在primary与backups的映射关系存储在CM中
- 映射关系可以被其它machine获取并缓存在本地
- Region分配:
- machine向CM请求分配new region
- CM给新Region分配单调递增的标识符,并为该Region选择replica machine,replica machine的选择遵从负载均衡、高容错。
- CM使用2PC协议完成region replicas分配,并在所有replicas上保存存储region和replicas的映射信息
FaRM中的Tx Log和Msg Queue设计为环形队列:
- 每个Receiver端都单独的log queue和msg queue
- Sender通过单边RDMA write写入queue
- Receiver RDMA NIC返回ack,不需要CPU参与
- Receiver周期读取队列头部处理写入数据
Distributed transactions and replication
FaRM的事务提交流程如下图所示。
FaRM事务具体提交流程:
- Execute phase
- coordinator使用单边RDMA从primary读取所需要的data object及版本号
- 将new value写入local buffer中
- 如果coordinator和primary属于同一个machine,则直接从local memory读取
- Commit phase
- Lock
- coordinator向所有涉及到write object的primary写入LOCK record。
- primary使用CAS操作对特定版本的object进行上锁。
- 如果上锁失败则返回fail,coordinator abort事务并向所有相关primary写入ABORT record,向client返回error。
- Validate
- 对only-read transaction进行读验证
- coordinator通过单边RDMA(若对象数量过多,则会使用RPC)从主节点读取版本号,比较是否改变
- 如果发生改变,则abort事务
- Commit backups
- coordinator向所有backup写入COMMIT-BACKUP record并等待ack
- 收到所有backup的ack后,进入下一步
- Commit primaries
- coordinator向所有primary写入COMMIT-PRIMARY record。
- 主节点处理相关记录,并释放lock。
- 只要收到其中某个主节点的ack回复,则认为是成功的,可将结果返回给应用
- Truncate
- coordinator收集到所有primary ack后,可进行日志截断。截断消息可通过其它日志记录的提交请求中捎带,节点收到后,既可以应用变更,同时也可以截断日志。
- Lock
FaRM中消息的定义和log record格式如下图所示。
Failure recovery
Failure detection
FaRM采用租约进行failure detection:
- CM拥有所有machine的租约,machine拥有CM的租约
- 三次握手确定租约
- 节点向CM发送租约请求
- CM回复同意,并捎带自己的租约请求,返回给节点
- 节点返回同意给CM
- 租约过期则判断为异常
- 租约非常短,以保证高可用性
- FaRM使用单独的send/rev消息队列来接收租约信息,保证租约信息能够及时处理
- 每过租约的1/5会发送lease renewal请求续租,lease renewal由单独的lease manager thread执行,且该线程具有最高的优先级。
Reconfiguration
FaRM中的更改配置操作如下:
- Suspect
- CM发现machine租约到期
- 阻塞所有外部client request
- 开始reconfiguration
- machine发现CM租约到期
- 通知一小部分backup cm开始进行reconfiguration
- 一段时间后没有出现new configuration,则自己尝试成为新CM
- CM发现machine租约到期
- Probe
- 新的CM向所有非suspect machine发送RDMA read。
- read fail节点被认为是suspect machine。
- 当半数以上节点read ok时,才会继续进行reconfiguration,因此不会出现network partition问题。
- Update configuration
- 新的CM向Zookeeper集群存储
<c+1,S,F,newCM>
,S为相应probe的机器集合。 - Zookeepr中采用CAS操作更换配置,只有当前配置序号为c时才可以替换,保证了多个机器同时触发reconfiguration时只能有一个成功。
- 新的CM向Zookeeper集群存储
- Remap regions
- 将failure machine上的regions重新分配到其它机器,在分配中考虑load balance和spplication locality
- Send new configuration
- 新的CM向S集合中的所有机器发送NEW-CONFIG message。
- 发送message的同时向其它机器发送lease request
- Apply new configuration
- 收到NEW-CONFIG信息后,应用新配置。
- 拒绝所有的外部client request
- 从这个时刻起,不再响应S集合外其它machine的读写请求
- 回复NEW-CONFIG-ACK message,并grant lease和发送lease request
- Commit new configuration
- 新的CM在收到所有的NEW-CONFIG-ACK并保证S中的machine在序号为c的配置租约已经到期后,发送NEW-CONFIG-COMMIT message,并附带lease grant。
- machine收到信息和lease grant后,开始接收external client request。
- 开始transaction recovery过程。
Transaction state recovery
后面的故障恢复部分过于复杂,并且是根据RDMA特性设计的独有方案,参考的价值也不是很大,没有实际的RDMA经验比较难以理解,本人水平较低。。暂时无法理解其中的奥妙。