Cassandra - 写入不会失败,但不会插入值 [英] Cassandra - Write doesn't fail, but values aren't inserted

查看:423
本文介绍了Cassandra - 写入不会失败,但不会插入值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个3个Cassandra 2.0节点的集群。我的应用程序我写了一个测试,尝试写入和从Cassandra读取一些数据。一般来说这很好。

I have a cluster of 3 Cassandra 2.0 nodes. My application I wrote a test which tries to write and read some data into/from Cassandra. In general this works fine.

好奇的是,我重新启动我的电脑后,这个测试会失败,因为写入后,我读到我之前写的相同的值,我得到null而不是值,但写入时没有异常。
如果我手动截断使用的列族,测试将通过。之后,我可以执行这个测试多久我想要,它一遍又一遍。此外,如果Cassandra中有值或不存在没有关系。结果是alwalys是一样的。

The curiosity is that after I restarted my computer, this test will fail, because after writting I read the same value I´ve write before and there I get null instead of the value, but the was no exception while writing. If I manually truncate the used column family, the test will pass. After that I can execute this test how often I want, it passes again and again. Furthermore it doesn´t matter if there are values in the Cassandra or not. The result is alwalys the same.

如果我看看CLI和CQL shell有两个不同的意见:

If I look at the CLI and the CQL-shell there are two different views:

有没有人有一个想法是怎么回事?

Does anyone have an ideas what is going wrong? The timestamp in the CLI is updated after re-execution, so it seems to be a read-problem?

我的代码的一部分:
对于插入我尝试

A part of my code: For inserts I tried

Insert.Options insert =   QueryBuilder.insertInto(KEYSPACE_NAME,TABLENAME)
                .value(ID, id)
                .value(JAHR, zonedDateTime.getYear())
                .value(MONAT, zonedDateTime.getMonthValue())
                .value(ZEITPUNKT, date)
                .value(WERT, entry.getValue())
                .using(timestamp(System.nanoTime() / 1000));

Insert insert = QueryBuilder.insertInto(KEYSPACE_NAME,TABLENAME)
                .value(ID, id)
                .value(JAHR, zonedDateTime.getYear())
                .value(MONAT, zonedDateTime.getMonthValue())
                .value(ZEITPUNKT, date)
                .value(WERT, entry.getValue());

我的选择看起来像

Select.Where select = QueryBuilder.select(WERT)
            .from(KEYSPACE_NAME,TABLENAME)
            .where(eq(ID, id))
            .and(eq(JAHR, zonedDateTime.getYear()))
            .and(eq(MONAT, zonedDateTime.getMonthValue()))
            .and(eq(ZEITPUNKT, Date.from(instant)));

一致性级别是QUORUM(对于两者)和replicationfactor 3

Consistencylevel is QUORUM (for both) and replicationfactor 3

推荐答案

我想说这似乎是时间戳的问题,因为截断解决问题。在Cassandra最后写入胜利,这可能是由于使用System.nanoTime()因为

I'd say this seems to be a problem with timestamps since a truncate solves the problem. In Cassandra last write wins and this could be a problem caused by the use of System.nanoTime() since


引起的问题此方法只能使用以测量经过的时间,与系统或挂钟时间的任何其他概念无关。

This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time.

...

此方法返回的值只有在计算在Java虚拟机的同一实例内获得的两个这样的值之间的差异时才变得有意义。

The values returned by this method become meaningful only when the difference between two such values, obtained within the same instance of a Java virtual machine, is computed.

http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#nanoTime()

这意味着与重新启动后的写入相比,在重新启动之前发生的写入可能已在未来执行。这将不会导致查询失败,但由于有一个新值可用,写入的值将不可见。

This means that the write that occured before the restart could have been performed "in the future" compared to the write after the restart. This would not fail the query, but the written value would simply not be visible due to the fact that there is a "newer" value available.

您有要求对插入时间戳使用亚毫秒精度?如果可能,我建议使用System.currentTimeMillis(),而不是nanoTime()。

Do you have a requirement to use sub-millisecond precision for the insert timestamps? If possible I would recommend using System.currentTimeMillis() instead of nanoTime().

http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#currentTimeMillis ()

如果您有使用亚毫秒精度的要求,可以使用System.currentTimeMillis()与某种原子计数器范围在0-999之间,然后使用它作为时间戳。然而,如果多个客户端同时插入同一行,这将会中断。

If you have a requirement to use sub-millisecond precision it would be possible to use System.currentTimeMillis() with some kind of atomic counter that ranged between 0-999 and then use that as a timestamp. This would however break if multiple clients insert the same row at the same time.

这篇关于Cassandra - 写入不会失败,但不会插入值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