本次总结图如下
SparkSql可以自定义函数、聚合函数、开窗函数
作用说明:自定义一个函数,并且注册本身,这样就能在SQL语句中使用
使用方式sqlContext.udf().register(函数名,函数(输入,输出),返回类型))
代码
public static void main(String[] args) { SparkConf conf = new SparkConf().setAppName("udf").setMaster("local"); JavaSparkContext sc = new JavaSparkContext(conf); SQLContext sqlContext = new SQLContext(sc); ListSparkStreaming:流式处理框架strs = Arrays.asList("yarn", "Marry", "Jack", "To m", "tom"); JavaRDD rdd = sc.parallelize(strs); JavaRDD rowRdd = rdd.map(new Function
, Row>() { @Override public Row call(String s) throws Exception { return RowFactory.create(s); } }); List structTypes = new ArrayList<>(); structTypes.add(DataTypes.createStructField("name", DataTypes.StringType, true)); StructType structType = DataTypes.createStructType(structTypes); DataFrame df = sqlContext.createDataFrame(rowRdd, structType); df.show(); /** *自定义一个函数,并且注册本身 */ sqlContext.udf().register("strLen", new UDF1 , Integer>() { @Override public Integer call(String s) throws Exception { return s.length(); } }, DataTypes.IntegerType); df.registerTempTable("nameTB"); sqlContext.sql("select name,strLen(name) from nameTB").show(); sc.stop(); }
注意点:
1、local的模拟线程数不许大于2、因为一条线程被receiver(接受数据的线程占用了),另外一个线程是job执行
2、Durations时间的设置,就是我们能接受的延迟度、时间间隔要根据集群资源、job执行时间设置,
3、业务逻辑完成,需要有一个output operator类算子(类似action类算子)
4、javaStreamingContext.start()
5、javaStreamingContext.stop() 无参的sotp方法会将sparkContext一同关闭 ,停止后不能再调用start,不关闭使用stop(false)
代码实战:transform 和 updateStateByKey
public static void main(String[] args) throws Exception { SparkConf conf = new SparkConf().setAppName("tst") /** * 如果携程local,则只会启动一个线程, * 对于sparkStrem,默认会有一个线程, 会一直监听server发送的数据,那么会这用这一个线程, * 每隔5秒发启动一个job线程处理请求过来的数据,无法执行,所以需要设置为local[2],另启动一个线程 */ .setMaster("local[2]"); JavaStreamingContext streamingContext = new JavaStreamingContext(conf, Durations.seconds(5)); JavaReceiverInputDStream代码实战reduceByWindow算子str = streamingContext.socketTextStream("localhost", 9999); JavaPairDStream , Integer> rdd = str.transformToPair(new Function , JavaPairRDD , Integer>>() { @Override public JavaPairRDD , Integer> call(JavaRDD stringJavaRDD) throws Exception { return stringJavaRDD.flatMap(new FlatMapFunction , String>() { @Override public Iterable call(String s) throws Exception { return Arrays.asList(s.split(" ")); } }).mapToPair(new PairFunction , String, Integer>() { @Override public Tuple2 , Integer> call(String s) throws Exception { return new Tuple2<>(s,1); } }).reduceByKey(new Function2 , Integer, Integer>() { @Override public Integer call(Integer v1, Integer v2) throws Exception { return v1+v2; } }); } }); /** * 多久会将内存中的数据(每一个key所对应的状态)写入到磁盘上一份呢? * 如果你的batch interval小于10s 那么10s会将内存中的数据写入到磁盘一份 * 如果bacth interval 大于10s,那么就以bacth interval为准 */ streamingContext.checkpoint("sscheckpoint01"); JavaPairDStream , Integer> keysDS=rdd.updateStateByKey /** * par1: 本次通过key分组后的值集合 * par2: 上一次记录的值 * par3: 返回的值 */ (new Function2 , Optional
, Optional >() { @Override public Optional call /** *par1: 本次通过key分组后的值集合 * par2: 上一次记录的值 */ (List par1, Optional par2) throws Exception { Integer result=par2.isPresent() ? par2.get():0; for(Integer i : par1) result =result+ i; return Optional.of(result); } }); str.print(); System.out.println("------------------------------------"); rdd.print(); System.out.println("------------------------------------"); keysDS.print(); streamingContext.start(); streamingContext.awaitTermination(); }
public static void main(String[] args) throws Exception { SparkConf conf = new SparkConf().setAppName("tes").setMaster("local[2]"); JavaStreamingContext spj = new JavaStreamingContext(conf, Durations.seconds(5)); spj.checkpoint("sscheckpoint01"); JavaReceiverInputDStreamreceiverInputDStream = spj.socketTextStream("localhost", 9999); JavaDStream transform = receiverInputDStream.transform(new Function , JavaRDD >() { @Override public JavaRDD call(JavaRDD stringJavaRDD) throws Exception { return stringJavaRDD; } }); /** * 每隔10秒,计算最近60秒内的数据,那么这个窗口大小就是60秒,里面有12个rdd,在没有计算之前,这些rdd是不会进行计算的。 * 那么在计算的时候会将这12个rdd聚合起来,然后一起执行reduceByKeyAndWindow 操作 * ,reduceByKeyAndWindow是针对窗口操作的而不是针对DStream操作的。 */ // JavaDStream stringJavaDStream = transform.reduceByWindow(new Function2 // @Override // public String call(String s, String s2) throws Exception { // return s + "_" + s2; // } // }, // /** // * 窗口长度 , 窗口滑动时间 // */ // Durations.seconds(15), Durations.seconds(10)); //优化后的代码 JavaDStream() { stringJavaDStream = transform.reduceByWindow(new Function2 , String, String>() { @Override /** * 将讲个时间数据累加 */ public String call(String s, String s2) throws Exception { return s + "_" + s2; } }, new Function2 , String, String>() { @Override /** * 使用优化代码,避免重复计算,现将上一次的计算结果和本次累加, * 然后去掉上一次结算结果头号计算 */ public String call(String s, String s2) throws Exception { return s.replace(s2,""); } }, /** * 窗口长度 , 窗口滑动时间 */ Durations.seconds(15), Durations.seconds(10)); stringJavaDStream.print(); spj.start(); spj.awaitTermination(); }