Cassandra 中的数据甚至与仲裁配置也不一致



当我们有Quorum进行读写时,我在使用Hector和Cassandra时遇到了一致性问题。

我使用 MultigetSubSliceQuery 查询超级列限制大小 100 的行,然后读取它,然后删除它。然后开始另一个。

我发现上一个查询应该删除的行仍然显示在下一个查询中。

同样来自普通的列系列,我将一列的值从状态="FALSE"更新为状态="真",下次我查询它时,状态仍然是"FALSE"。

更多详情:

  1. 并非每次都发生(1/10,000)
  2. 两个查询之间的时间约为 500 毫秒(但我们发现一对查询之间经过了 2 秒,仍然表明存在一致性问题)
  3. 我们使用 ntp 作为我们的集群时间同步解决方案。
  4. 我们有 6 个节点,复制因子为 3

我知道 Cassandra 应该是"最终一致的",并且在 Cassandra 内部写入之前可能不会发生读取。但是两秒钟?!如果是这样,那么拥有仲裁或其他一致性级别配置不是毫无意义吗?

那么首先,这是Cassandra的正确行为吗,如果不是,我们需要分析哪些数据才能进一步投资?

用系统日志检查源代码后,我找到了不一致的根本原因。导致问题的三个因素:

  • 不同节点创建和更新相同的记录
  • 本地系统时间同步不够准确(尽管我们使用 NTP)
  • 一致性级别为法定人数

这是问题所在,以以下作为事件序列

 seqID   NodeA         NodeB          NodeC
 1.      New(.050)     New(.050)      New(.050)
 2.      Delete(.030)  Delete(.030)

第一个创建请求来自节点 C,本地时间戳为 00:00:00.050,假设请求首先记录在节点 A 和节点 B 中,然后与节点 C 同步。

然后删除来自本地时间戳为 00:00:00.030 的节点 A 的请求,并在节点 A 和节点 B 中记录。

读取请求来临时,Cassandra 会做版本冲突合并,但合并只取决于时间戳,所以虽然 Delete 发生在创建之后,但合并最终结果是"New",由于本地时间同步问题,它具有最新的时间戳。

我也遇到了类似的问题。出现此问题的原因是 cassandra 驱动程序默认使用服务器时间戳来检查哪个查询是最新的。但是,在最新版本的 cassandra 驱动程序中,他们已经对其进行了更改,现在默认情况下他们使用客户端时间戳。

我在这里描述了问题的细节

由于

分布式删除的工作方式,已删除的行可能显示为"范围重影":请参阅 http://wiki.apache.org/cassandra/FAQ#range_ghosts

如果您在CL_QUORUM读取写入单个列,那么无论时间间隔如何,您都应该始终获得完全一致性(前提是仍然遵守严格的排序,即您确定读取总是在写入之后)。如果你没有看到这个,那么在某个地方,有些东西是错误的。

首先,我建议 a) 验证客户端是否正确同步到 NTP,和/或通过以某种方式在客户端之间交叉检查时间重现问题,以及 b) 可能尝试重现CL_ALL问题。

另一个想法 - 您的客户端是与 NTP 同步,还是仅与 Cassandra 服务器节点同步?请记住,Cassandra 使用客户端时间戳来确定哪个值是最新的。

我的一个客户端/节点遇到了这个问题。我正在测试的其他 2 个客户端(以及其他 2 个节点)运行顺利。我有一个在所有读取和写入中使用 QUORUM 的测试,它很快就会失败。实际上,某些进程看不到其他进程的任何内容,而其他进程即使在我 QUORUM 删除数据后也可能始终看到数据。

就我而言,我打开了日志并打算使用 tail -F 命令测试这一壮举:

tail -F /var/lib/cassandra/log/system.log

看看我是否收到此处显示的一些错误。令我惊讶的是,尾进程本身返回了一个错误:

tail: inotify cannot be used, reverting to polling: Too many open files

从另一个线程,这意味着某些进程将无法打开文件。换句话说,Cassandra 节点可能无法按预期响应,因为它无法正确访问磁盘上的数据。

我不太确定这是否与发布问题的用户的问题有关,但 tail -F 肯定是确定是否达到文件限制的好方法。

(仅供参考,我在同一台机器上运行了 5 台相对较重的服务器,所以我对这一事实并不感到惊讶。我将不得不考虑增加 ulimit。如果我以这种方式修复它,我会再次在这里报告。

有关文件限制和 ulimit 命令行选项的详细信息:https://askubuntu.com/questions/181215/too-many-open-files-how-to-find-the-culprit

---------更新 1

以防万一,我首先使用 Oracle 的 Java 1.7.0-11 进行了测试(如下所述,我首先使用了 3,000 的限制,但没有成功!运行我的 Cassandra 测试时,同样的错误大约会同时弹出(另外,即使 ulimit 为 3,000,tail -F 错误仍然会出现......

---------更新2

好!这奏效了。我将 ulimit 更改为 32,768,问题消失了。请注意,我必须在 /etc/security/limits.conf 中扩大每用户限制并运行sudo sysctl -p,然后才能将最大值提高到如此高的数字。不知何故,即使旧限制只有 1024,3000 的默认上限也是不够的。

最新更新