深入研究Cassandra后 重读Dynamo Paper (Document Transcript)

  • 2010 年 7 月 Schubert Zhang重新认真地研读了 Dynamo Paper,读的很慢,足足花了一个星期的时间。与上次读该 Paper不同,这次带着 Cassandra 的实现来理解它。但最终得出了负面的结论:不认为 Dynamo 的架构是个好架构,在大规模的生产系统中,这个架构引入了太多复杂性和设计原则矛盾。或者说 Dynamo 的架构对于存储大规模的数据是不合适的。 Cassandra 社区目前还非常活跃,但通过一段时间对 Cassandra 的研究、使用和理解,感觉 Dynamo 的架构约束在 Cassandra 中也带来了不少问题,而为解决这些问题引入的复杂性和维护性问题也开始突出。 随着多个曾经选择 Cassandra 的公司(Twitter、Flowdock、Facebook的 rumor,Digg 和 Reddit 虽然仍在按计划倚重 Cassandra,但估计难逃失败)宣布“暂时”离开 Cassandra,我们也要重新基于我们自己的理解来审视这个架构。 记得同样出自 Facebook 的 Joydeep Sen Sarma (Hive 的作者之一)曾经写过一篇 blog:Dynamo: A flawed architecture 挑 Dynamo 的毛病,以前没有仔细看,重新读一读发现他的评论似乎有点吹毛求疵,啥问题也没讲清楚,没有太多参考价值。但我认为 Dynamo 的架构缺陷确实是存在的: 用这种 Consistency Hash 的环状拓扑来做存储系统, 特别是大规模(每个节点存储数百 GB、数 TB 甚至数十 TB)存储系统,是不合适的。要想真的弄清楚问题,还是要结合 Cassandra 来仔细读一读 Dynamo 的 Paper。 下面就个人理解,对一些问题进行粗略的讨论。1. 采用 consistent hashing 实现数据 partitioning 带来的问题,Scalability 问题。 分布式存储系统必然要把数据 partition/distribute 到不同的节点上存储,4.2 节和图 2 描 述了基于 consistent hashing 的 partitioning algorithm,那是一个类似 Chord 的 hash ranges 组成的 ring。 但这种相对刚性的 hash partitioning 方法, 在节点加入、节点故障和 balancing 等方面的处理是相当复杂的。 (1) 首先,设计原则中节点的动态对 ring 中其他节点的影响最小的原则将被打破。 在4.2节中有这样的原则描述“The principle advantage of consistent hashing is that departure or arrival of a node only affects its immediate neighbors and other nodes remain unaffected.”但为了 balancing和节点的能力异构的支持,打破了这个原则: To address these issues, Dynamo “ uses a variant of consistent hashing (similar to the one used in [10, 20]): instead of mapping a node to a single point in the circle, each node gets assigned to multiple points in the ring. To this end, Dynamo uses the concept of “virtual nodes”. A virtual node looks like a single node in the system, but each node can be responsible for more than one virtual node. Effectively, when a new node is added to the
  • 2. system, it is assigned multiple positions (henceforth, “tokens”) in the ring.”这样当一个新物理节 点加入时,同样期待所有其他物理节点向其迁移数据。当一个物理节点故障时,同 样期待将其数据由所有其他物理节点暂管。 而为了尽量让不同的物理机器对同一数据存储N个replicas,在配置部署这些virtual nodes时也有些复杂: To address this, the preference list for a key is constructed by skipping “ positions in the ring to ensure that the list contains only distinct physical nodes.” 当一个节点存储的数据量较大时(TB), 新节点的加入和离开会造成相邻节点的大量 数据迁移,这在我们研究Cassandra时也发现这个严重的问题。本来加入节点是为 了缓解系统的负载, 但因为要在少数节点之间大量迁移数据, 造成新的大量的磁盘 IO、网络IO和CPU负荷将压垮整个系统。(补充:后来在Reddit和Digg所报告的事 故中确实发生了这类严重问题。) Cassandra目前还没有实现“virtual nodes”,那么 Dynamo实现了“virtual nodes”就可以了吗?“virtual nodes”就像Bigtable的Tablet,在 数据Balance时, 可以起到在整个集群中分散负载的作用, 但看Paper的描述中可见, 这种“virtual nodes”还是要靠人去配置和维护的,可想其规划和维护难度有多大(下 节介绍)。(2) 刚性的 hash partitioning,在集群中节点故障和恢复是常态的环境下的复杂性。 在6.2节提到为了实现balance,所做的一些优化,提到了三种partitioning strategy, 其中strategy-1和目前Cassandra的RandomPartitioner一样,即节点的位置token和 partition range placement一致,是个最刚性的partitioning strategy,这将带来几个问 题:i) 当新节点加入时,需要从相邻节点迁移数据,而要迁移哪些数据需要从相 邻节点做全面的scan才能分离出来,开销极大。如果放在后台慢慢做,新节点的 bootstraping过程将是漫长的。ii) 节点加入或退出时,因为range的动态变更,相应 的Merkle Tree必须重新构建,这也是很漫长的过程。还有些其他的维护问题都较难 实现。这种策略在现实大规模存储系统中几乎不可用。strategy-2是一种过渡策略, 一般不采用。strategy-3是较理想的策略,例如先将ring划分为10000个range,假如 现在有100台同样的机器,则每个节点分配100个range(所谓“virtual nodes”) ,这样 在节点动态时,迁移数据和计算Merkle Tree都是以range为单位的。这种策略把 partition range placement和节点布局的token分离了。但必须维护一个全局一致的节 点布局tokens和partition ranges间的映射,并且实现partition ranges的assignment,这 个逻辑也没有讲清楚如何实现,相信也是较为复杂的。其实如果采用strategy-3,和 bigtable中的tablet指派和分布方法就类似了,只是bigtable实现的是master指派, Dynamo可能是Gossip-based(至少Cassandra是Gossip-based) ,但在逻辑上并没有本 质差异。bigtable tablet的划分是采用最安全可靠和鲁棒的B+Tree分裂算法,用户不 必去维护一个空间划分的映射,动态性和灵活性都有保证。Dynamo/Cassandra的做 法就丑陋多了。 这也是为什么在 Cassandra 的 maillist 中,Jonathan Ellis 曾指出“nodes being down should be a rare event, not a normal condition”这样和设计初衷相反的回答。且这种假 设在大规模分布式系统中是不成立的,看看 GFS 和 Bigtable 中前面大量篇幅告诉 大家的,节点故障是常见的而不是偶然的。
  • 3. 在Cassandra Paper 5.4节,最后得出这样的结论“An administrator uses a command line tool or a browser to connect to a Cassandra node and issue a membership change to join or leave the cluster.”即节点的动态退到依赖于人工管理。如果您维护着几百上千台机器怎么 办?且实际情况是,即便是人工维护,也会出乱子,系统还是会长时间不可用或超 负荷。 (3) Cassandra 中没有实现 Virtual Nodes,而计划是在节点间交换 Load 信息来将负荷轻 的节点移到负荷重的节点处去分担其负荷。 但这种方法如果做成动态的, 节点在 ring 上的移动将很频繁,而造成控制混乱。如果靠手动维护,将使维护工作很重。另外, 当节点故障时,同样会使迁移工作很繁重。2. 一致性问题 eventually-consistent 因为在数据 write 的时候少关心一致性问题, 而采用离线一致性检查 和 read repair 的方式修正一致性。 (1) 对于我们常常遇到的 write 多 read 少的应用数据, repair 几乎不能保证数据的一 read 致性。结果是数据长期不一致,甚至永远不一致。因为很多数据可能很久或者永远 也不会被读到。 (2) Read 时做的一致性检查,虽然只比较 Digest 在网络 IO 上减少了字节数,但要知道 Read 操作是 Random,Random 对磁盘负荷的开销是巨大的。因为要比对 Digest 判 断是否 Read Repair,每个 read 操作实际上都有 hit 3 个 replica 的磁盘,这个开销是 惊人的,甚至远远超过因为所谓的 Eventually Consistent 在 write 操作是不须写全 3 份所获得的好处。如果评估过 Cassandra 就知道其 Read 性能有多差,并且对系统负 荷的影响有多大。 其实我觉得 eventually-consistent 中在 Read 时 Repair 一致性问题本身就是错误的, 我们知道为了读写最终要落到磁盘上,而为了写的快,现在一般的做法是要尽量做 sequentially 写而避免 random 写, Bigtable 就是这个基本原则(CommitLog+SSTable), Cassandra 号称是 Dynamo 和 Bigtable 的“完美”结合(这是错误的) ,在写磁盘上 也是基于 CommitLog+SSTable。大家都知道顺序写是很快的,所以 Write 的时候保 证一致性是可以做到很快的(GFS 正时这样做的) 。但 Read 的时候因为谁也不知道 applications 要读那个数据,必然是 Random 的,选择这个时候去 Repair,必然压垮 本来就忙的很的磁盘。 (3) 离线检查采用非常好的 Merkle Tree 算法,但这种算法比较基于静态数据是比较有 效的,每次比较必须对现有数据重建 Merkle Tree。对于总是有数据不一致(例如, 节点动态、网络动态、磁盘动态等)的情况下,很难保证持续的一致性,而且每次重 建 Merkle Tree 需花太多系统资源和时间。如果评估过 Cassandra 就知道其做大量数 据的 Anty-Entropy 时系统几乎要忙死。 (4) Dynamo 的数据模型是简单的 key-value,而且每个 key-value 都很小(如<1MB)。 Merkle Tree 用于这种数据模型也许是适用的。但对于 Cassandra 的数据模型 Key-Columns,因为操作时的粒度是 Column,随时都可能出现同一个 Key 的不同 Column 不一致的情况,因此不一致的情况会更普遍,这种同步策略是否适应有待 考验。不可否认,如果 Dynamo 每个节点只存储书 GB 数据甚至更少,因为大部分 甚至全部数据可以 Cache 在内存中,或许这种架构是可以应付的。3. Hinted Handoff 的不可见性
  • 4. Hinted Handoff 虽然可以保证数据可以被 write,但是不可见的,无法读取。Cassandra 中关闭 Hinted Haddoff 其实会导致数据永久不一致。 Hinted Handoff 适合解决一些临时性短时间节点不可达问题,而不适合解决稍微长点时 间的节点不可达,因此,在生产系统中效果可能不好。 而 Hinted Handoff 并不能代替 Replication,因为他没有增加对 Replication 数据的保证。4. Replication 实现 Dynamo 的 Replication 的宏观管理粒度虽然是基于 Partition Range 的,但实际在操作层 面是基于 Key-Value。 前面提到的混合的 Key-Value 很难做一致性检查和数据分离, 在实 际实现数据迁移、 数据分离、 数据维护等很多工作都很不便, 而且离线的校验效率很低。 复杂性太高。5. Dynamo 的 Virtual Nodes 是为了 DHT 的刚性环结构多数据进行划分的粒度太粗的问题,这么粗的粒度几乎无法 实现系统的 Scalability (试想加入一个节点对相邻节点的冲击有多大) 。Virtual Nodes 实际上就是要把划分粒度弄细些,但 Virtual Nodes 的维护是很难的,如何实现动态维护 所有的 Virtual Nodes 光靠几句话是难以解决的,单靠配置解决也是不可想象的,试想每 个节点有几百个 Virtual Nodes,还有保证不能相邻导致散列太不均匀的难度有多大。6. Local Storage Engine 的实现 Dynamo 的实现比较偷懒,直接使用了现成的比较成熟的 BDB 或 MySQL 等(侧面说明 他单点存储的数据是很小的, 甚至是内存级别的)。 不过其 pluggable 的实现是比较好的。 也正因为 Dynamo 的实现缺乏 Storage Engine 的经验, 也直接导致了 Cassandra 的这部分 实现非常糟糕。Cassandra 引入了 Bigtable 的 CommitLog+SSTable 原则,但其具体实现 确实个另类, 从其 IndexFile 和 DataFile 就可以看出这种另类, 所以他本质上不是 SSTable, 我们曾经在其中加入了 Compression 功能,但其基于 Block 的划分竟然是在 Key 范围内 的(参考 http://www.slideshare.net/schubertzhang/dastorcassandra-report-for-cdr-solution 这 个 ppt 中的图) 。但这部分其实并没有引起大的问题,不是架构造成的。7. 前端功能和后台任务抢占系统资源 后台任务太多,会长时间占用太多的系统资源,导致系统前端应用性能下降,更糟的情 况会是系统后台任务永远赶不上前端数据操作的情况的恶性循环。减少后台任务的种类 和频度是必要的,同时要使后台任务的执行减少无用的重复。在 Dynamo 中,节点的动 态和一致性检查都会使后台任务长时间运行,而且 bootstraping 时间会比较长。在 Cassandra 中没有限制和并发的 Compaction(我们曾经为 Cassandra 增加了并发的 Compaction 功能)也会使系统长时间处于繁重的后台处理中。8. 架构决定不了的问题必须采用很多修补架构的技术,但并不是很有效。 Dynamo 的 Read Rapir, Hinted Handoff、Merkle Tree、Virtual Nodes,Clock Vector 等技术, 其实都是为了修补其架构和设计原则缺陷而采用的方法,但实际使用中的表现并不好, 徒引入更多的复杂性。
  • 5. Cassandra 的所谓“Dynamo+Bigtable”其实是个错误 数据模型方面: Dynamo 的一个 Key/Value 是作为一个原子操作的(采用 Merkle Tree 较合 适), Cassandra 在 Dynamo 上引入 Bigtable 的稀疏 column 数据模型后, 而 就失去了这个 假设,数据一致性的策略将更加复杂。要知道 Bigtable 是一个“A Distributed Storage System”而 Dynamo 只是个“Key-value Store”。 存储引擎方面:Dynamo 的存储引擎上没有特别支持,可以采用 BDB/MySQL 也可以开 发其他的存储引擎。但 Cassandra 引入了 Bigtable 的 CommitLog 和 SSTable,这没有问 题,但其实现特别是 SSTable 的实现是个另类。另外:1. Dynamo Paper 中采用的测试和评估系统 SLA(Service Level Agreements)的方法可以在我 们以后的评估测试中采用。比如对操作 Throughput 和 Latency 的评估,采用 99.9%分布 和平均值结合的方式评估。或者我们也可以考虑类似 n 西格玛的指标。这个性能测试方 法能是每个测试和系统评估人员必须要掌握的,这一点是这个 Paper 中正面的部分。2. Dynamo 中的 Client 模型,除了类似 Cassandra 中的最廋的 Thrift/Avro 接口外,也可以 选择介于肥大 Client(Client 本身也在集群中,知道集群的所有节点信息,例如 Cassandra 的 Client Mode Instance)和廋 Client 之间的一种实现(Client 周期到随机节点查询集群信 息)。有个大胆的结论:(1) Dynamo 模型作为简单的 Key-Value Store,每个节点只存储少量数据,可能是可以的。 但 Cassandra 把他作为一个 Data Storage 系统,也许是个错误的选择。(2) Dynamo 采用的核心分布式架构 DHT,不适合实现实际空间有限(如 1000 个节点,而不 是 100 万个节点)的存储系统。这种架构在存储系统中的 Scalability 特性是很差的。(3) Dynamo 采用了错误的分布式架构,并采用一些看似巧妙“高科技”但实际上不合适甚 至帮倒忙的修补技术(Read Repair,Hint Handoff, Markle Tree 等)(4) 所谓 Eventually Consistent 导致的结果是等于 Always Inconsistent。而且引入太多复杂性。(5) Cassandra 虽然号称是 Dynamo+Bigtable 结合的产物,但实际上在架构上完全是 Dynamo 的,没有一点 Bigtable 的影子。只是在 Data Schema 上稍微有点 Bigtable 的影子(Column Family),但也不得要领。所以所谓的 Dynamo+Bigtable 的结合体必然造就一个怪胎,不 能成大器。 那个以 Cassandra 为基础的 Startup 惊人拿到几百万美金的 VC, 看来那个 VC 被骗了。References:- http://engineering.twitter.com/2010/07/cassandra-at-twitter-today.html- http://blog.nodeta.fi/2010/07/26/flowdock-migrated-from-cassandra-to-mongodb/- Joydeep Sen Sarma < Dynamo: A flawed architecture – Part I> and < Dynamo – Part I: afollowup and re-rebuttals>- http://www.mail-archive.com/user@cassandra.apache.org/msg03150.html除了在上述《重读 Dynamo Paper》中提到的架构复杂性问题外,Cassandra 还存在下列问题:
  • 6. 1. Compaction 大量数据耗时耗资源,这其实是架构错误导致的。2. 没有数据压缩,而且很难实现好的压缩,是其糟糕的 Storage Engine 实现导致的。3. 节点加入/退出等维护复杂,这也是是架构错误导致的。4. 很多 Bug。2012 补充:- http://www.slideshare.net/schubertzhang/dastorcassandra-report-for-cdr-solution-http://highscalability.com/blog/2010/7/11/so-why-is-twitter-really-not-using-cassandra-to-store-tweets.html1. 获悉 Twitter 等若干曾经对 Cassandra 很感兴趣的公司都纷纷在 blog 中宣部离开;2. Reddit 的 Cassandra 苦恼;http://blog.reddit.com/2010/05/reddits-may-2010-state-of-servers.html另外原始问题的连接找不到了。3. Digg 倚重 Cassandra 做了一个大改版,也是一个大失败,当时辞退了其 VP Engineering,2012 年 7 月以 50 万美元卖了。http://tech.qq.com/a/20120713/000016.htm
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值