2009-10-01 95 views
60

有什么要避免的陷阱?你们有没有什么优惠?例如,我听说导出/导入Cassandra数据非常困难,这让我想知道是否会妨碍将生产数据同步到开发环境。设计Cassandra数据模型的最佳实践是什么?

顺便说一句,在Cassandra上很难找到好的教程,我唯一拥有的http://arin.me/code/wtf-is-a-supercolumn-cassandra-data-model仍然是非常基础的。

谢谢。

+0

我建议你在Cassandra中获得关于数据建模的更多信息。我已阅读http://www.cs.wayne.edu/andrey/papers/TR-BIGDATA-05-2015-CKL.pdf和http://www.datastax.com/dev/blog/basic-rules- of-cassandra-data-modeling作为这种情况下有用的文章。它们将帮助您了解如何根据查询(查询驱动的方法)和数据重复及其优点/缺点对表进行建模。 – Elnaz 2016-03-05 08:46:16

回答

41

对我来说,最主要的是决定是否使用OrderedPartitioner或RandomPartitioner。

如果使用RandomPartitioner,范围扫描是不可能的。这意味着你必须知道任何活动的确切关键,包括清理旧数据。

所以如果你有很多流失,除非你有一些神奇的方式来确切地知道你已经插入了什么东西,使用随机分区器,你可以很容易地“丢失”东西,这会导致磁盘空间泄漏并最终会消耗所有存储空间。

另一方面,您可以询问有序分区器“我在A和B之间的列族X中具有哪些键”? - 它会告诉你。你可以清理它们。

但是,它也有缺点。由于Cassandra不会自动进行负载均衡,所以如果使用有序分区器,则很可能所有数据都将以一个或两个节点结束,而其他所有数据都不会结束,这意味着您将浪费资源。

我对此没有任何简单的回答,除非您可以在某些情况下通过在开始时放置一个较短的散列值(您可以从其他数据源轻松枚举的东西)获得“两全其美”你的密钥 - 例如用户ID的16位十六进制散列 - 它会给你4个十六进制数字,然后是你真正想使用的密钥。

然后,如果你有一个最近删除的用户列表,你可以散列他们的ID和范围扫描清理任何与他们有关的东西。

下一个棘手的问题是二级索引 - Cassandra没有 - 所以如果你需要用Y查找X,你需要在两个键下插入数据,或者有一个指针。同样,这些指针可能需要在它们指向的东西不存在时进行清理,但在此基础上没有简单的查询方法,所以您的应用程序需要记住。

应用程序错误可能会遗留已遗忘的孤立键,除非您编写一些定期扫描db中每个键的垃圾回收器,否则无法轻松检测它们需要一段时间 - 但你可以做一些块)来检查那些不再需要的。

这些都不是基于真实的用法,而是我在研究过程中发现的。我们不在生产中使用Cassandra。

编辑:Cassandra现在在主干中有二级索引。

+0

非常丰富,非常感谢。 – Jerry 2009-10-03 12:53:13

+1

我认为上面提出的'自动负载平衡'问题是足够重要的,以保证自己的线程...我开始在http://stackoverflow.com/questions/1767789/cassandra-load-balancing 谢谢 – deepblue 2009-11-20 01:36:58

+0

0.5做半自动负载平衡。 (“半”意味着运营商必须要求它,但Cassandra负责处理剩下的事情。)0.5 beta2上周发布,RC即将推出。 – jbellis 2009-12-17 15:00:13

7

是否有任何交易中断? 不一定处理断路器,但东西是

  1. 客户端连接到最近的节点,解决这个问题应该事先知道知道,与其他所有卡桑德拉的所有通信节点通过其代理。 a。读/写流量不是均匀分布在节点之间 - 某些节点的代理数据比他们自己承载的数据多 b。如果节点出现故障,客户端无奈,无法读取,无法写入集群中的任何地方。

  2. 虽然卡桑德拉声称“写作永不失败”,但他们确实失败了,至少在他们说话的那一刻。如果目标数据节点变得缓慢,请求超时并写入失败。节点没有响应的原因很多:垃圾收集器启动,压缩过程,无论什么... 在所有这些情况下,所有写入/读取请求均失败。在传统的数据库中,这些请求会变得相当缓慢,但是在卡桑德拉他们只是失败了。

  3. 还有就是多让,但没有多删除和一个不能截断的ColumnFamily要么

  4. 如果一个新的空数据输入节点从一个邻居节点集群,数据的一部分钥匙圈将仅被转移。这导致数据分布不均匀和负载不均匀。你可以通过加倍节点数来修复它。一个人也应该手动跟踪令牌并明智地选择它们。

17

