何时不应使用Cassandra?

227

最近有很多与 Cassandra 相关的讨论。

Twitter、Digg、Facebook 等大型网站都在使用它。

什么时候需要使用Cassandra:

  • 需要使用Cassandra时
  • 不需要使用Cassandra时
  • 使用关系型数据库替代Cassandra时

8
可能应该添加一个警告?这基本上只涉及NoSQL和关系型数据库的比较,这在我的个人看法中很主观。 - Ed James
3
请问这个系统适合用于消息传递吗?我认为如果Twitter在使用它,那么应该是可以的,不过他们可能并没有在Twitter的所有功能中都使用它? - Luke
http://techblog.bozho.net/?p=232 - Bozho
18个回答

186

没有什么是万能的解决方案,每个技术都是为了解决特定的问题而存在并都有其优缺点。关键在于您要知道自己面临的问题,并确定最适合解决该问题的方案。

我将按照您提出问题的顺序依次回答它们。由于Cassandra基于NoSQL数据库系列,因此在回答您的问题之前,重要的是您了解为什么使用NoSQL数据库。

为什么使用NoSQL

对于RDBMS来说,选择相对容易,因为这一类所有数据库(如MySQL、Oracle、MS SQL、PostgreSQL)几乎都提供了针对ACID属性的相似解决方案。当涉及到NoSQL时,决策变得困难,因为每个NoSQL数据库都提供不同的解决方案,您必须了解哪一个最适合您的应用/系统要求。例如,MongoDB适用于系统要求无模式文档存储的用例。HBase可能适合搜索引擎、分析日志数据或任何需要扫描巨大的二维无连接表格的地方。Redis是为提供各种数据结构(如树、队列、链表等)的内存搜索而构建的,可以很好地用于制作实时排行榜、发布-订阅等系统。同样,还有其他适合不同问题声明(包括Cassandra)的数据库。现在让我们转到原始问题,并逐个回答它们。

何时使用Cassandra

作为NoSQL家族的一部分,Cassandra提供了一个解决方案,用于解决需要具有非常重的写入系统并且希望在存储的数据之上构建一个灵敏的报告系统的问题。考虑Web分析的使用情况,其中为每个请求存储日志数据,并且您想要建立围绕此数据的分析平台,以实时计算每小时、每个浏览器、每个IP等的点击次数。您可以参考此篇博客文章,了解Cassandra适用的更多用例。

何时使用关系型数据库而不是Cassandra

Cassandra基于NoSQL数据库,不提供ACID和关系数据属性。如果你需要强制要求ACID属性(例如金融数据),那么在这种情况下,Cassandra将不适合。显然,你可以通过一些变通方式来实现,但是你最终会编写大量应用程序代码来模拟ACID属性,这将严重影响产品的上市时间。同时,使用Cassandra管理此类系统将变得复杂和繁琐。

何时不使用Cassandra

如果上述解释让人感到有道理,我认为就不需要回答这个问题了。


