运营系统分析平台技术设计:

  1. 项目定义于运营系统关键指标的数据分析
  2. 关键代码描述:
    1. HiveWriter 主要用于写hive表抽象,包括加分区,写hive表,写success文件:

      import org.apache.hadoop.fs.{FileSystem, Path}
      import org.apache.spark.sql.SparkSession class HiveWriter(tableName: String, outputDir: String, currentDate: String) { val currentYear = currentDate.substring(0, 4)
      val currentMonth = currentDate.substring(4, 6)
      val currentDay = currentDate.substring(6, 8) //加分区
      def addPartition(ss: SparkSession, hour: String): Unit = {
      var query: String = ""
      if(hour == ""){
      query =
      s"""ALTER TABLE $tableName ADD IF NOT EXISTS
      |PARTITION(year='$currentYear',month='$currentMonth',day='$currentDay')
      |LOCATION '$outputDir/$currentYear/$currentMonth/$currentDay'
      """.stripMargin
      }else{
      query =
      s"""ALTER TABLE $tableName ADD IF NOT EXISTS
      |PARTITION(year='$currentYear',month='$currentMonth',day='$currentDay',hour=$hour)
      |LOCATION '$outputDir/$currentYear/$currentMonth/$currentDay/$hour'
      """.stripMargin
      }
      ss.sql(query)
      } //写hive表
      def save(ss:SparkSession, name: String, hour: String): Unit = {
      var query: String = ""
      if(hour == ""){
      query =
      s"""
      |INSERT overwrite TABLE ${tableName} partition(YEAR=${currentYear},MONTH=${currentMonth},DAY=${currentDay})
      |SELECT *
      |FROM ${name}
      """.stripMargin
      }else{
      query =
      s"""
      |INSERT overwrite TABLE ${tableName} partition(YEAR=${currentYear},MONTH=${currentMonth},DAY=${currentDay},HOUR=${hour})
      |SELECT *
      |FROM ${name}
      """.stripMargin }
      ss.sql(query)
      } //写success文件
      def writeSuccFile(ss: SparkSession, hour: String): Unit = {
      val conf = ss.sparkContext.hadoopConfiguration
      val hdfs = FileSystem.get(conf)
      var path: String = ""
      if(hour == ""){
      path = s"${outputDir}/${currentYear}/${currentMonth}/${currentDay}/_SUCCESS"
      }else{
      path = s"${outputDir}/${currentYear}/${currentMonth}/${currentDay}/${hour}/_SUCCESS"
      }
      val success = new Path(path)
      hdfs.create(success)
      } }

      HiveConf

    2. QueryConf 主要用于根据传递来的表,时间等信息构建各种ETL需要的SQL:
      class QueryConf(tableName: String, currentDate: String, outputDir: String, callTableName: String) {
      
        val oneWeekAgo = CommonUtils.calTime(currentDate, Calendar.DATE, -6)
      
        //查询字段
      val resFields = Seq("pope_act_id","group_id","pid","order_id","is_complete","pay_suc_time") val payQuery =
      s"""
      |SELECT DISTINCT cast(order_id AS string) order_id,
      | pay_suc_time
      |FROM table
      |WHERE concat(YEAR,MONTH,DAY) = ${currentDate} |AND pay_suc_time != ''
      |AND pay_suc_time IS NOT NULL
      |AND order_id IS NOT NULL""".stripMargin val callQuery =
      s"""
      |SELECT DISTINCT pope_act_id,
      | group_id,
      | pid,
      | order_id,
      | is_complete
      |FROM ${callTableName}
      |WHERE concat(YEAR,MONTH,DAY) BETWEEN ${oneWeekAgo} AND ${currentDate}
      |AND pope_act_id != ''
      |AND pid != 0""".stripMargin }

      QueryConf

    3. Process 执行器代码主要用于实际执行的封装: 
      import org.apache.spark.sql.SparkSession
      
      class Process(ss: SparkSession, queryConf: QueryConf, writer: HiveWriter) {
      
        def processPay(): Unit = {
      
          val payRawData = ss.sql(queryConf.payQuery)
      val callRawData = ss.sql(queryConf.callQuery)
      val payData = payRawData.join(callRawData,Seq("order_id"),"inner")
      .selectExpr(queryConf.resFields: _*) val name = "pay_tbl"
      payData.createOrReplaceTempView(name) writer.addPartition(ss, "")
      writer.save(ss, name, "")
      writer.writeSuccFile(ss, "") } }
      object Process {
      def apply(ss: SparkSession, queryConf: QueryConf, writer: HiveWriter): Process = {
      new Process(ss, queryConf, writer)
      }
      }
    4. 程序串联 : 
      val Array(appName, tableName, currentDate, outputDir, callTableName) = args
      val ss = SparkSession.builder().appName(appName).enableHiveSupport().getOrCreate() val queryConf = new QueryConf(tableName, currentDate, outputDir, callTableName)
      val writer = new HiveWriter(tableName, outputDir, currentDate) val processor = Process(ss,queryConf,writer)
      processor.processPay() ss.stop()

      串联程序

  3. 关键技术细节:
    1. SQL字符串表达式建议如下:s"""sql""".stripMargin,更整洁更好维护复杂的SQL
    2. 涉及到时间计算,预先unix_timestamp(observe_end_time) 在SQL中转化成时间戳,在map算子中只做最简单的判断计算
    3. Scala 枚举:
      object ActivityCallTBL extends Enumeration {
      type ActivityCallTBL = Value
      val callStatus = Value("gulfstream_ods.ods_binlog_d_order_status_increment")
      val callBase = Value("gulfstream_ods.ods_binlog_d_order_base_increment")
      }
    4. 定义结构体: {} 里面能写复杂代码定义产出结果,适用于一句话搞不定返回值的情况
    5. ROW_NUMBER()函数,常用案例包括 
      1.   取出每种rate下score最大的两条记录
      2.   SQL实例:以下意思就是取a_birth_time最早的order信息:
        select order_id, passenger_id pid, product_id, a_birth_time ,unix_timestamp(a_birth_time) tim, area, starting_lng, starting_lat, dest_lng, dest_lat,  type order_type, combo_type, require_level, extra_info
        from ( select * , row_number() over (partition by order_id order by a_birth_time ) as tid
        from gulfstream_ods.ods_binlog_d_order_base_increment
        where concat(year,month,day,hour)='2017112309' ) a where tid = 1
    1. sql cast功能: cast(order_id AS string) order_id, spark.sql实现: df.select(df("colA").cast("int"))
    2. sql nvl功能 : nvl(t1.a_create_time,'1971-01-01 00:00:00') AS create_time

    3. spark select Seq() : selectExpr(Seq(): _*)
    4. import org.apache.spark.sql.functions  定义spark中用Scala实现的各种SQL常用算子
    5. withColumn("is_complete",functions.lit(0))  使用常数类型构造一个新的column,withColumn("testkey", concat($"apollo_exp_id", lit(":0:"), $"apollo_group_id"))
    6. df("colA") =!= df("colB")   column不等于算子
    7. 添加UDF函数 val genCarpool = spark.udf.register("genCarpool", func), 使用ds.withColumn("ds_carpool", genCarpool(ds("raw_ct")))
    8. import org.apache.spark.sql.functions._ 之后就能使用   from_unixtime(Colunm) 函数了。
    9. import spark.implicits._   牛逼的隐式转换把Scala类型 转化为  DF的类型,包括能使用df.select($"sss")
    10. functions.explode : spark中集合类打平函数,会把一个集合中的多个元素打平成多个Row
    11. df.drop  删除指定的column
    12. functions.when : functions.when(resPre("new_carpool").contains(resPre("ds_carpool")) and ???,1).otherwise(0), 关键技巧先转换成String(1,2,3,4) 再判断contains基本值
    13. coalesce(10) 在结果DF之后加上控制写hive表最合适的part个数
    14. package object activity 包对象更好适合常量场景
    15. <: 继承关系,[T <: Conf]
    16. DF启用别名: activeMarketingActDF.alias("a").join(odsGCouponRuleInfoDF.alias("b"), $"a.info_id" === $"b.id").selectExpr("a.id")

    17. flatMap函数: 当map中返回的是 LIST 会把结果打平
    18. selectExpr表达式: ds.selectExpr("colA", "colB as newName", "abs(colC)")
    19. 多个列中最大,最小值: greatest(exprs: Column*)  跳过null least(exprs: Column*) 跳过null 取最小的值
    20. 其他有效函数

      1. between
      2. isNaN
      3. isNull
    21. sparkGC太多可以优化点如下

      1. 调大task个数,更快GC,减少长时间GC时间拖慢整个进程。优化参数如下
        1. --conf spark.dynamicAllocation.maxExecutors=1000 \
          --conf spark.executor.cores=4 \

      2. 调大执行器的年轻代大小: --conf "spark.executor.extraJavaOptions=-XX:NewSize=2048m"
    22. YarnScheduler: Lost executor 13 on bigdata-hdp-apache1005.xg01.diditaxi.com: Container killed by YARN for exceeding memory limits. 12.5 GB of 12 GB physical memory used. Consider boosting spark.yarn.executor.memoryOverhead.   解决手段:
      1. --conf spark.executor.memory=12g
      2. repartition 设置大点
      3. --conf  spark.shuffle.spill.numElementsForceSpillThreshold=1500000 ,内存中row的数量超过这个值,不再放到内存直接写磁盘

