Question
- Dynamo 是如何实现自动负载均衡?
设计考虑
数据复制算法
- 选择最终一致性,因为强一致性会影响数据的高可用性。也就是说高可用性和一致性两者间必须要做一个trade-off,联想到CAP理论中,只考虑AP和CP。(可能P2P模式下,很难保证强一致性)
- Dynamo采用最终一致性,不会阻拦别的事务的写操作,因为无需复制完所有的副本才可以进行写操作。这里将冲突的复杂解决方法推到reads上,确保写不会被拒绝。
- 支持强一致性的系统不能很好处理网络分区问题
- 但是Tair却不是这样的,它选择了强一致性(因为它有),它认为Dynamo牺牲了一致性却没有换来什么好处。
冲突解决方法
- 一般考虑在data store还是application中解决,在data store(常用)中解决的话只能用一些很简单的方法,如last write wins;而在application中解决的话,就能结合应用的特性和data schema来综合考虑进行解决(比如合并冲突版本啥的)
其他的关键原理
- Incremental scalability:增加存储节点,都系统的操作和系统本身影响很小
- Symmetry:系统中每个节点都是平等的,责任都是相同的
- Decentralization:没有中心控制节点
- Heterogeneity:不同服务器的能力不同,那么工作量的分布也要随之改变(这边没看懂)
相关工作
Peer to Peer 系统
- 从非结构化的P2P网络(如Freenet, Gnutella)到结构化的P2P网络(使用全局的一致性协议确保任意节点都能route到下一个想要去的节点)(如Pastry,Chord)。Oceanstore和PAST都建于这些routing overlays。
分布式文件系统和数据库
- Dynamo允许网络分区的情况下让读写操作继续,使用不同的冲突解决机制去解决更新冲突。
- Dynamo假定系统环境是安全的情况下进行构建的,不关注数据一致性和安全性问题
Dynamo的独特之处
- 目标应用是:总是可写的,也就是不拒绝update请求(尽管在failures或者并发写的情况下,都可写,这里就是在讲弱一致性的好处了)
- Dynamo假定所有的节点都是可信任的
- Dynamo不需要schema,hierarchical namespaces的支持
- 追求99.9%的延迟性能(每个节点本地都routing 信息)
系统架构
系统接口函数
- get(key): returns a single object or a list of objects with conflicting versions along with a context.
- put(key,context,object) : context和object存在一起是为了能确认put请求提供的context obect的有效性(具体context中的内容是什么,不是很清楚)
分区算法
- 改进一致性哈希算法
- 传统的一致性哈希算法的问题:节点是在ring上随机分布的,这样会导致数据和负载分布不均衡; 无视每个节点的性能会存在差异(Dynamo根据不同节点的性能给予不同数据的token,可认为这个是虚拟节点。物理节点与虚拟节点之间是 1:n的关系)
- 使用虚拟节点的好处: 当一个节点不可用的时候,它的节点负载会被剩下的节点均衡分配; 出现一个新节点,也会平均接受来自其他可用节点的负载; 1:n 中的n可用根据该物理节点的性能来进行设置。
复制
- 每个数据项都被保存在N个主机上,假定key经过分区算法被分配到节点1上,那么1~N都会保存该key。由于存在虚拟节点,可能物理节点不满N个,通过构建skipping positions来解决这一问题(不太理解这一点)。
- 参数N:per-instance
- 存储key的节点list: perference list
数据版本
- 主要是vector clock,但我觉得这个有点鸡肋,将冲突推至客户端去解决。
get()和put()操作的执行
错误处理
永久故障处理:复制同步
- merkle tree还是可以看看的
成员资格和错误检测
增加/移除存储节点
强一致性 & 弱一致性
- 强一致性: 发一条微博的瞬间,就能看到发的内容,满足原子性
- 弱一致性:发一条微博后,过一会儿,才能看到发的内容。
注:大致了解这篇论文后,我要弃了,还不如看看基础的分布式知识,太耗时间了。。