什么是设计Cassandra数据模型的最佳实践?

时间:2009-10-01 08:51:16

标签: database-design nosql cassandra

要避免哪些陷阱?你有什么优惠吗?例如,我听说出口/导入Cassandra数据非常困难,让我想知道这是否会妨碍生产数据与开发环境的同步。

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

感谢。

5 个答案:

答案 0 :(得分:41)

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

如果使用RandomPartitioner,则无法进行范围扫描。这意味着您必须知道任何活动的确切密钥,包括清理旧数据。

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

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

然而,也存在不利因素。由于Cassandra不进行自动负载平衡,如果您使用有序分区程序,很可能所有数据最终只会在一个或两个节点中,而在其他节点中则不会,这意味着您将浪费资源。

我没有任何简单的答案,除非你在某些情况下通过在你的开头放一个简短的哈希值(你可以很容易地从其他数据源枚举的东西)得到“两全其美”。密钥 - 例如用户ID的16位十六进制哈希 - 它将为您提供4个十六进制数字,然后是您真正想要使用的密钥。

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

下一个棘手的位是二级索引 - Cassandra没有 - 所以如果你需要在Y上查找X,你需要在两个键下插入数据,或者有一个指针。同样,当他们指向的东西不存在时,可能需要清理这些指针,但在此基础上查询内容并不容易,因此您的应用需要Just Remember。

