当我们有Quorum进行读写时,我遇到了使用Hector和Cassandra的一致性问题 .
我使用MultigetSubSliceQuery从超级列限制大小100查询行,然后读取它,然后删除它 . 并开始另一个 .
我发现我之前的查询应该删除的行仍然显示在下一个查询中 .
而且从普通的列族中,我将一列的值从status ='FALSE'更新为status ='TRUE',下次我查询它时,状态仍为'FALSE' .
更多详情:
-
并非每次都发生过(1 / 10,000)
-
两次查询之间的时间约为500毫秒(但是我们发现一对查询,其间已经过了2秒,仍然表明存在一致性问题)
-
我们使用ntp作为我们的集群时间同步解决方案 .
-
我们有6个节点,复制因子是3
我知道Cassandra应该是“最终一致的”,并且在写入Cassandra之前可能不会发生这种情况 . 但是两秒钟?!如果是这样,那么拥有Quorum或其他一致性级别配置是否毫无意义?
首先,它是Cassandra的正确行为,如果不是,我们需要分析哪些数据才能进一步投资?
4 回答
在使用系统日志检查源代码后,我发现了不一致的根本原因 . 导致问题的因素有三个:
从 different nodes 创建并更新相同的记录
本地系统 time is not synchronized 足够准确(虽然我们使用NTP)
一致性等级为 QUORUM
这是问题,请将以下内容作为事件序列
第一个 Create 请求来自 Node C ,带有本地时间戳 00:00:00.050 ,假设请求首先记录在 Node A 和 Node B ,然后再与 Node C 同步 .
然后 Delete 请求来自 Node A ,带有本地时间戳 00:00:00.030 ,并记录在 node A 和 Node B 中 .
当 read 请求到来时,Cassandra会做版本冲突合并,但合并 only depend on time stamp ,所以虽然 Delete 发生在 Create 之后,但合并的最终结果是“ New ”,其中由于本地时间同步问题而具有最新时间戳 .
我也遇到过类似的问题 . 发生此问题是因为cassandra驱动程序默认使用服务器时间戳来检查哪个查询是最新的 . 但是在最新版本的cassandra驱动程序中,它们已对其进行了更改,现在默认情况下它们使用的是客户端时间戳 .
我已经描述了问题的细节here
由于分布式删除的工作方式,已删除的行可能会显示为"range ghosts":请参阅http://wiki.apache.org/cassandra/FAQ#range_ghosts
如果您正在CL_QUORUM上读取和写入各个列,那么无论时间间隔如何,您都应始终获得完全一致性(如果仍然遵守严格排序,即您确定读取始终在写入之后) . 如果你没有看到这个,那么在某个地方,某些东西是错误的 .
首先,我建议a)验证客户端是否正确地与NTP同步,和/或以某种方式在客户端之间交叉检查时重现问题,以及b)尝试用CL_ALL重现问题 .
另一个想法 - 您的客户端是与NTP同步还是只与Cassandra服务器节点同步?请记住,Cassandra使用客户端时间戳来确定哪个值是最新的 .
我正在使用我的一个客户端/节点遇到此问题 . 我正在测试的其他2个客户端(以及其他2个节点)运行顺畅 . 我有一个测试,在所有读取和所有写入中使用QUORUM,它很快就会失败 . 实际上有些进程看不到其他进程,而其他进程可能总是看到数据,即使我在QUORUM中删除它 .
在我的情况下,我打开日志并打算使用tail -F命令测试该专长:
看看我是否收到了一些错误 . 令我惊讶的是尾部进程本身返回了一个错误:
从另一个线程,这意味着某些进程将无法打开文件 . 换句话说,Cassandra节点可能没有按预期响应,因为它无法正确访问磁盘上的数据 .
我不太确定这是否与发布问题的用户的问题有关,但是尾部-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进行测试(如下所述,我首先使用了3000的限制而没有成功!)运行我的Cassandra测试时,同样的错误会弹出同样的错误(甚至在ulimit为3,000的情况下,尾部会出现-F错误......)
---------更新2
好的!那很有效 . 我将ulimit更改为32,768,问题就消失了 . 请注意,我必须在
/etc/security/limits.conf
中放大每用户限制并运行sudo sysctl -p
才能将最大值提高到如此高的数字 . 不知何故,默认的上限3000是不够的,即使旧的限制只有1024 .