【问题标题】:What's The Best Practice In Designing A Cassandra Data Model? [closed]设计 Cassandra 数据模型的最佳实践是什么? [关闭]
【发布时间】:2015-08-05 05:44:23
【问题描述】:

还有哪些需要避免的陷阱?您是否有任何交易中断?例如,我听说导出/导入 Cassandra 数据非常困难,这让我想知道这是否会妨碍将生产数据同步到开发环境。

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

谢谢。

【问题讨论】:

标签: database-design nosql cassandra


【解决方案1】:

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

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

因此,如果您有很多流失,除非您有某种神奇的方法可以准确地知道您为哪些键插入了东西,否则使用随机分区器很容易“丢失”东西,从而导致磁盘空间泄漏并最终会消耗所有存储空间。

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

但是,也有不利的一面。由于 Cassandra 不进行自动负载平衡,如果您使用有序分区器,那么您的所有数据很可能最终只会在一两个节点中,而在其他节点中则没有,这意味着您会浪费资源。

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

然后,如果您有一个最近删除的用户列表,您只需散列他们的 ID 并进行范围扫描以清理与他们相关的任何内容。

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

并且应用程序错误可能会留下您忘记的孤立键,并且您将无法轻松检测它们,除非您编写一些垃圾收集器定期扫描数据库中的每个键(这将需要一段时间 - 但你可以分块进行)以检查不再需要的部分。

这些都不是基于实际使用,只是我在研究过程中发现的。我们不在生产环境中使用 Cassandra。

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

【讨论】:

  • 内容丰富,非常感谢。
  • 我认为上面提出的“自动负载平衡”问题非常重要,足以保证它自己的线程......我从stackoverflow.com/questions/1767789/cassandra-load-balancing开始感谢
  • 0.5 确实做了半自动负载平衡。 (“semi”表示运营商必须提出请求,但随后 Cassandra 会负责其余的工作。)上周发布了 0.5 beta2,RC 即将推出。
  • "导致磁盘空间泄漏" IIRC,Cassandra数据有一个TTL字段,可用于自动删除过期数据。
  • 自从我最初写这篇文章以来,Cassandra 有了许多新功能。但是,如果您不设置 TTL 字段,它不会阻止磁盘空间泄漏。有些数据需要永久保存,所以如果您忘记删除它们,就会发生泄漏。
【解决方案2】:

这太长了,不能作为评论添加,所以要澄清问题列表回复中的一些误解:

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

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

  3. 确实目前还没有多重删除或截断支持,但目前正在审查这两个方面的补丁。

  4. 显然要在集群节点之间保持负载平衡:您尝试保持的平衡越完美,您将进行的数据移动就越多,这不是免费的。默认情况下,Cassandra 集群中的新节点将移动到令牌环中的最佳位置,以最大限度地减少不均匀性。在实践中,这已被证明效果很好,并且集群越大,加倍最优的说法就越不真实。这在http://wiki.apache.org/cassandra/Operations

  5. 中有更多介绍

【讨论】:

    【解决方案3】:

    您有任何交易中断吗? 不一定是交易破坏者,但需要注意的事情

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

    2. 尽管 Cassandra 声称“写入永远不会失败”,但它们确实会失败,至少在说话的那一刻确实如此。如果目标数据节点变得迟缓,请求超时并且写入失败。节点变得无响应的原因有很多:垃圾收集器启动、压缩过程等等…… 在所有这些情况下,所有写/读请求都会失败。在传统数据库中,这些请求会相应地变慢,但在 Cassandra 中它们会失败。

    3. 有multi-get但没有multi-delete,也不能截断ColumnFamily

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

    【讨论】:

      【解决方案4】:
      【解决方案5】:

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

      在过去的 18 个月里,我一直在生产中使用 Cassandra 来开发社交游戏。

      我认为您必须使用 Cassandra 才能发挥其优势。因此,有必要很好地了解它的作用和作用,了解要使用哪种数据模型,甚至确定另一个数据库解决方案是否对您更有用。

      OrderedPartitioner 仅在您的应用程序依赖键范围查询时才有用,但您为此放弃了 Cassandra 最强大的功能之一:自动分片和负载平衡。代替行键范围查询尝试使用同一行中的列名范围来实现您需要的相同功能。 TL;DR 使用它的节点之间不会平衡读/写。

      RandomPartioner(md5 散列)和 MurmurPartitioner(Murmur 散列,更好更快)是支持大数据和高访问频率的必经之路.您唯一放弃的是键范围查询。同一行中的所有内容仍位于集群中的同一节点上,您可以在这些节点上使用比较器和列名范围查询。 TL;DR : 使用它来进行适当的平衡,你不会放弃任何重大的东西。


      你应该知道的关于 cassandra 的事情:

      Cassandra 最终是一致的。 Cassandra 选择用一致性换取高可用性和出色的分区 (http://en.wikipedia.org/wiki/CAP_theorem)。但是您可以从 cassandra 获得一致性,这完全取决于您在读取和写入时的一致性策略。在谈论使用 cassandra 时,这是一个非常重要且复杂的话题,但您可以在此处详细了解它 http://www.datastax.com/docs/1.2/dml/data_consistency

      根据经验(并为简单起见),我在 QUORUM ConsistencyLevel 读写(因为在我的应用程序中,读取的频率往往与写入的频率顺序相同)。如果您的应用程序的写入量很大并且读取发生的频率要低得多,那么请使用 write at ONE 并 read at ALL。或者,如果您的用例相反(写入频率远低于读取频率),那么您可以尝试在 ONE 上读取并在 ALL 上写入。 如果一致性是您要解决的问题,那么使用 ANY 作为写入的一致性级别并不是一个好主意,因为它保证了突变已经到达集群,但不能保证它已经被写入任何地方。这是我在 cassandra 上获得写入静默失败的唯一情况。

      这些都是简单的规则,可以让您轻松开始 cassandra 开发。要从生产集群中获得尽可能高的一致性和性能,您应该认真研究这个主题并真正理解它。

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

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

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

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


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

      假设您的所有用户都需要非常频繁地更新一个位置。
      不要仅将理论上的单个位置映射到一个行键!这将使您的所有写入仅落在集群中的一个节点上。如果它不能让一切都崩溃(因为你有摇滚明星管理员),它至少会严重削弱集群的性能。
      我的建议是将您的写入存储在足够多的不同行键中,以便您将写入分布在集群中的所有节点上。要检索该单个理论位置的所有数据,请在所有“子行键”上使用 multi_get。

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

      【讨论】:

        猜你喜欢
        • 2010-09-18
        • 2010-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多