Cassandra DB中的日期插入:非平凡的1h班次问题

时间:2014-04-15 09:49:58

标签: php .net date cassandra

我对这个问题有点绝望......我不知道如何面对它。

以下是查看此问题的更简单方法:

如果我的insert cql查询是:

  

“开始批量使用一致性插入到my_table(id,'2014-04-11 8:00:00',...,'2014-04-15 10:00:00')值('2036548' ,3.15,...,4.11)应用批次“

...我的数据请求cql查询是:

  

“选择FIRST 100000'2014-04-01 0:00:00'..'2014-04-16 0:00:00'来自my_table,其中id = 2036548”

...为什么插入日期 2014-04-15 10 :00:00 更改为 2014-04-15 11 < / strong>:00:00 从卡桑德拉拉出来的时候?

vb.net中提取代码的日期是:

Public Shared Function getCassandraDate(ByVal value As Byte()) As Date
    Dim buffer As Byte() = New Byte(value.Length - 1) {}
    value.CopyTo(buffer, 0)
    Array.Reverse(buffer)
    Dim ticks As Long = BitConverter.ToInt64(buffer, 0)
    Dim dateTime As New System.DateTime(1970, 1, 1, 0, 0, 0, _
         0)

    dateTime = dateTime.AddMilliseconds(ticks)
    Return dateTime.ToLocalTime
End Function

...... PHP中的相同内容:

date_default_timezone_set("Europe/Paris");
$time = $this->unpackDate($packed_time);
$str_time = date('Y-m-d H:i:s',$time); //TODO : to local time

private function unpackDate($data, $is_name=null)
{
    $arr = unpack('N2', $data);

    // If we are on a 32bit architecture we have to explicitly deal with
    // 64-bit twos-complement arithmetic since PHP wants to treat all ints
    // as signed and any int over 2^31 - 1 as a float
    if (PHP_INT_SIZE == 4) {

        $hi = $arr[1];
        $lo = $arr[2];
        $isNeg = $hi  < 0;

        // Check for a negative
        if ($isNeg) {
            $hi = ~$hi & (int)0xffffffff;
            $lo = ~$lo & (int)0xffffffff;

            if ($lo == (int)0xffffffff) {
                $hi++;
                $lo = 0;
            } else {
                $lo++;
            }
        }

        // Force 32bit words in excess of 2G to pe positive - we deal wigh sign
        // explicitly below

        if ($hi & (int)0x80000000) {
            $hi &= (int)0x7fffffff;
            $hi += 0x80000000;
        }

        if ($lo & (int)0x80000000) {
            $lo &= (int)0x7fffffff;
            $lo += 0x80000000;
        }

        $value = $hi * 4294967296 + $lo;

        if ($isNeg)
            $value = 0 - $value;

    } else {
        // Upcast negatives in LSB bit
        if ($arr[2] & 0x80000000)
            $arr[2] = $arr[2] & 0xffffffff;

        // Check for a negative
        if ($arr[1] & 0x80000000) {
            $arr[1] = $arr[1] & 0xffffffff;
            $arr[1] = $arr[1] ^ 0xffffffff;
            $arr[2] = $arr[2] ^ 0xffffffff;
            $value = 0 - $arr[1]*4294967296 - $arr[2] - 1;
        } else {
            $value = $arr[1]*4294967296 + $arr[2];
        }
    }
    return $value / 1e3;
}

更多详情

处理链:

(1)。通过.NET插入Cassandra

(2)。 Cassandra数据存储

(3)。从PHP或.NET中提取数据

问题:

至于今天,步骤(1)中 2014-04-15 10 :00:00 的日期将作为 2014-04出现步骤(3)中-15 11 :00:00

详细信息:

(关于此链中的日期格式)

(1)。 .NET当地时间(时区:“Europe / Paris”)。正在执行的插入cql:"BEGIN BATCH USING CONSISTENCY ONE insert into my_table(id,'2014-04-11 8:00:00',...,'2014-04-15 10:00:00') values ('2036548',3.15,...,4.11) APPLY BATCH"

(2)。 ???我不知道卡桑德拉在这做什么...... ???

(3)。用于提取数据的cql查询示例:"Select FIRST 100000 '2014-04-01 0:00:00'..'2014-04-16 0:00:00' from my_table where id=2036548"。在php:date_default_timezone_set("Europe/Paris"); $str_time = date('Y-m-d H:i:s',$time);。在.NET中:dateTime.ToLocalTime

额外信息:

我认为在几周前夏令时改变之前它运作良好。但我无法确定这一点。

如果在步骤(1)中,如果我在插入日期前将日期更改为UTC, 2014-04-15 10 :00:00 将成为 2014-04-15 08 :00:00 ,输出 2014-04-15 09 :00:00 < / em>,这仍然不正确。

我非常怀疑这里的诀窍是在步骤(1)和(2)之间,也就是说,我无法理解Cassandra如何处理日期。


EDIT1:

@Ananth的问题:

  

cassandra和客户端都运行在同一个数据中心吗?

这很复杂:

  • 从server1插入.NET,与server-cassandra(数据中心)不同的服务器。
  • PHP(用于提取数据)在server-cassandra上运行。
  • .NET(用于提取数据)在server1上运行,而不是在server-cassandra上运行。
  • PHP和.NET提取相同的结果。
  

你可以在这里发布你的架构吗?

这是

CREATE TABLE tsmeasures (
  id int PRIMARY KEY
) WITH
  comment='' AND
  comparator=timestamp AND
  read_repair_chance=0.100000 AND
  gc_grace_seconds=0 AND
  default_validation=double AND
  min_compaction_threshold=4 AND
  max_compaction_threshold=32 AND
  replicate_on_write='true' AND
  compaction_strategy_class='SizeTieredCompactionStrategy' AND
  compression_parameters:sstable_compression='SnappyCompressor';

EDIT2:

逐步测试后,结果如下:

  • 实际日期:2014-04-15 17:00:00(当地时间)
  • cql text:'2014-04-15 15:00:00'(UTC,通过.NET完成)
  • PHP Cassandra解压缩此日期=&gt; $ ticks = 1397577600(*)解包使用前面显示的代码完成

转换(通过http://www.epochconverter.com/

  • GMT:星期二,
  • 2014年4月15日16:00:00 GMT您所在的时区:2014/4/15 6:00:00 GMT + 2

这些结果对我没有意义......

更多详情:

cql insert:

  

“开始批量使用一致性插入tsmeasures(id,'2014-04-11 15:00:00',...,'2014-04-15 15:00:00')值('2036548' ,0,...,4.85)应用批次“

cql fetch:

  

“SELECT'2014-04-10 16:00:00'..'2014-04-20 17:00:00'FROM tsmeasures WHERE id IN   (2036548,2036479,2036174,650877)“

因此'2014-04-15 15:00:00'包含在获取范围内,我可以识别它,因为它是最高值。

我会继续挖掘......

1 个答案:

答案 0 :(得分:1)

这似乎是一个时区问题。在存储时和检索时间戳时,您似乎既没有指定时区。根据{{​​3}}如果客户端没有提供时区,Cassandra会应用协调器节点处理写请求的时区。如果时间戳在写入和读取之间切换,则可能意味着您的所有或部分Cassandra节点未配置为与客户端相同的时区。