繁体   English   中英

如何使用Apache Flink从Cassandra读取?

[英]How to read from Cassandra using Apache Flink?

我的flink程序应该对每个输入记录进行一次Cassandra查找,并根据结果进行进一步处理。

但是我目前只能从Cassandra读取数据。 到目前为止,这是我提出的代码段。

ClusterBuilder secureCassandraSinkClusterBuilder = new ClusterBuilder() {
        @Override
        protected Cluster buildCluster(Cluster.Builder builder) {
            return builder.addContactPoints(props.getCassandraClusterUrlAll().split(","))
                    .withPort(props.getCassandraPort())
                    .withAuthProvider(new DseGSSAPIAuthProvider("HTTP"))
                    .withQueryOptions(new QueryOptions().setConsistencyLevel(ConsistencyLevel.LOCAL_QUORUM))
                    .build();
        }
    };

    for (int i=1; i<5; i++) {
        CassandraInputFormat<Tuple2<String, String>> cassandraInputFormat =
                new CassandraInputFormat<>("select * from test where id=hello" + i, secureCassandraSinkClusterBuilder);
        cassandraInputFormat.configure(null);
        cassandraInputFormat.open(null);
        Tuple2<String, String> out = new Tuple8<>();
        cassandraInputFormat.nextRecord(out);
        System.out.println(out);
    }

但这是一个问题,每次查找需要近10秒,换句话说,此for循环需要50秒才能执行。

如何加快此操作? 另外,还有其他方法可以在Flink中查找Cassandra吗?

我想出了一个解决方案,该解决方案可以非常快速地用流数据查询Cassandra。 对于有相同问题的人将是有用的。

首先,只需最少的代码即可查询Cassandra,

Session session = secureCassandraSinkClusterBuilder.getCluster().connect();
ResultSet resultSet = session.execute("SELECT * FROM TABLE");

但是,这样做的问题是,创建Session是一项非常耗时的操作,每个关键空间应执行一次操作。 您只需创建一次Session ,然后将其重新用于所有读取查询。

现在,由于Session不是Java可序列化的,因此它不能作为参数传递给Flink运算符,如MapProcessFunction 有几种解决方法,可以使用RichFunction并在其Open方法中对其进行初始化,也可以使用Singleton。 我将使用第二种解决方案。

在创建Session地方创建一个Singleton类,如下所示。

public class CassandraSessionSingleton {
    private static CassandraSessionSingleton cassandraSessionSingleton = null;

    public Session session;

    private CassandraSessionSingleton(ClusterBuilder clusterBuilder) {
        Cluster cluster = clusterBuilder.getCluster();
        session = cluster.connect();
    }

    public static CassandraSessionSingleton getInstance(ClusterBuilder clusterBuilder) {
        if (cassandraSessionSingleton == null)
            cassandraSessionSingleton = new CassandraSessionSingleton(clusterBuilder);
        return cassandraSessionSingleton;
    }

}

然后,您可以将该会话用于以后的所有查询。 在这里,我以ProcessFunction进行查询为例。

public class SomeProcessFunction implements ProcessFunction <Object, ResultSet> {
    ClusterBuilder secureCassandraSinkClusterBuilder;

    // Constructor
    public SomeProcessFunction (ClusterBuilder secureCassandraSinkClusterBuilder) {
        this.secureCassandraSinkClusterBuilder = secureCassandraSinkClusterBuilder;
    }

    @Override
    public void  ProcessElement (Object obj) throws Exception {
        ResultSet resultSet = CassandraLookUp.cassandraLookUp("SELECT * FROM TEST", secureCassandraSinkClusterBuilder);
        return resultSet;
    }
}

请注意,您可以将ClusterBuilder传递给ProcessFunction因为它是可序列化的。 现在,我们执行查询的cassandraLookUp方法。

public class CassandraLookUp {
    public static ResultSet cassandraLookUp(String query, ClusterBuilder clusterBuilder) {
        CassandraSessionSingleton cassandraSessionSingleton = CassandraSessionSingleton.getInstance(clusterBuilder);
        Session session = cassandraSessionSingleton.session;
        ResultSet resultSet = session.execute(query);
        return resultSet;
    }
}

仅在第一次运行查询时创建单例对象,此后,将重复使用同一对象,因此查找没有延迟。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM