分布式状态
● 例子:文件系统
● 例子:网络文件系统 分布式状态
- “在系统的某处保留的某个地方描述某事物或由某事物决定的信息”
- 分布式状态的好处
- 性能
- 可靠性
- 一致性
● 网络文件系统:文件访问
● 客户端缓存
为什么我们需要缓存?
- 减少对瓶颈服务的负载
- 利用局部性
- 更好的延迟
- 缓存位置更便利且希望更快
- 高层视图:
- 缓存:将数据移动到我们想使用它的地方
- RPC:将计算移动到数据所在的地方
多个缓存怎么办?更新呢?
NFS
NFS文件系统的方法
- NFS:由Sun Microsystems在1984年开发
- 设计哲学:简单性
- “无状态”
- 所有关键信息保留在文件服务器的磁盘上
- 仍可以在服务器内存中缓存,但不能依赖缓存来确保正确性
- 服务器不缓存客户端信息
- 幂等操作
- 在偏移量处读写
- 查找
NFS更新协议
- 当客户端写入文件时
- 更新本地缓存
- 向服务器发送写请求
- 服务器将数据写入磁盘
NFS更新协议的问题
- 性能
- 每个客户端写请求都同步写入服务器磁盘
- 一致性
- 其他客户端缓存未被通知更新
- 读取不一致数据
- NFS的解决方案?
- 周期性轮询
- 最终接收更新
NFS周期性轮询
Sprite
替代方案:Sprite文件系统
- Sprite:来自伯克利的类Unix分布式操作系统
- 服务器跟踪打开的文件状态
- 哪些客户端正在读写哪些文件
- open()/close()需要联系服务器
- 服务器使用“写回缓存”
- 修改的块保留在内存中
- 30秒后写回磁盘
Sprite文件系统:一致性
- 服务器知道哪些客户端正在读写文件
- 如果只有一个客户端打开文件
- 客户端不会同步将更新发送到服务器
- 30秒后写回服务器
- 如果多个客户端打开文件,并且至少有一个在写入
- 所有读写操作都通过服务器(不可缓存)
Sprite的更新协议
Sprite方法的优缺点
- 优点:
- 一致性
- 性能
- 缺点:
- 复杂性
- 持久性和恢复
- 权衡!
其他方法
- 作废
- 写入者使所有其他缓存副本无效
- 写入更新
- 写入者更新所有其他缓存副本
一致性
我们说Sprite比NFS提供了更好的一致性 但我们如何定义和比较一致性?
如何定义一致性?
- 看到旧值是否可以?只要不超过30秒?
- 也许看到旧值可以,只要它不是在我们最后一次更新之前?
- 或者我们应该总是读取最新的更新?
- 如果读取和更新同时(大致)发生怎么办?
- 如果有并发更新怎么办?我应该读哪一个?
- 我们需要正式的语义!
一致性
- 一致性:一组操作对数据存储或共享对象的允许语义(返回值)。
- 一个安全属性:
- 指定在任何执行中不应该发生的“坏事”
- 不是活性属性:
- 指定在每次执行中应该发生的“好事”
- 一致性属性指定接口,而不是实现。
- 数据可能被复制、缓存、分解等。
- 异常:违反一致性语义
术语:强和弱
- 强一致性:系统表现得好像只有一份数据副本
- 缓存和复制等实现细节对客户端不可见
- 弱一致性:允许与单一存储模型显著不同的行为。
- 最终一致性:异常行为只是暂时的。
为什么会有差异?
- 性能
- 一致性需要在数据被缓存/复制时进行同步/协调
- 通常为了确保总是返回正确答案而变慢
- 可用性
- 如果客户端离线,或网络不工作怎么办
- 弱/最终一致性可能是唯一选项
- 可编程性
- 较弱的模型更难以理解
一些符号
- 假设有一个单一寄存器
- 对共享寄存器的更正式定义参考Lamport的论文
- 适用于任意共享对象
- 进程发出RPC以读取或写入值
- 初始请求开始于时间t,回复在稍后的某个时间t+x返回 顺序一致性
顺序一致性
- 要求操作历史等同于一个合法的顺序历史,其中合法的顺序历史是一个
- 尊重每个节点本地排序的历史。
- 真实(物理)时间跨进程不决定排序
- 也称为...
- 应用于事务时称为可串行化
线性一致性
- 线性一致性 = 顺序一致性 + 尊重真实时间顺序。
- 如果操作1结束于操作2开始之前,则操作1在顺序历史中出现在操作2之前。
- 如果它们是并发的,那么任何顺序都可以接受。
- 线性一致的数据结构表现得就像有一个单一、正确的副本。
- 对于并发对象来说,这是最强的保证之一。
线性一致性与顺序一致性
- 顺序一致性允许操作出现在真实时间顺序之外。这在实际实现中如何发生?
- 系统是顺序一致但不是线性一致的最常见方式是允许只读操作返回陈旧数据。
因果一致性
- 非并发的写操作(即,由happens-before关系相关的写操作)必须按照该顺序被看到。并发写可以在不同节点上以不同的顺序被看到。
- 线性一致性意味着因果一致性。
我们可以更弱!
- FIFO一致性:由同一个进程完成的写操作按照该顺序被看到;由不同进程完成的写操作可以按不同顺序被看到。
- 最终一致性 ≈ 如果对一个对象的所有写操作都停止了,最终所有进程都会读到相同的值。