这是太久添加为注释,这样从清理一些误解的列表中,回答问题:

  1. 任何客户端可以连接到任何节点;如果您选择的第一个节点(或通过负载平衡器连接到的节点)关闭,则只需连接到另一个节点即可。另外,一个“胖客户端”api可用于客户可以指导自己的写操作;一个例子是http://wiki.apache.org/cassandra/ClientExamples

  2. 当服务器没有响应而不是无限期地挂起时,定时出现了大多数处理过载rdbms系统的人所希望的功能。 Cassandra RPC超时是可配置的;如果你愿意,你可以自由设置它几天,而无限期地处理挂起。 :)

  3. 确实没有多重删除或截断支持,但在审查中有这些补丁。

  4. 在集群节点间保持负载平衡显然存在一个折衷:您尝试保留事物的平衡性越好,您将执行的数据移动越多,这不是免费的。默认情况下,Cassandra集群中的新节点将移动到令牌环中的最佳位置以最小化不均匀性。在实践中,这已被证明是行之有效的,而且你的群集越大,加倍是最佳的真实情况就越少。这是覆盖更http://wiki.apache.org/cassandra/Operations

5

我认为这值得一更新,因为卡桑德拉1.2最近出来了。

在过去的18个月里,我一直在使用Cassandra进行社交游戏。

我的是,你必须使用卡桑德拉的优势。因此,要充分了解它是什么以及如何执行,有必要查看要使用哪种数据模型,甚至需要确定另一个数据库解决方案是否对您更有用。

OrderedPartitioner是有益的,只有您的应用程序依赖于键范围的查询,但你放弃的卡桑德拉的最强大的功能为一个:自动分片和负载平衡。而不是行键范围查询尝试使用同一行中的列名称范围实现相同的功能。 TL; DR读取/写入不会在使用此节点的节点之间进行平衡。

RandomPartioner(MD5哈希)和MurmurPartitioner(杂音哈希,更好,更快的)是,如果你想支持大数据和高访问频率你必须要走的路。你放弃的唯一的事情就是关键的范围查询。同一行中的所有内容仍位于集群中的同一节点上,您可以在这些节点上使用比较器和列名称范围查询。 TL; DR:将此用于正确平衡,您将放弃没有重大的事情。


事情你应该知道卡桑德拉:

卡桑德拉是最终一致。 Cassandra选择交换一致性以实现高可用性和出色的分区(http://en.wikipedia.org/wiki/CAP_theorem)。但是你可以从cassandra获得一致性,当你读写它时,所有关于你的一致性策略都是关于你的。在讨论使用cassandra时,这是一个相当重要和复杂的话题,但您可以在这里详细阅读http://www.datastax.com/docs/1.2/dml/data_consistency。作为一个经验法则(并保持简单),我在QUORUM ConsistencyLevel中读写(因为在我的应用程序中,读取的频率与写入频率相同)。如果您的应用程序非常繁重并且读取次数少得多,那么请使用ONE写入并在ALL处读取。或者,如果你的用例是相反的(写入次数比读取次数少得多),那么你可以尝试阅读ONE并写在ALL上。 如果一致性是您正在尝试解决的问题,那么使用ANY作为写入的一致性级别并不是一个好主意,因为它确保突变已经到达集群,但并不是它已被写入任何地方。这是我得到写入的唯一情况,在cassandra上默默无闻。

这些简单的规则使cassandra开发变得简单易行。为了从生产集群中获得尽可能多的一致性和性能,您应该努力研究这个主题并且自己真正理解它。

如果你需要一个具有复杂关系的实体(表)的人类可读的数据模型,那么我认为卡桑德拉不适合你。 MySQL和NewSQL可能对你的用例更有帮助。

要知道的一件好事就是,cassandra大概是如何保存和读取数据的。无论您何时写入(删除实际上是在cassandra中写入“墓碑”值),系统都会将新值和时间戳记放入新的物理位置。

当您阅读时,cassandra会尝试为某个键/列名称位置提取所有的写入,并返回最近他能找到的最新时间戳记(由客户端提供的时间戳记)。所以节点所需的内存直接取决于写入的频率。 cassandra有一个压缩过程,负责清理旧的突变。 Cassandra有一个内部缓存,在读取时更新位置的最新值。

读取会引起SSTables(持久数据的数据结构)磁盘上的合并/压缩,但最好不要指望它。清除墓碑和过期列(使用生存时间功能)是由垃圾收集器管理的另一种机制(有关更多详细信息,请参阅GC宽限期设置)。


这使我想到最后一点:确保您的写入和读取将在您的群集中保持平衡!

我们假设您的所有用户都需要非常频繁地更新一个位置。
不要将理论上的单个位置映射到只有一个行键!这将使您的所有写入只落在群集中的一个节点上。如果它不能带来一切(因为你有Rockstar系统),它至少会严重削弱集群的性能。
我的建议是用足够的不同行键存储您的写入操作,以便在群集中的所有节点上分配您的写入操作。要检索单个理论位置的所有数据,请在所有“子行键”上使用multi_get。

例如:
我想有一个所有活动http会话(其中有uuid分配给他们)的列表。 不要全部保存到一个“会话”行键中。我用作包含6个节点的cassandra集群的行密钥是: _sessions。 然后,我有一个小16键multi_get来检索所有活动会话,或者我仍然可以通过仅使用一个简单的get(如果我知道它的uuid当然)来确定会话是否处于活动状态。 如果您的群集更大,您可能需要使用散列函数来生成存储桶密钥。