osap一站式分析模型的更多相关文章

  1. Moebius集群:SQL Server一站式数据平台

    一.Moebius集群的架构及原理 1.无共享磁盘架构 Moebius集群采用无共享磁盘架构设计,各个机器可以不连接一个共享的设备,数据可以存储在每个机器自己的存储介质中.这样每个机器就不需要硬件上的 ...

  2. 层次分析模型(AHP)及其MATLAB实现

    今天用将近一天的时间学习了层次分析模型(AHP),主要参考了一份pdf,这个网站,和暨南大学章老师的课件,现写出一些自己总结的要点. 一.层次分析法的基本步骤: 角度一: 实际问题——分解——> ...

  3. 【OpenCV入门教程之三】 图像的载入,显示和输出 一站式完全解析(转)

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/20537737 作者:毛星云(浅墨)  ...

  4. 王家林的81门一站式云计算分布式大数据&移动互联网解决方案课程第14门课程:Android软硬整合设计与框架揭秘: HAL&Framework &Native Service &App&HTML5架构设计与实战开发

    掌握Android从底层开发到框架整合技术到上层App开发及HTML5的全部技术: 一次彻底的Android架构.思想和实战技术的洗礼: 彻底掌握Andorid HAL.Android Runtime ...

  5. 一站式Hadoop&Spark云计算分布式大数据和Android&HTML5移动互联网解决方案课程(Hadoop、Spark、Android、HTML5)V2的第一门课程

    Hadoop是云计算的事实标准软件框架,是云计算理念.机制和商业化的具体实现,是整个云计算技术学习中公认的核心和最具有价值内容. 如何从企业级开发实战的角度开始,在实际企业级动手操作中深入浅出并循序渐 ...

  6. 一站式远程页面调试工具spy-debugger 2.0,已支持HTTPS

    项目名称: spy-debugger 项目地址:https://github.com/wuchangming/spy-debugger 关于spy-debugger npm Build Status ...

  7. Liunx+C编程一站式学习

    Liunx+C编程一站式学习这本书有什么特点?面向什么样的读者?这本书最初是为某培训班的嵌入式系统Linux工程师就业班课程量身定做的教材之一.该课程是为期四个月的全日制职业培训,要求学员毕业时具备非 ...

  8. 老司机带你用vagrant打造一站式python开发测试环境

      前言 作为一个学习和使用Python的老司机,好像应该经常总结一点东西的,让新司机尽快上路,少走弯路,然后大家一起愉快的玩耍. 今天,咱们就使用vagrant配合xshell打造一站式Python ...

  9. 为智能硬件提供一站式解决方案——机智云GoKit评测

    为智能硬件提供一站式解决方案——机智云GoKit评测 2014年12月24日 作者: ladouyu 3 17,414+ 4 EMW3162GoKit开发板STM32F103智能硬件机智云2.0 从物 ...

