Cassandra提交日志澄清

11
我已经阅读了几份有关Cassandra提交日志的文件,但对于这些“结构”我看到的信息存在冲突。图表显示当进行写操作时,Cassandra会将数据写入memtable和commit log。令人困惑的是,这个commit log存储在哪里。
我看到过很多次的图表显示commit log存储在磁盘上。但是,如果您继续阅读,他们还会谈论内存中的commit log缓冲区,并且该内存块每10秒钟被刷新到磁盘中。
DataStax文档指出: “当进行写操作时,Cassandra将数据存储在称为memtable的内存结构中,并通过在内存中追加写入来提供可配置的耐久性。此缓冲区每10秒钟刷新到磁盘。”
他们的图表中没有任何地方显示名为commit log buffer的内存结构。他们只显示commit log存储在磁盘上。
它还说明: “当发生写操作时,Cassandra将数据存储在内存中的结构memtable中,并将写操作附加到磁盘上的commit log中。”
因此,我对以上内容感到困惑。是将数据写入最终刷新到磁盘的commit log内存缓冲区(我认为也称为“commit log”),还是将数据写入memtable和commit log磁盘上?
Apache的文档指出: “Cassandra像其他现代系统一样,通过首先将写操作附加到commit log中来提供持久性。这意味着只有commitlog需要fsync,如果commitlog位于自己的卷上,则消除了寻址的需求,因为commitlog是仅追加的。实现详见ArchitectureCommitLog。”
Cassandra的默认配置将commitlog_sync模式设置为定期,导致在每个commitlog_sync_period_in_ms毫秒时同步commitlog,所以在此时间窗口内如果所有副本崩溃,您可能会丢失最多那么多数据。
从Apache声明中我推断出,由于写入的异步性质(缓存写入确认),只有在所有副本在刷新/同步之前崩溃时才会丢失数据(它甚至说明了您可以在commitlog被fsync之前丢失数据)。

我不确定从DataStax的文档和图表中能够推断出什么,因为他们提到了关于commit log的两个不同说法 - 一个在内存中,一个在磁盘上。

有人能否澄清这个我认为写得不好且存在冲突的文档?

我会假设存在一个commit log缓冲区,因为它们都引用了它(但DataStax在图表中没有显示)。如何管理以及何时管理它,我认为这是理解的关键。

1个回答

14

通常在解释写入路径时,提交日志被描述为一个文件 - 并且确实提交日志是提供持久性的磁盘存储机制。当深入讨论缓冲区高速缓存和必须发出fsync时,就会引入混乱。对“内存中的提交日志缓冲区”的引用是指操作系统缓冲区高速缓存,而不是Cassandra中的内存结构。您可以在代码中看到,并没有单独的内存结构用于提交日志,而是将变异序列化并写入支持文件的缓冲区

Cassandra带有两种管理提交日志上的fsync的策略。

commitlog_sync 
    (Default: periodic) The method that Cassandra uses to acknowledge writes in milliseconds:
    periodic: (Default: 10000 milliseconds [10 seconds])
    Used with commitlog_sync_period_in_ms to control how often the commit log is synchronized to disk. Periodic syncs are acknowledged immediately.

    batch: (Default: disabled)note
    Used with commitlog_sync_batch_window_in_ms (Default: 2 ms) to control how long Cassandra waits for other writes before performing a sync. When using this method, writes are not acknowledged until fsynced to disk.

periodic提供更好的性能,但可能会稍微增加数据丢失的风险。 batch设置保证了耐久性,但代价是延迟。


帮我理解写入发生时会发生什么。当Cassandra满足一致性时,比如2,它会确认写入。这是否意味着它已经被写入磁盘上的提交日志或内存中?换句话说,为了“保证”,您必须等待它被刷新(例如,默认为10000毫秒或10秒)吗?从我所读的内容来看,在内存同步之前,您有可能会丢失数据,在我们的例子中,最多可以丢失10秒钟的数据 - 但由于内存接收到数据(在满足一致性级别的所有副本上),因此确认很快。 - Jim Wartnick
4
为了得到确认,写入必须进入提交日志和内存表。为实现一致性级别2,此操作必须在2个节点上完成。你的问题似乎集中在于:什么是“进入提交日志”?默认情况下,这意味着写入已被发出到文件系统,但可能尚未同步到实际磁盘。如果您需要绝对的耐久性,则可以将commitlog_sync更改为批处理,代价是更高的延迟。 - Andrew Weaver
@AndrewWeaver 我有一个小疑问。你在上面的回答中提到数据有可能会丢失,我不太理解。如果我们在提交日志中有关于写入的信息,并且我们假设一个节点在从提交日志同步到实际磁盘之前崩溃了,那么当重新启动时,节点不会重放提交日志并恢复数据吗? - Vinay
1
@Vinay,你已经回答了自己的问题。如果一个节点在fsync之前崩溃,那么它实际上并没有存储在磁盘上。如果它不在磁盘上,节点就无法从提交日志中读取它。 - Andrew Weaver
对于未来的读者,这里有一些(旧的)参考资料。 - Dinei
请纠正我,但是在不进行fsync的情况下“附加到提交日志”和尚未附加到提交日志之间的区别似乎是人为且无关紧要的,只会导致混淆。如果我们关心的只是它是否耐用,那么fsync就是唯一重要的。这种区别有没有理由存在?也许是写入经过了所有应用逻辑而没有错误吗? - bhh1988

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