osap一站式分析模型
运营系统分析平台技术设计:
- 项目定义于运营系统关键指标的数据分析
- 关键代码描述:
- 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
- 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
- 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)
}
} - 程序串联 :
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()串联程序
- 关键技术细节:
- SQL字符串表达式建议如下:s"""sql""".stripMargin,更整洁更好维护复杂的SQL
- 涉及到时间计算,预先unix_timestamp(observe_end_time) 在SQL中转化成时间戳,在map算子中只做最简单的判断计算
- 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")
} - 定义结构体: {} 里面能写复杂代码定义产出结果,适用于一句话搞不定返回值的情况
- ROW_NUMBER()函数,常用案例包括
- 取出每种rate下score最大的两条记录
- 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
- sql cast功能: cast(order_id AS string) order_id, spark.sql实现: df.select(df("colA").cast("int"))
sql nvl功能 : nvl(t1.a_create_time,'1971-01-01 00:00:00') AS create_time
- spark select Seq() : selectExpr(Seq(): _*)
- import org.apache.spark.sql.functions 定义spark中用Scala实现的各种SQL常用算子
- withColumn("is_complete",functions.lit(0)) 使用常数类型构造一个新的column,withColumn("testkey", concat($"apollo_exp_id", lit(":0:"), $"apollo_group_id"))
- df("colA") =!= df("colB") column不等于算子
- 添加UDF函数 val genCarpool = spark.udf.register("genCarpool", func), 使用ds.withColumn("ds_carpool", genCarpool(ds("raw_ct")))
- import org.apache.spark.sql.functions._ 之后就能使用 from_unixtime(Colunm) 函数了。
- import spark.implicits._ 牛逼的隐式转换把Scala类型 转化为 DF的类型,包括能使用df.select($"sss")
- functions.explode : spark中集合类打平函数,会把一个集合中的多个元素打平成多个Row
- df.drop 删除指定的column
- functions.when : functions.when(resPre("new_carpool").contains(resPre("ds_carpool")) and ???,1).otherwise(0), 关键技巧先转换成String(1,2,3,4) 再判断contains基本值
- coalesce(10) 在结果DF之后加上控制写hive表最合适的part个数
- package object activity 包对象更好适合常量场景
- <: 继承关系,[T <: Conf]
DF启用别名: activeMarketingActDF.alias("a").join(odsGCouponRuleInfoDF.alias("b"), $"a.info_id" === $"b.id").selectExpr("a.id")
- flatMap函数: 当map中返回的是 LIST 会把结果打平
- selectExpr表达式: ds.selectExpr("colA", "colB as newName", "abs(colC)")
- 多个列中最大,最小值: greatest(exprs: Column*) 跳过null least(exprs: Column*) 跳过null 取最小的值
其他有效函数
- between
- isNaN
- isNull
sparkGC太多可以优化点如下
- 调大task个数,更快GC,减少长时间GC时间拖慢整个进程。优化参数如下
--conf spark.dynamicAllocation.maxExecutors=1000 \
--conf spark.executor.cores=4 \
- 调大执行器的年轻代大小: --conf "spark.executor.extraJavaOptions=-XX:NewSize=2048m"
- 调大task个数,更快GC,减少长时间GC时间拖慢整个进程。优化参数如下
- 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. 解决手段:
- --conf spark.executor.memory=12g
- repartition 设置大点
- --conf spark.shuffle.spill.numElementsForceSpillThreshold=1500000 ,内存中row的数量超过这个值,不再放到内存直接写磁盘
osap一站式分析模型的更多相关文章
- Moebius集群:SQL Server一站式数据平台
一.Moebius集群的架构及原理 1.无共享磁盘架构 Moebius集群采用无共享磁盘架构设计,各个机器可以不连接一个共享的设备,数据可以存储在每个机器自己的存储介质中.这样每个机器就不需要硬件上的 ...
- 层次分析模型(AHP)及其MATLAB实现
今天用将近一天的时间学习了层次分析模型(AHP),主要参考了一份pdf,这个网站,和暨南大学章老师的课件,现写出一些自己总结的要点. 一.层次分析法的基本步骤: 角度一: 实际问题——分解——> ...
- 【OpenCV入门教程之三】 图像的载入,显示和输出 一站式完全解析(转)
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/20537737 作者:毛星云(浅墨) ...
- 王家林的81门一站式云计算分布式大数据&移动互联网解决方案课程第14门课程:Android软硬整合设计与框架揭秘: HAL&Framework &Native Service &App&HTML5架构设计与实战开发
掌握Android从底层开发到框架整合技术到上层App开发及HTML5的全部技术: 一次彻底的Android架构.思想和实战技术的洗礼: 彻底掌握Andorid HAL.Android Runtime ...
- 一站式Hadoop&Spark云计算分布式大数据和Android&HTML5移动互联网解决方案课程(Hadoop、Spark、Android、HTML5)V2的第一门课程
Hadoop是云计算的事实标准软件框架,是云计算理念.机制和商业化的具体实现,是整个云计算技术学习中公认的核心和最具有价值内容. 如何从企业级开发实战的角度开始,在实际企业级动手操作中深入浅出并循序渐 ...
- 一站式远程页面调试工具spy-debugger 2.0,已支持HTTPS
项目名称: spy-debugger 项目地址:https://github.com/wuchangming/spy-debugger 关于spy-debugger npm Build Status ...
- Liunx+C编程一站式学习
Liunx+C编程一站式学习这本书有什么特点?面向什么样的读者?这本书最初是为某培训班的嵌入式系统Linux工程师就业班课程量身定做的教材之一.该课程是为期四个月的全日制职业培训,要求学员毕业时具备非 ...
- 老司机带你用vagrant打造一站式python开发测试环境
前言 作为一个学习和使用Python的老司机,好像应该经常总结一点东西的,让新司机尽快上路,少走弯路,然后大家一起愉快的玩耍. 今天,咱们就使用vagrant配合xshell打造一站式Python ...
- 为智能硬件提供一站式解决方案——机智云GoKit评测
为智能硬件提供一站式解决方案——机智云GoKit评测 2014年12月24日 作者: ladouyu 3 17,414+ 4 EMW3162GoKit开发板STM32F103智能硬件机智云2.0 从物 ...
随机推荐
- java四大会话技术
未经作者允许,不得转载 第一cookie技术 常用方法: new Cookie(),构造一个cookie getName() ,获取cookie的名字 getValue () ,取到具体cookie的 ...
- js 关于性能的数据存储
1.JavaScript中四种基本数据存取位置:字面量,本地变量,数组元素,对象成员.(四个都是存在于内存中) 一般来说:[字面量,局部变量]运行速度>[数组,对象成员] 2.内部属性包含了一个 ...
- Docker中搭建zookeeper集群
1.获取官方镜像 从dockerhub获取官方的zookeeper镜像: docker pull zookeeper 2.了解镜像内容 拉取完镜像后,通过 docker inspect zookeep ...
- Linux入门(15)——Ubuntu16.04安装codeblocks搭建C/C++的IDE环境
安装codeblocks: sudo add-apt-repository ppa:damien-moore/codeblocks-stable sudo apt-get update sudo ap ...
- 典型的NIO代码
public void selector() throws IOException { ByteBuffer buffer = ByteBuffer.allocate(1024); Selector ...
- 【ASP.NET MVC 学习笔记】- 08 URL Routing
本文参考:http://www.cnblogs.com/willick/p/3343105.html 1.URL Routing告诉MVC如何正确的定位Controller和Action. 2.URL ...
- 通过Struts了解MVC框架,兼说如何在面试中利用Struts证明自己
虽然目前Struts MVC框架不怎么用了,但它确是个能帮助大家很好地入门Web MVC框架,而且,一些历史项目可能还用Struts,反正技多不压身,大家如果能在面试中通过项目证明自己Struts这块 ...
- Hive中常用的查询命令
日志数据的统计处理在这里反倒没有什么特别之处,就是一些 SQL 语句而已,也没有什么高深的技巧,不过还是列举一些语句示例,以示 hive 处理数据的方便之处,并展示 hive 的一些用法. a) ...
- Android 开发笔记___AutoComplateTextView__自动完成文本框
原理:EdtText结合监听器TextWatcher与下拉框spinner,一旦监控到EditText的文本发生变化,就自动弹出适配好的文字下拉内容. 属性以及设置方法: XML中的属性 代码中 说明 ...
- 蓝桥杯-算法训练--ALGO-4 结点选择
本人是一个刚刚接触C++不久的傻学生~记录一些自己的学习过程.大神路过可以批评指正~ 刚学动态规划,水平还很渣,一下子不知道从何下手,借鉴了一下这位大哥的文章 http://www.cnblogs.c ...