zoukankan      html  css  js  c++  java
  • 工作采坑札记:1. Hadoop中的BytesWritable误区

    1. 背景

    近日帮外部门的同事处理一个小需求,就是将HDFS中2018年至今所有存储的sequence序列化文件读取出来,重新保存成文本格式,以便于他后续进行处理。由于同事主要做机器学习方向,对hadoop或spark方面不了解,所以我就想着这么小的需求,简单支持下即可,花个几分钟写了一个脚本提供给他,没想到,过了一天他又找到我,说脚本读取出来的文件大部分有问题…原来自己代码有bug

    2. 初始版本

    Spark或Hadoop读取sequence文件只需调用相应函数即可。

    第一版本的spark程序代码如下:

      1 package com.ws.test
      2 
      3 import org.apache.hadoop.io.{BytesWritable, Text}
      4 import org.apache.spark.{SparkConf, SparkContext}
      5 
      6 object Test {
      7   def main(args: Array[String]): Unit = {
      8     if (args.length < 1) {
      9       println("input param error: <method name>")
     10     } else {
     11       args(0) match {
     12         case "deseqData" => deseqData(args)
     13         case _ =>
     14       }
     15     }
     16   }
     17 
     18   def deseqData(args: Array[String]): Unit ={
     19 
     20     if(args.length != 3){
     21       println("input param error: <method name> <input dir> <output dir>")
     22       return
     23     }
     24 
     25     val conf = new SparkConf()
     26     conf.setAppName(args(0))
     27     val sc = new SparkContext(conf)
     28 
     29     val inputDir = args(1)
     30     val outputDir = args(2)
     31 
     32     sc.sequenceFile[Text, BytesWritable](s"hdfs://$inputDir")
     33       .map(data => new String(data._2.getBytes)).saveAsTextFile(outputDir)
     34 
     35     sc.stop()
     36   }
     37 }
    View Code

    提供的bash脚本如下:

    #!/bin/bash
    
    source ~/.bashrc
    
    if [[ $# -ne 2 ]];then
        echo "$(date +'%Y-%m-%d %H:%M:%S')    input param error: <file input path> <file output path>"
        exit 1
    fi
    
    SPARK_BIN_DIR=/home/hadoop/spark/spark-1.5.2-bin-hadoop2.3/bin
    HADOOP_BIN_PATH=/home/hadoop/hadoop-2.3.0-cdh5.0.0/bin
    
    
    $HADOOP_BIN_PATH/hadoop fs -rm -r $2
    if [ $? -ne 0];then
        echo "$(date +'%Y-%m-%d %H:%M:%S')    output file dir does not exist in hdfs"
    fi
    
    runJob(){
        echo "$(date +'%Y-%m-%d %H:%M:%S')    spark task begins!"
        nohup $SPARK_BIN_DIR/spark-submit --class com.ws.test.Test  --master yarn --num-executors 10 --driver-memory 7192M --executor-memory 7192M --queue default run.jar deseqData $1 $2 >> log 2>&1 &
        if [ $? -ne 0 ];then
            echo "$(date +'%Y-%m-%d %H:%M:%S')    spark task running error"
            exit 1
        fi
    
        pid=$!
        echo "$(date +'%Y-%m-%d %H:%M:%S')    spark task processId is $pid, wait to finish..."
        wait $pid
        if [ $? -ne 0 ];then
            echo  "$(date +'%Y-%m-%d %H:%M:%S')    spark task running exception"
            exit 1
        fi
        tail -f log
        echo "$(date +'%Y-%m-%d %H:%M:%S')    spark task  finished!"
    }
    
    runJob $1 $2
    View Code

    执行./run.sh /crawler/data/2018-04-04/0/data1522774524.799569.seq /crawler/wstest执行解析任务即可

    提取的结果如下:

    截图

    那些@符号是什么鬼…

    3. 优化版本

    由于导出的数据存在问题,遂优化了一版,不同之处如下:

      1 sc.sequenceFile[Text, BytesWritable](s"hdfs://$inputDir")
      2   //      .map(data => new String(data._2.getBytes))
      3   .map(data => {
      4   val value = data._2
      5   value.setCapacity(value.getLength)
      6   new String(value.getBytes)
      7 }).saveAsTextFile(outputDir)
      8 
    View Code

    打包重新运行bash脚本,得到的结果如下图:

    截图

    终于正常了,长舒一口气…,but为什么这样呢?

    4. 原因分析

    当你把byte[]数据保存为BytesWritable后,通过BytesWritable.getBytes()再获取到的数据不一定是原数据,可能变长了很多,这是因为BytesWritable采用自动内存增长算法,你保存数据长度为size时,它可能将数据保存到了长度为capacity(capacity>size)的buffer中。此时,使用BytesWritable.getBytes()得到的数据最后一些字符是多余的。如果里面保存的是protocol buffer序列化后的字符串,则将无法反序列化。

    此时可以使用BytesWritable.setCapacity(bytesWritable.getLength())将后面多于空间剔除

  • 相关阅读:
    vert.x笔记:6.vert.x集群化部署
    vert.x笔记:5.vert.x集成dubbo服务
    Wampserver 配置端口可访问服务
    git credential for windows 总是弹出的问题
    如何用B表的数据,更新A表的值
    WampServer部署https 服务的过程
    PHP 命名空间冲突解决方式
    Windows下 Docker 简单部署 Django应用
    C#实现后台格式化U盘的功能
    Winform 实现断点续传的思路及代码
  • 原文地址:https://www.cnblogs.com/mengrennwpu/p/8747772.html
Copyright © 2011-2022 走看看