【发布时间】:2015-02-11 04:30:22
【问题描述】:
我在 Cassandra 中有一个表,我在其中填充了一些包含 1000 条条目的行(每行包含 10000 多列)。行中的条目非常频繁地更新,基本上只是用不同的值更新了一个字段(它是一个整数)。列的所有其他值保持不变。我的问题是,更新会就地完成吗? Cassandra 在频繁更新条目方面有多好?
【问题讨论】:
标签: cassandra cassandra-2.0 cassandra-cli nosql
我在 Cassandra 中有一个表,我在其中填充了一些包含 1000 条条目的行(每行包含 10000 多列)。行中的条目非常频繁地更新,基本上只是用不同的值更新了一个字段(它是一个整数)。列的所有其他值保持不变。我的问题是,更新会就地完成吗? Cassandra 在频繁更新条目方面有多好?
【问题讨论】:
标签: cassandra cassandra-2.0 cassandra-cli nosql
最初,这些更新存储在称为 Memtable 的内存数据结构中。 Memtables 会定期刷新到不可变的 SSTables。
因此将从各种 SSTable 中读取单个宽行。在称为“压缩”的过程中,不同的 SSTable 将被合并到磁盘上更大的 SSTable。
提高刷新 Memtables 的阈值是一种优化方式。如果在 Memtable 刷新到磁盘之前更新非常快,我认为更新应该就地在内存中,但不确定。
同样每个读操作都会先检查 Memtables,如果数据还在,它会被简单地返回——这是最快的访问。
卡桑德拉read path:
When a read request for a row comes in to a node, the row must be combined from all SSTables on that node that contain columns from the row in question
卡桑德拉write path:
【讨论】:
首先,每次更新也是 cassandra 的顺序写入,因此,就 cassandra 而言,无论您是更新还是写入,它对 cassandra 没有任何影响。
真正的问题是您需要多快才能读取这些写入内容才能读取?正如@john 建议的那样,首先将所有写入写入驻留在内存中的可变 CQL Memtable。因此,对于特定 CQL 表,每个更新本质上都作为新的顺序条目附加到 memtable 中。为了持久性,它也会定期同时写入“commitlog”(每 10 秒)。
当 Memtable 已满或达到 comittlog 的总大小时,cassandra 会将所有数据刷新到不可变的排序字符串表 (SSTable)。在刷新之后,压缩是保留新列值的所有 PK 条目并删除所有先前值(更新之前)的过程。
频繁刷新会带来频繁顺序写入磁盘和压缩的开销,这可能会占用大量 I/O 并对 cassandra 性能产生严重影响。
就读取而言,首先 cassandra 将尝试从 row cache(如果已启用)或 memtable 读取。如果它在那里失败,它将按顺序转到bloom filter、key cache、partition summary、partition index,最后转到 SSTable。当为所有列值收集数据时,其在内存中的聚合和具有最新时间戳的列值在聚合后返回给客户端,并在row cache 中为该分区键创建一个条目。
所以,是的,当您查询分区键时,它将扫描所有 SSTable 以查找该特定 CQL 表,并扫描 memtable 以查找所有尚未刷新到磁盘的列值。
【讨论】:
不,无法就地更新。
正如@john 建议的那样,如果您经常写入,那么您应该延迟刷新过程。在刷新期间,对存储在 MemTable 中的同一分区的多次写入将作为单个分区写入新创建的 SSTable 中。
C* 适合大量写入。但是,您需要监控每次读取访问的 SSTable 数量。如果 # 太高,那么您需要检查您的压缩策略。
【讨论】: