驱动程序升级后,Cassandra列元数据显示“DateType”而不是“timestamp”

时间:2017-07-18 19:51:26

标签: cassandra datastax datastax-java-driver

我有一些Java代码可以对Cassandra表的模式进行内省。升级Cassandra驱动程序依赖项后,此代码不再按预期工作。使用旧驱动程序版本时,timestamp列的类型已从ColumnMetadata#getType()返回为DataType.Name#TIMESTAMP。使用新驱动程序,同一个调用将返回DataType.Name#CUSTOMCustomType#getCustomTypeClassName返回org.apache.cassandra.db.marshal.DateType

旧驱动程序版本为com.datastax.cassandra:cassandra-driver-core:2.1.9

<dependency>
    <groupId>com.datastax.cassandra</groupId>
    <artifactId>cassandra-driver-core</artifactId>
    <version>2.1.9</version>
</dependency>

新驱动程序版本为com.datastax.cassandra:dse-driver:1.1.2

<dependency>
    <groupId>com.datastax.cassandra</groupId>
    <artifactId>dse-driver</artifactId>
    <version>1.1.2</version>
</dependency>

群集版本是DataStax Enterprise 2.1.11.969:

cqlsh> SELECT release_version FROM system.local;

 release_version
-----------------
      2.1.11.969

为了说明问题,我创建了一个简单的控制台应用程序,用于打印指定表的列元数据。 (见下文。)使用旧驱动程序构建时,输出如下所示:

# old driver
mvn -Pcassandra-driver clean package
java -jar target/cassandra-print-column-metadata-cassandra-driver.jar <address> <user> <password> <keyspace> <table>
...
ts timestamp
...

使用新驱动程序构建时,输出如下所示:

# new driver
mvn -Pdse-driver clean package
java -jar target/cassandra-print-column-metadata-dse-driver.jar <address> <user> <password> <keyspace> <table>
...
ts 'org.apache.cassandra.db.marshal.DateType'
...

到目前为止,我只在timestamp列中遇到过这个问题。我还没有看到任何其他数据类型,尽管我的架构并没有详尽地使用所有支持的数据类型。

DESCRIBE TABLE表示该列为timestampsystem.schema_columns表明validatororg.apache.cassandra.db.marshal.DateType

[cqlsh 3.1.7 | Cassandra 2.1.11.969 | CQL spec 3.0.0 | Thrift protocol 19.39.0]

cqlsh:my_keyspace> DESCRIBE TABLE my_table;

CREATE TABLE my_table (
  prim_addr text,
  ch text,
  received_on timestamp,
  ...
  PRIMARY KEY (prim_addr, ch, received_on)
) WITH
  bloom_filter_fp_chance=0.100000 AND
  caching='{"keys":"ALL", "rows_per_partition":"NONE"}' AND
  comment='emm_ks' AND
  dclocal_read_repair_chance=0.000000 AND
  gc_grace_seconds=864000 AND
  read_repair_chance=0.100000 AND
  compaction={'sstable_size_in_mb': '160', 'class': 'LeveledCompactionStrategy'} AND
  compression={'sstable_compression': 'SnappyCompressor'};

cqlsh:system> SELECT * FROM system.schema_columns WHERE keyspace_name = 'my_keyspace' AND columnfamily_name = 'my_table' AND column_name IN ('prim_addr', 'ch', 'received_on');

 keyspace_name | columnfamily_name | column_name | component_index | index_name | index_options | index_type | type           | validator
---------------+-------------------+-------------+-----------------+------------+---------------+------------+----------------+------------------------------------------
     my_keyspace |  my_table |          ch |               0 |       null |          null |       null | clustering_key | org.apache.cassandra.db.marshal.UTF8Type
     my_keyspace |  my_table |   prim_addr |            null |       null |          null |       null |  partition_key | org.apache.cassandra.db.marshal.UTF8Type
     my_keyspace |  my_table | received_on |               1 |       null |          null |       null | clustering_key | org.apache.cassandra.db.marshal.DateType

这是驱动程序中的错误,行为的故意改变,还是我的某种错误配置?

的pom.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>cnauroth</groupId>
    <artifactId>cassandra-print-column-metadata</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <description>Console application that prints Cassandra table column metadata</description>
    <name>cassandra-print-column-metadata</name>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <slf4j.version>1.7.25</slf4j.version>
    </properties> 

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                            <mainClass>cnauroth.Main</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <finalName>${project.artifactId}</finalName>
                    <appendAssemblyId>false</appendAssemblyId>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <profiles>
        <profile>
            <id>dse-driver</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>com.datastax.cassandra</groupId>
                    <artifactId>dse-driver</artifactId>
                    <version>1.1.2</version>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-assembly-plugin</artifactId>
                        <configuration>
                            <finalName>${project.artifactId}-dse-driver</finalName>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>cassandra-driver</id>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>com.datastax.cassandra</groupId>
                    <artifactId>cassandra-driver-core</artifactId>
                    <version>2.1.9</version>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <artifactId>maven-assembly-plugin</artifactId>
                        <configuration>
                            <finalName>${project.artifactId}-cassandra-driver</finalName>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
    </dependencies>
</project>

Main.java

package cnauroth;

import java.util.List;

import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.ColumnMetadata;
import com.datastax.driver.core.Session;

class Main {

    public static void main(String[] args) throws Exception {
        // Skipping validation for brevity
        String address = args[0];
        String user = args[1];
        String password = args[2];
        String keyspace = args[3];
        String table = args[4];

        try (Cluster cluster = new Cluster.Builder()
                .addContactPoints(address)
                .withCredentials(user, password)
                .build()) {
            List<ColumnMetadata> columns =
                    cluster.getMetadata().getKeyspace(keyspace).getTable(table).getColumns();
            for (ColumnMetadata column : columns) {
                System.out.println(column);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

看起来用于Timestamp的内部Cassandra类型在Cassandra 1.2和2.0(CASSANDRA-5723)之间从org.apache.cassandra.db.marshal.DateTypeorg.apache.cassandra.db.marshal.TimestampType更改。如果您使用Cassandra 1.2(或DSE兼容版本)创建表,则会使用DateType(即使您稍后升级了群集)。

似乎2.1版本的java驱动程序能够解释这个问题(source),但从3.0开始它不会(source)。相反,它将其解析为自定义类型。

幸运的是,驱动程序仍然能够序列化和反序列化此列,因为cql时间戳类型是通过响应中的协议传递的,但它是一个错误,驱动程序将其解析为错误的类型。我继续创建JAVA-1561以跟踪此事。

如果您要将群集迁移到C * 3.0+或DSE 5.0+,我怀疑问题会消失,因为架构表引用了cql名称而不是代表性的Java类名称(除非它确实是自定义类型)。