将countByKey结果存储到Cassandra中

将countByKey结果存储到Cassandra中,cassandra,apache-spark,Cassandra,Apache Spark,我想计算任何一天每个用户的指示状态消息数(在Cassandra表中),然后将其存储在单独的Cassandra表中,以驱动一些仪表板页面。我设法让“countByKey”正常工作,但现在无法想出如何将Spark Cassandra“saveToCassandra”方法与映射一起使用(它只需要RDD) JavaSparkContext sc=新的JavaSparkContext(conf); cassandrajavard indicatatepresence table=javaFunctions

我想计算任何一天每个用户的指示状态消息数(在Cassandra表中),然后将其存储在单独的Cassandra表中,以驱动一些仪表板页面。我设法让“countByKey”正常工作,但现在无法想出如何将Spark Cassandra“saveToCassandra”方法与映射一起使用(它只需要RDD)

JavaSparkContext sc=新的JavaSparkContext(conf);
cassandrajavard indicatatepresence table=javaFunctions(sc).cassandraTable(“mykeyspace”,“indicatedpresence”);
javapairdd keyedByUserDate=指示PresenceTable.keyBy(新函数(){
私有静态最终长serialVersionUID=1L;
@凌驾
公共用户日期调用(CassandraRow cassandraIndicatePresenceRow)引发异常{
SimpleDataFormat sdf=新SimpleDataFormat(“yyyy-MM-dd”);
返回新的UserDate(cassandraIndicatePresenceRow.getString(“userid”)、sdf.format(cassandraIndicatePresenceRow.getDate(“日期”));
}
});
Map countByKey=keyedByUserDate.countByKey();
writerBuilder(“分析”、“countbykey”和?).saveToCassandra();

有没有一种直接在writerBuilder中使用地图的方法?或者我应该编写自己的自定义减速机,它返回一个RDD,但本质上与countByKey方法做相同的事情?或者,我应该将映射中的每个条目转换为一个新的POJO(例如UserDateCount,带有user、date和count)并使用“parallelize”将列表转换为RDD,然后存储它吗?

最好的做法是永远不要将结果返回给驱动程序(使用countByKey)。相反,执行reduceByKey以
(key,count)
的形式获取另一个RDD。将该RDD映射到表的行格式,然后对其调用
saveToCassandra

这种方法最重要的优点是我们从不将数据序列化回驱动程序应用程序。所有信息都保存在集群上,并从集群直接保存到C*中,而不是通过驱动程序应用程序的瓶颈运行

示例(非常类似于减少字数的映射):

  • 将每个元素映射到(键,1)
  • 调用reduceByKey进行更改(键,1)->(键,计数)
  • 将每个元素映射到可写入C*(键,计数)->WritableObject的对象
  • 调用save到C*
  • 在Scala中,这类似于

    keyedByUserDate
      .map(_.1, 1)                               // Take the Key portion of the tuple and replace the value portion with 1
      .reduceByKey( _ + _ )                      // Combine the value portions for all elements which share a key
      .map{ case (key, value) => your C* format} // Change the Tuple2 to something that matches your C* table
      .saveToCassandra(ks,tab)                   // Save to Cassandra
    
    在Java中,它有点复杂(为K和V插入您的类型)

    .mapToPair(新的PairFunction>,Tuple2(){
    @凌驾
    公共Tuple2调用(Tuple2输入)引发异常{
    返回新的Tuple2(input._1(),1)
    }
    }.reduceByKey(新功能2(长、长、长)(){
    @凌驾
    公共长调用(长值1,长值2)引发异常{
    返回值1+2
    }
    }.map(新函数1(Tuple2,OutputTableClass)({
    @凌驾
    公共OutputTableClass调用(Tuple2输入)引发异常{
    //在这里做些工作
    返回新的OutputTableClass(col1、col2、col3…colN)
    }
    }.saveToCassandra(ks,tab,mapToRow(OutputTableClass.class))
    
    最好不要将结果返回给驱动程序(使用countByKey)。相反,执行reduceByKey以
    (key,count)
    的形式获取另一个RDD。将该RDD映射到表的行格式,然后调用
    saveToCassandra

    这种方法最重要的优点是我们从不将数据序列化回驱动程序应用程序。所有信息都保存在集群中,并直接从集群保存到C*中,而不是通过驱动程序应用程序的瓶颈运行

    示例(非常类似于减少字数的映射):

  • 将每个元素映射到(键,1)
  • 调用reduceByKey进行更改(键,1)->(键,计数)
  • 将每个元素映射到可写入C*(键,计数)->WritableObject的对象
  • 调用save到C*
  • 在Scala中,这类似于

    keyedByUserDate
      .map(_.1, 1)                               // Take the Key portion of the tuple and replace the value portion with 1
      .reduceByKey( _ + _ )                      // Combine the value portions for all elements which share a key
      .map{ case (key, value) => your C* format} // Change the Tuple2 to something that matches your C* table
      .saveToCassandra(ks,tab)                   // Save to Cassandra
    
    在Java中,它有点复杂(为K和V插入您的类型)

    .mapToPair(新的PairFunction>,Tuple2(){
    @凌驾
    公共Tuple2调用(Tuple2输入)引发异常{
    返回新的Tuple2(input._1(),1)
    }
    }.reduceByKey(新功能2(长、长、长)(){
    @凌驾
    公共长调用(长值1,长值2)引发异常{
    返回值1+2
    }
    }.map(新函数1(Tuple2,OutputTableClass)({
    @凌驾
    公共OutputTableClass调用(Tuple2输入)引发异常{
    //在这里做些工作
    返回新的OutputTableClass(col1、col2、col3…colN)
    }
    }.saveToCassandra(ks,tab,mapToRow(OutputTableClass.class))
    
    Ah好的,这就是我的想法——因此,基本上,如果我找到“countByKey”的源代码,并将其放入我自己的“reduceByKey”自定义函数中,但将其作为RDD保留,而不是让它调用“MapAsserAlizableJavaMap”,那就可以了?这就是想法,reduceByKey应该只是一个(+))有点lambda抱歉,我对这个相当陌生,我对reduce感到困惑-对于RDD,reduce接受并返回V。这是否意味着要进行计数,我的V类必须在其内部包含一个count字段(大概在reduce运行之前,该字段将被硬编码为1)?如果我的V是一个CassandraRow,我可能必须创建一个像CassandraRow一样的包装器WithCount并在我的RDD中使用它?或者有更好的方法吗?我在问题AHH中添加了更多细节,地图返回(键,1)是不是有点我想不出来-回答得很好,谢谢你的帮助!啊,好吧,这就是我的想法-所以基本上,如果我找到“countByKey”的源代码,并将其放在我自己的“reduceByKey”自定义函数中,但将其作为RDD保留,而不是让它调用“mapAsSerializableJavaMap”,那就可以了?这就是我的想法,reduceByKey s应该是一个(+uu)类型的lambda抱歉,我对这个相当陌生,我对reduce感到困惑-对于RDD,reduce接受并返回V。这意味着要这样做吗
    .mapToPair(new PairFunction<Tuple2<K,V>,K,Long>>, Tuple2<K, Long>(){
        @Override
        public Tuple2<K, Long> call(Tuple2<K, V> input) throws Exception {
          return new Tuple2(input._1(),1)
        }
    }.reduceByKey(new Function2(Long,Long,Long)(){
        @Override
        public Long call(Long value1, Long value2) throws Exception {
          return value1 + value2
        }
    }.map(new Function1(Tuple2<K, Long>, OutputTableClass)(){  
        @Override
        public OutputTableClass call(Tuple2<K,Long> input) throws Exception {
        //Do some work here
        return new OutputTableClass(col1,col2,col3 ... colN)
       }
    }.saveToCassandra(ks,tab, mapToRow(OutputTableClass.class))