[英]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运算符,如Map
或ProcessFunction
。 有几种解决方法,可以使用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.