SlideShare a Scribd company logo
1 of 6
Download to read offline
深入研究 Cassandra 后
                                      重读 Dynamo Paper


                                                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
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 中前面大量篇幅告诉
   大家的,节点故障是常见的而不是偶然的。
在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 的不可见性
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 等技术,
   其实都是为了修补其架构和设计原则缺陷而采用的方法,但实际使用中的表现并不好,
   徒引入更多的复杂性。
9. 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: a
followup and re-rebuttals>
- http://www.mail-archive.com/user@cassandra.apache.org/msg03150.html

除了在上述《重读 Dynamo Paper》中提到的架构复杂性问题外,Cassandra 还存在下列问题:
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-t
weets.html
1. 获悉 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

More Related Content

More from Schubert Zhang

Engineering practices in big data storage and processing
Engineering practices in big data storage and processingEngineering practices in big data storage and processing
Engineering practices in big data storage and processingSchubert Zhang
 
Bigtable数据模型解决CDR清单存储问题的资源估算
Bigtable数据模型解决CDR清单存储问题的资源估算Bigtable数据模型解决CDR清单存储问题的资源估算
Bigtable数据模型解决CDR清单存储问题的资源估算Schubert Zhang
 
Big Data Engineering Team Meeting 20120223a
Big Data Engineering Team Meeting 20120223aBig Data Engineering Team Meeting 20120223a
Big Data Engineering Team Meeting 20120223aSchubert Zhang
 
HBase Coprocessor Introduction
HBase Coprocessor IntroductionHBase Coprocessor Introduction
HBase Coprocessor IntroductionSchubert Zhang
 
Hadoop大数据实践经验
Hadoop大数据实践经验Hadoop大数据实践经验
Hadoop大数据实践经验Schubert Zhang
 
Wild Thinking of BigdataBase
Wild Thinking of BigdataBaseWild Thinking of BigdataBase
Wild Thinking of BigdataBaseSchubert Zhang
 
RockStor - A Cloud Object System based on Hadoop
RockStor -  A Cloud Object System based on HadoopRockStor -  A Cloud Object System based on Hadoop
RockStor - A Cloud Object System based on HadoopSchubert Zhang
 
Hadoop compress-stream
Hadoop compress-streamHadoop compress-stream
Hadoop compress-streamSchubert Zhang
 
Ganglia轻度使用指南
Ganglia轻度使用指南Ganglia轻度使用指南
Ganglia轻度使用指南Schubert Zhang
 
DaStor/Cassandra report for CDR solution
DaStor/Cassandra report for CDR solutionDaStor/Cassandra report for CDR solution
DaStor/Cassandra report for CDR solutionSchubert Zhang
 
Learning from google megastore (Part-1)
Learning from google megastore (Part-1)Learning from google megastore (Part-1)
Learning from google megastore (Part-1)Schubert Zhang
 
Hanborq optimizations on hadoop map reduce 20120221a
Hanborq optimizations on hadoop map reduce 20120221aHanborq optimizations on hadoop map reduce 20120221a
Hanborq optimizations on hadoop map reduce 20120221aSchubert Zhang
 
Cassandra Compression and Performance Evaluation
Cassandra Compression and Performance EvaluationCassandra Compression and Performance Evaluation
Cassandra Compression and Performance EvaluationSchubert Zhang
 
The World of Structured Storage System
The World of Structured Storage SystemThe World of Structured Storage System
The World of Structured Storage SystemSchubert Zhang
 
Distributed Filesystems Review
Distributed Filesystems ReviewDistributed Filesystems Review
Distributed Filesystems ReviewSchubert Zhang
 
Red Hat Global File System (GFS)
Red Hat Global File System (GFS)Red Hat Global File System (GFS)
Red Hat Global File System (GFS)Schubert Zhang
 

More from Schubert Zhang (20)

Engineering practices in big data storage and processing
Engineering practices in big data storage and processingEngineering practices in big data storage and processing
Engineering practices in big data storage and processing
 
HiveServer2
HiveServer2HiveServer2
HiveServer2
 
Horizon for Big Data
Horizon for Big DataHorizon for Big Data
Horizon for Big Data
 
Bigtable数据模型解决CDR清单存储问题的资源估算
Bigtable数据模型解决CDR清单存储问题的资源估算Bigtable数据模型解决CDR清单存储问题的资源估算
Bigtable数据模型解决CDR清单存储问题的资源估算
 
Big Data Engineering Team Meeting 20120223a
Big Data Engineering Team Meeting 20120223aBig Data Engineering Team Meeting 20120223a
Big Data Engineering Team Meeting 20120223a
 
HBase Coprocessor Introduction
HBase Coprocessor IntroductionHBase Coprocessor Introduction
HBase Coprocessor Introduction
 
Hadoop大数据实践经验
Hadoop大数据实践经验Hadoop大数据实践经验
Hadoop大数据实践经验
 
Wild Thinking of BigdataBase
Wild Thinking of BigdataBaseWild Thinking of BigdataBase
Wild Thinking of BigdataBase
 
RockStor - A Cloud Object System based on Hadoop
RockStor -  A Cloud Object System based on HadoopRockStor -  A Cloud Object System based on Hadoop
RockStor - A Cloud Object System based on Hadoop
 
Fans of running gump
Fans of running gumpFans of running gump
Fans of running gump
 
Hadoop compress-stream
Hadoop compress-streamHadoop compress-stream
Hadoop compress-stream
 
Ganglia轻度使用指南
Ganglia轻度使用指南Ganglia轻度使用指南
Ganglia轻度使用指南
 
DaStor/Cassandra report for CDR solution
DaStor/Cassandra report for CDR solutionDaStor/Cassandra report for CDR solution
DaStor/Cassandra report for CDR solution
 
Big data and cloud
Big data and cloudBig data and cloud
Big data and cloud
 
Learning from google megastore (Part-1)
Learning from google megastore (Part-1)Learning from google megastore (Part-1)
Learning from google megastore (Part-1)
 
Hanborq optimizations on hadoop map reduce 20120221a
Hanborq optimizations on hadoop map reduce 20120221aHanborq optimizations on hadoop map reduce 20120221a
Hanborq optimizations on hadoop map reduce 20120221a
 
Cassandra Compression and Performance Evaluation
Cassandra Compression and Performance EvaluationCassandra Compression and Performance Evaluation
Cassandra Compression and Performance Evaluation
 
The World of Structured Storage System
The World of Structured Storage SystemThe World of Structured Storage System
The World of Structured Storage System
 
Distributed Filesystems Review
Distributed Filesystems ReviewDistributed Filesystems Review
Distributed Filesystems Review
 
Red Hat Global File System (GFS)
Red Hat Global File System (GFS)Red Hat Global File System (GFS)
Red Hat Global File System (GFS)
 

深入研究Cassandra后 重读Dynamo Paper

  • 1. 深入研究 Cassandra 后 重读 Dynamo Paper 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. 9. 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: a followup 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-t weets.html 1. 获悉 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