简介
Frangipani
有着关于 缓存一致性, 分布式事务和分布式故障恢复的有趣设计
整体架构: 网络文件系统 (Network File System, NFS
)
Frangipani
模块运行在工作站内核中, 实现文件系统
文件系统的所有数据结构都存储在一个叫做 Petal
的虚拟磁盘中
锁服务
锁服务器里面有一个 锁表单, 每个锁是一个文件
存储文件名字和持有锁的工作站
此处以互斥锁来举例, 实际上 Frangipani
是读写锁
工作站的 Frangipani
模块中也要存储锁表单
锁表单里面记录文件名, 锁的状态, 文件缓存的内容
规则
- 当未持有锁的时候, 不允许缓存数据
- 释放锁之前的修改必须被写入
Petal
中
流程
工作站向锁服务器请求对应的锁, 之后向 Petal
服务器请求具体的数据
锁状态一般有两种 Busy
和 Idle
状态
当工作站进行各种系统调用(创建删除文件之类)时, 锁处于 Busy
状态
当工作站处理完文件之后, 锁状态被置为 Idle
(每隔 30s 将缓存写入 Petal
)
当有其他工作站请求这个锁时, 且锁状态是 Idle
本工作站把缓存的数据写入 Petal
, 删除对应锁表项
原子性保证
工作站在修改文件的时候持有持有锁, 实现了原子性保证
故障恢复
通过预写式日志(Write-Ahead Log, WAL
) 来实现故障恢复
每个工作站的 Log
保存在 Petal
中, 每个 Log
条目包含 Log
序列号, 只包含元数据的修改
流程
- 把工作站内存中未写入的
Log
写入Petal
中 - 把缓存的数据写入
Petal
- 回复 锁服务器, 释放锁
故障分析
写入 Log
时崩溃
锁服务器有一种租约机制, 如果工作站长时间未响应, 那么锁服务器会通知
另外一个还活着的工作站让他读取 Log
然后进行恢复, 恢复完成之后释放锁
写入数据的时候崩溃
同上, 读取 Log
进行更新, 写入操作是幂等的, 可以重复写入
释放锁之后崩溃
文件增加一个版本号, 恢复的时候先确认版本号是否正确再恢复
目标环境
小的工作组, 不是大型分布式系统的主要应用场景