1
答案的问题在于它将所有NoSQL解决方案都混为一谈。详见http://dataconomy.com/sql-vs-nosql-need-know/了解更多信息。在NoSQL领域中,基本的划分是文档、键值、图形和大表。它们针对不同的问题具有不同的特点。一个适合mongo的解决方案可能并不适合cassandra。 - Yehosef
19
这段话的意思是,唯一把所有NoSQL解决方案归为一类的方式是通过NoSQL这个类别;除此之外,这篇文章很好地指出每个NoSQL数据库都为不同问题提供了不同的解决方案。作者没有让人感觉到Mongo、Cassandra或其他任何NoSQL数据库解决了相同的问题。 - Nick Suwyn
1
“NoSQL数据库”不是一个具体的事物。 “NoSQL”只是用于现代非关系型数据库的术语(请参见[维基百科](https://en.wikipedia.org/wiki/NoSQL))。 - eddyP23
2
另外,需要注意的是,并非所有的NoSQL数据库都不符合ACID。图形数据库通常符合ACID要求。 - eddyP23
Cassandra支持行级别原子操作和轻量事务使用每个分区的原子性和隔离性。如果我的要求是在行级别具有ACID,我不能使用Cassandra吗?即使对于关键数据? - TechEnthusiast
请注意,偏好重写主要是针对完整的写入。这种方式效率较低,特别是在更新存储数据时需要更多的开发工作。我还要补充一点,这也是不适合使用Cassandra的反向指示。 - Frank Hopkins

57

在评估分布式数据系统时,您必须考虑CAP定理 - 您可以选择以下两个: 一致性、可用性和分区容错性。

Cassandra是一种可用的、分区容错的系统,支持最终一致性。更多信息请参见我撰写的这篇博客文章:NoSQL系统的可视化指南


你上次看到两个分区都很大的情况是什么时候?请参考我的问题:http://stackoverflow.com/questions/7969874/is-the-cap-theorem-a-red-herring - Aaron Watters
5
Cassandra 显然允许在查询时指定一致性要求,这可能对某些使用情况是一个有用的折衷方案。 - Richard Marr

34

Cassandra是解决一个特定问题的答案:当您拥有的数据量太大,无法放在一台服务器上时,该怎么办?如何在多台服务器上存储所有数据而不破坏银行账户并让开发人员保持理智?Facebook每天会获得4TB的新压缩数据,而这个数字很可能会在一年内增长超过两倍。

如果您没有这么多数据,或者您可以支付数百万美元用于企业级Oracle/DB2集群安装和所需的专家设置和维护,则使用SQL数据库就足够了。

然而,Facebook现在几乎完全使用MySQL,放弃了Cassandra,并将分区提升到应用程序堆栈中以获得更快的性能和更好的控制。


2
你知道为什么FB停止使用Cassandra吗?还有,“将分区向上移动到应用程序堆栈中”是什么意思?是指FB使用多个MySQL表,并使用一些应用程序逻辑来决定要使用哪个表来存储数据集吗? - Manu Chadha
@Vargif Verdi,MongoDB也可以解决你的特定问题,对吧?那么在这种情况下,我们应该使用MongoDB还是Cassandra? - MrSham

29

NoSQL的一般理念是,你应该使用最适合你的应用程序的数据存储方式。如果你有一张包含金融数据的表格,使用SQL。如果你有需要复杂/缓慢查询才能映射到关系型模式的对象,请使用对象或键值存储。

当然,你遇到的任何现实问题都处于这两个极端之间,而且两种解决方案都不会完美。你需要考虑每种存储的功能和使用其中一个而非另一个的后果,这将非常特定于你试图解决的问题。


3
该模式不太可能改变,它适合于表格结构,丢失或不一致的数据可能会导致实际问题。 - Tom Clarkson
4
我不明白为什么不一致的数据会给银行带来真正的问题。场景:你有一个银行账户,上面有100美元的余额限制,并且有两张银行卡。当你尝试同时使用这两张卡在2个不同的ATM机上取款时,你将获得2次100美元的取款,并收到一封信件附带额外费用。银行通过使用不一致的数据赚钱(低于限制的额外费用)。连接全球所有ATM机的大型关系数据库太困难了。你能否举一个不一致的财务数据可能成为问题的例子? - Paco
5
那些东西都是 COBOL 和批处理,远没有你想象的那样设计得好和稳定。ATM机不连接任何统一的数据存储,所以几乎不是一个合适的例子。这就像说 SQL 不适用于 Web 应用程序,因为您不能直接让互联网上的每个人都访问您的数据库。此外,我从未提到过银行——考虑一些诸如电子商务网站上的订单之类的事情,您无需与一个认为SQL是新且不可信的保守组织打交道。 - Tom Clarkson
6
@Paco: 第一台自动取款机读取您的余额($100),第二台自动取款机也是如此。 两台自动取款机都从$100中扣除$100,并将最终余额$0写回到您的账户。结果:银行损失了$100。 - Seun Osewa
9
重点是,如果没有适当的事务隔离,普通银行甚至不会知道账户已经透支。他们甚至都不会知道。 - Seun Osewa
显示剩余6条评论

15

我将重点关注一些重要的方面,这些方面可以帮助你决定是否真正需要Cassandra。列表并不详尽,只是我脑海中的一些重点-

  • 在数据集关系(跨数据集)有严格要求时,不要把Cassandra视为首选。

  • Cassandra默认是AP系统(CAP)。但是它支持可调一致性,这意味着它可以配置为支持CP。 因此,不要只是因为在某个地方读到它是AP系统而忽略它,如果你正在寻找CP系统。 Cassandra更准确地被称为“可调一致性”,这意味着它允许您轻松地决定所需的一致性级别,并平衡可用性级别。

  • 如果你的规模不大,或者可以处理非分布式数据库,请不要使用Cassandra。

  • 如果你的团队认为,只要使用像Cassandra这样的分布式数据库,就可以解决所有问题,那么请认真考虑。起步使用这些数据库非常简单,因为它们带有许多默认值,但为了解决特定问题进行优化和掌握它,需要大量的工程工作。

  • Cassandra是列导向的,但同时每行也有一个唯一的键。因此,将其视为索引的行定向存储可能会有所帮助。 你甚至可以将它用作文档存储。

  • Cassandra不强制你预先定义字段。因此,如果你处于创业模式或者你的特性正在发展(如敏捷开发)-Cassandra支持它。所以最好首先考虑查询,然后再考虑回答这些查询所需的数据。

  • Cassandra针对写入具有真正高吞吐量的优化。如果你的用例以读取为主(例如缓存),那么Cassandra可能不是理想的选择。


  • 2
    针对您提到的最后一点,如果我们使用键/值类型缓存与Cassandra一起使用,是否可以解决具有高写入和读取比例的系统的目的? - Gautam Jain
    是的,我同意@GautamJain的观点。 - rai.skumar

    15
    除了上面提到的关于何时使用和何时不使用Cassandra的答案之外,如果您决定使用Cassandra,您可能希望考虑不使用Cassandra本身,而是使用其中的许多同类产品之一。
    一些上面的答案已经指出了各种“NoSQL”系统,这些系统与Cassandra共享许多属性,存在一些小或大的差异,并且可能比Cassandra本身更适合您的特定需求。
    此外,在这个问题最初提出几年后,一个名为Scylla(请参见https://en.wikipedia.org/wiki/Scylla_(database))的Cassandra克隆版被发布。Scylla是C++中Cassandra的开源重新实现,它声称具有比原始Java Cassandra更高的吞吐量和较低的延迟,同时在功能、API和文件格式方面与原始版本基本兼容。因此,如果您已经考虑使用Cassandra,您也可以考虑使用Scylla。

    抱歉,但这并不是对原问题的回答。 - Gautam Jain
    1
    那是你的观点...13个人持有不同的看法。让我们面对现实吧 - 不使用Cassandra的一种方法是使用类似于Cassandra但不是Cassandra的东西。 - Nadav Har'El

    13

    没错。当你有大量数据,大量查询但查询种类非常少时,使用Cassandra是很有意义的。Cassandra基本上通过分区和复制来工作。如果所有的查询都基于相同的分区键,那么Cassandra是你最好的选择。如果你得到一个基于非分区键的属性的查询,Cassandra允许你使用新的分区键复制整个数据。因此现在你有了两个不同分区键的相同数据的2个副本。

    这就引出了下一个问题。什么时候使用Cassandra?正如我提到的,Cassandra通过为每个新的分区键复制完整的数据库来扩展。但你不能一遍又一遍地制作新的副本。因此,当你的查询多样化,即每个查询在where子句中有不同的列时,Cassandra不是一个好的选择。

    现在到了第三个问题。使用RDBMS的整个要点是当你想要ACID属性时。如果你正在构建像支付服务之类的东西,并希望每个事务都被隔离、每个事务要么完成要么不完成、更改在系统失败后持久,以及交易完成前后银行账户中的金额保持一致,则只有RDBMS可以帮助你实现这一点。

    这篇文章详细阐述了整个问题,特别是何时使用Cassandra或其他NoSQL选项来回答“在系统设计面试中选择最佳数据库”的问题 -> 选择最佳数据库。一定要看看。

    编辑: 回答proximab在评论中提出的问题,当我们考虑银行系统时,我们立刻想到“ACID是最好的解决方案”。但即使是银行系统也由多个子系统组成,这些子系统可能甚至不涉及任何与交易相关的数据,例如账户持有人的个人信息、账单、信用卡详情、信用历史等。

    所有这些信息都需要存储在某个数据库中。现在,如果您存储与帐户相关的信息(如帐户余额),则应始终保持一致。例如,如果您尝试从帐户A向帐户B发送资金,则从帐户A消失的资金应立即显示在帐户B中,并且不能同时存在于两个帐户中。此系统在任何时候都不能不一致。这就是ACID至关重要的地方。

    另一方面,如果您要保存信用卡详细信息或信用记录,并且这些信息不应该落入错误的手中,则需要一些只允许授权用户访问的内容。我认为Cassandra支持这种需求。也就是说,像信用历史和信用卡交易等数据是不断增加的。此外,您可以查询的有限数量非常有限。这两个条件使Cassandra成为完美的解决方案。


    1
    有趣的事情是,来自英国的银行Monzo使用Cassandra作为他们的数据库。您能在您的回答中详细说明一下吗? - proximab
    1
    我已经更新了答案以回应您的评论。希望这回答了您的问题! - Deeksha Kaul

    10

    与正在部署Cassandra的人交谈时,我们发现它不能很好地处理多对多关系。他们正在进行一项非常规的工作来进行初步测试。我向一位Cassandra顾问请教此事,他表示如果你面临这个问题集,他不会推荐使用它。


    7
    你应该问自己以下问题:
    1. (容量、速度) 你是否需要写入和读取大量信息,以至于没有一台计算机能够处理写入的数据量?
    2. (全球性) 你是否需要在世界各地都能够使用这种写入和读取能力,以便世界某个地区的写入内容能够被另一个地区访问?
    3. (可靠性) 无论是在哪个云环境、哪个国家、虚拟机、容器还是裸机上,你是否需要这个数据库始终保持运行状态,永远不会崩溃?
    4. (可扩展性) 你是否需要这个数据库能够轻松地继续增长并实现线性扩展?
    5. (一致性) 你是否需要可调整的一致性,其中一些写入操作可以异步执行,而其他操作需要通过认证?
    6. (技能) 你是否愿意付出必要的努力来学习这种技术以及与创建全球分布式数据库所需的数据建模相关的知识,从而为每个人提供快速的服务体验?

    如果你对以上任何一个问题的回答是“可能”或“不”,那么你应该使用其他技术。如果你对所有问题的回答都是“当然”,那么你应该使用Cassandra。

    当你可以在一台设备上完成所有操作时,请使用关系型数据库管理系统。它可能比大多数技术更容易使用,任何人都可以使用它。


    4

    重单查询 vs. 亿万轻查询负载是需要考虑的另一个因素,除了其他答案。在 NoSql 风格的数据库中自动优化单个查询本质上更加困难。我使用过 MongoDB,在尝试计算复杂查询时遇到了性能问题。我没有使用过 Cassandra 但我认为它也会有同样的问题。

    另一方面,如果您的负载预计是非常多的小查询,并且您想要轻松扩展,则可以利用大多数 NoSql 数据库提供的最终一致性。请注意,最终一致性实际上不是非关系型数据模型的特性,但在基于 NoSql 的系统中更容易实现和设置。

    对于单个非常重的查询,任何现代 RDBMS 引擎都可以很好地并行化查询的部分,并利用您投入的所有 CPU 和内存(在单台机器上)。NoSql 数据库没有足够的关于数据结构的信息来使其能够做出假设,从而允许对大查询进行真正智能的并行化。它们确实允许您轻松扩展更多的服务器(或核心),但一旦查询达到一定的复杂度水平,您基本上被迫将其手动拆分为 NoSql 引擎知道如何智能处理的部分。

    在我的MongoDB使用经验中,由于查询的复杂性,MongoDB无法对其进行优化并在多个数据上运行部分查询。MongoDB可以并行处理多个查询,但不太擅长优化单个查询。

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接