随机推荐

  1. SQL server 数据库备份大

    首先简单的介绍一下Sql server 备份的类型有: 1:完整备份(所有的数据文件和部分的事务日志文件) 2:差异备份(最后一次完成备份后数据库改变的部分) 3:文件和文件组备份(对指定的文件和文件 ...

  2. python第四课——线程、进程、协程

    面试or笔试题:简述线程.进程.协程之间的关系? 内容概要 1.进程与线程优.缺点的比较 2.适用情况 3.线程 线程的创建 setDaemon join event RLock 队列 4.进程 创建 ...

  3. mysql安装教程以及配置快捷方式

    1.首先双击exe 3.Next 安装过程省略.... Win+r 然后输入:cmd 打开dos窗口后: 输入: mysql -uroot -p你设置的密码 案例:mysql -uroot -proo ...

  4. JAVA基础知识总结:七

    一.面向对象编程 1.什么是面向对象? 万物皆对象 案例一:我想吃大盘鸡 面向过程 面向对象 1.我自己去买一只鸡 1.委托一个会砍价的人去帮忙买鸡 2.我自己宰鸡 2.委托一个胆大的人宰鸡 3.我自 ...

  5. ajax+分页

    <!DOCTYPE html> <html> <head lang="zh-cn"> <meta charset="UTF-8& ...

  6. Java web学习 Cookie&&Session

    cookie&&session 会话技术 从打开一个浏览器访问某个站点,到关闭这个浏览器的整个过程,成为一次会话.会 话技术就是记录这次会话中客户端的状态与数据的. 会话技术分为Coo ...

  7. 读书笔记-你不知道的JS上-闭包与模块

    闭包定义 当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行. 看一段最简单的闭包代码: function foo() { var a = 2; //闭包 fun ...

  8. rewrite写法

    RewriteRule ^/android-special-(\d+).html$ /special/index.php?c=index&a=specialDetail&speid=$ ...

  9. 1034: [ZJOI2008]泡泡堂BNB

    1034: [ZJOI2008]泡泡堂BNB Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3234  Solved: 1655[Submit][St ...

  10. Problem E

    题意:看电视,计算出最多看多少个电视,已给出电视起始终止时间: 解体思路:思路这个题拿到手没多想,上课的例题,就照葫芦画瓢写了一个: 感悟:虽然刚开始学贪心,第一遍代码就AC了有点小小的成就感: 代码 ...