应用程序错误可能会留下您忘记的孤立密钥,除非您编写一些定期扫描数据库中每个密钥的垃圾收集器,否则您无法轻易检测到它们(这将需要一段时间 - 但你可以用大块的方式来检查那些不再需要的东西。

这些都不是基于实际用法,而是我在研究过程中想到的。我们不会在生产中使用Cassandra。

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

答案 1 :(得分:17)

这太长了,无法添加评论,所以要清除问题列表回复中的一些误解:

  1. 任何客户端都可以连接到任何节点;如果您选择的第一个节点(或通过负载均衡器连接)发生故障,只需连接到另一个节点即可。此外,客户端可以自行指导写入“胖客户端”API。一个例子是http://wiki.apache.org/cassandra/ClientExamples

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

  3. 确实没有多重删除或截断支持,但在审核中有两个补丁。

  4. 显然需要在保持群集节点之间的负载平衡方面进行权衡:您尝试保留的内容越平衡,您将执行的数据移动越多,这是不自由的。默认情况下,Cassandra集群中的新节点将移动到令牌环中的最佳位置,以最大限度地减少不均匀性。实际上,这已被证明效果很好,你的群集越大,加倍就越不正确。 http://wiki.apache.org/cassandra/Operations

  5. 中详细介绍了这一点

答案 2 :(得分:7)

答案 3 :(得分:7)

  

你有什么优惠吗?   不一定是交易破坏者,而是需要注意的事情

  1. 客户端连接到最近的节点,该节点应事先知道该地址,与通过它代理的所有其他Cassandra节点的所有通信。 一个。读/写流量不是均匀分布在节点之间 - 一些节点代理的数据多于它们自己托管的数据 湾如果节点发生故障,客户端无能为力,无法读取,无法在群集中的任何位置写入。

  2. 虽然Cassandra声称“写作永不失败”,但他们确实失败了,至少在他们发言的那一刻。如果目标数据节点变得迟缓,请求超时并且写入失败。节点变得无法响应有很多原因:垃圾收集器启动,压缩过程,无论什么...... 在所有这些情况下,所有写/读请求都会失败。在传统的数据库中,这些请求会成比例地变慢,但在Cassandra中它们就会失败。

  3. 有多次获取,但没有多次删除,也无法截断ColumnFamily

  4. 如果新的空数据节点进入群集,则只会传输来自密钥环上一个邻居节点的数据部分。这导致数据分布不均匀和负载不均匀。您可以通过总是加倍节点数来修复它。还应该手动跟踪令牌并明智地选择它们。

答案 4 :(得分:5)

我认为自从Cassandra 1.2最近推出以来,这值得更新。

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

我虽然是你必须使用Cassandra的优势。因此,有必要了解使用哪种数据模型以及如何使用,甚至确定另一种数据库解决方案是否对您更有用。

仅当您的应用程序依赖于键范围查询时,

OrderedPartitioner 才有用,但是您放弃了Cassandra最强大的功能之一:自动分片和负载平衡。而不是行键范围查询尝试使用同一行中的列名称范围来实现所需的相同功能。 TL; DR 读/写将不会在使用此节点的节点之间进行平衡。

如果您想支持大数据和高访问频率,

RandomPartioner (md5哈希)和 MurmurPartitioner (Murmur哈希,更好,更快)是您必须采用的方式。你唯一放弃的是关键范围查询。同一行中的所有内容仍然位于群集中的同一节点上,您可以对这些节点使用比较器和列名称范围查询。 TL; DR :使用这个进行正确的平衡,你将不会放弃任何专业。


你应该了解的关于cassandra的事情:

Cassandra通常是一致的。 Cassandra选择交换Consistency以获得高可用性和出色的分区(http://en.wikipedia.org/wiki/CAP_theorem)。但是你可以从cassandra获得一致性,当你读写它时,它就是你的一致性政策。在讨论使用cassandra时,这是一个非常重要且复杂的主题,但您可以在此处详细阅读http://www.datastax.com/docs/1.2/dml/data_consistency

根据经验(并保持简单)我在QUORUM ConsistencyLevel上读写(因为在我的应用程序中,读取的频率与写入的顺序相同)。如果您的应用程序写得非常繁重,并且读取的次数少得多,那么请使用“在ONE写入”并在“全部”读取。或者,如果您的用例相反(写入比读取的频率低很多),那么您可以尝试在ONE上读取并在ALL上写入。 如果一致性是您要解决的问题,那么使用ANY作为写入的一致性级别并不是一个好主意,因为它可以保证突变已经到达集群但不是已经写入任何地方。这是我在cassandra上静默失败的唯一一种情况。

这些是简单的规则,可以让您轻松开始使用cassandra。为了从生产集群中获得尽可能多的一致性和性能,您应该努力学习这个主题,并且自己真正理解它。

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

要知道的一件好事是,cassandra大致如何保存和读取数据。无论何时你写(删除实际上写的"墓碑" cassandra中的值),系统都会将新值及其时间戳放在一个新的物理位置。

当你阅读时,cassandra会尝试为某个key / column_name位置提取所有写入内容,并返回他能找到的最新内容(具有最高时间戳的那个,由客户端提供)。因此,节点所需的存储器直接取决于写入的频率。 cassandra中有一个压缩过程,负责清理旧的突变。 Cassandra有一个内部缓存,使用最新的位置值读取更新。

SSTables磁盘上的合并/压缩(持久存储数据的数据结构)可以通过读取来激发,但最好不要指望它。清除逻辑删除和过期列(使用生存时间功能)是由垃圾收集器管理的不同机制(有关详细信息,请参阅GC宽限时间设置)。


这让我想到了我想要做的最后一点:确保你的集群中的写入和读取都是平衡的!

我们假设您的所有用户都需要经常更新单个位置 不要将理论上的单个位置映射到只有一个行键!这将使您的所有写入仅落在群集中的一个节点上。如果它没有降低一切(因为你有摇滚明星系统),它至少会严重削弱集群的性能。
我的建议是将您的写入存储在足够多的不同行键中,您将在集群中的所有节点上分配写入。要检索该单个理论位置的所有数据,请在所有"子行键"上使用multi_get。

示例:
我希望有一个所有活动的http会话列表(已分配给它们的uuid)。 不要将所有内容保存到一个"会话"行键。我用作6个节点的cassandra集群的行密钥是: _sessions。 然后我有一个小的16键multi_get来检索所有活动的会话,或者我仍然可以通过使用一个简单的get来判断会话是否处于活动状态(如果我知道它的uuid当然)。 如果您的群集更大,您可能希望使用哈希函数来生成存储桶密钥。