数据采集规范
由于需要采集的异构数据源有SQLSERVER,MYSQL,Elastic Search,单独的Sqoop不满足需求,因此选型Spark以自定义的方式采集数据到数据仓库
导入策略为新增和变化
ES的导入示例
#!/bin/bash
if [ $1 ];
then
host=$1
else
echo 'need es host'
exit
fi
if [ $2 ];
then
dt=$2
else
dt=`date -d "-1 day" +%F`
fi
if [ $3 ];
then
dt1=$3
else
dt1=`date -d "-1 day" +%F`
fi
echo "起始日期:$dt,结束日期:$dt1"
/opt/cloudera/parcels/SPARK2/bin/spark2-submit \
--class com.mingzhi.common.universal.load_new_change_from_es \
--master yarn \
--deploy-mode cluster \
--num-executors 3 \
--executor-memory 1G \
--executor-cores 1 \
--conf spark.default.parallelism=200 \
--conf spark.port.maxRetries=300 \
/mnt/db_file/wfs/jar/es_hdfs-1.0-SNAPSHOT-jar-with-dependencies.jar \
$host wfs_order_list_index _doc paascloud wfs_order_list_index $dt $dt1 "orderCreateTime" "orderUpdateTime" parquet
参数列表:
Es主机host,es索引,es表名,数仓库,数仓表,导入日期起始时间,导入日期结束时间,数据创建时间,数据结束使劲,压缩格式
MYSQL的导入示例
#!/bin/bash
if [ $1 ];
then
host=$1
else
echo 'need mysql host'
exit
fi
if [ $2 ];
then
username=$2
else
echo 'need mysql username'
exit
fi
if [ $3 ];
then
pwd=$3
else
echo 'need mysql pwd'
exit
fi
if [ $4 ];
then
dt=$4
else
dt=`date -d "-1 day" +%F`
fi
if [ $5 ];
then
dt1=$5
else
dt1=`date -d "-1 day" +%F`
fi
echo "起始日期:$dt,结束日期:$dt1"
/opt/cloudera/parcels/SPARK2/bin/spark2-submit \
--class com.mingzhi.common.universal.load_new_change_from_mysql \
--master yarn \
--deploy-mode cluster \
--num-executors 3 \
--executor-memory 2G \
--executor-cores 2 \
--conf spark.sql.shuffle.partitions=20 \
--conf spark.port.maxRetries=300 \
/mnt/db_file/jars/common-1.0-SNAPSHOT-jar-with-dependencies_v1.jar \
$host paascloud_wfs_new tbwork_order paascloud tbwork_order $username $pwd $dt $dt1 'create_time' 'update_time'
参数列表:
Mysql主机host,mysql数据库,表名,数仓库,数仓表,用户名,密码,日期起始时间,日期结束时间,数据创建时间,数据修改时间
导入策略为新增
ES的导入示例
#!/bin/bash
if [ $1 ];
then
host=$1
else
echo 'need es host'
exit
fi
if [ $2 ];
then
dt=$2
else
dt=`date -d "-1 day" +%F`
fi
if [ $3 ];
then
dt1=$3
else
dt1=`date -d "-1 day" +%F`
fi
echo "起始日期:$dt,结束日期:$dt1"
/opt/cloudera/parcels/SPARK2/bin/spark2-submit \
--class com.mingzhi.common.universal.load_new_from_es \
--master yarn \
--deploy-mode cluster \
--num-executors 3 \
--executor-memory 1G \
--executor-cores 1 \
--conf spark.default.parallelism=200 \
--conf spark.port.maxRetries=300 \
/mnt/db_file/wfs/jar/es_hdfs-1.0-SNAPSHOT-jar-with-dependencies.jar \
$host wfs_order_track_index _doc paascloud wfs_order_track_index $dt $dt1 "createTime"
参数列表:
ES主机host,es索引,es表,数仓库,数仓表,日期起始时间,日期结束时间,数据创建时间
MYSQL的导入示例
#!/bin/bash
if [ $1 ];
then
host=$1
else
echo 'need mysql host'
exit
fi
if [ $2 ];
then
username=$2
else
echo 'need mysql username'
exit
fi
if [ $3 ];
then
pwd=$3
else
echo 'need mysql pwd'
exit
fi
if [ $4 ];
then
dt=$4
else
dt=`date -d "-1 day" +%F`
fi
if [ $5 ];
then
dt1=$5
else
dt1=`date -d "-1 day" +%F`
fi
echo "起始日期:$dt,结束日期:$dt1"
/opt/cloudera/parcels/SPARK2/bin/spark2-submit \
--class com.mingzhi.common.universal.load_new_from_mysql \
--master yarn \
--deploy-mode cluster \
--num-executors 2 \
--executor-memory 2G \
--executor-cores 4 \
--conf spark.sql.shuffle.partitions=20 \
--conf spark.port.maxRetries=300 \
/mnt/db_file/jars/common-1.0-SNAPSHOT-jar-with-dependencies_v1.jar \
$host paascloud_wfs_new tbwork_order_track_record paascloud tbwork_order_track_record $username $pwd $dt $dt1 'create_time'
参数列表:
MYSQL主机host,数据库名,数据表名,数仓库,数仓表,用户名,密码,日期起始时间,日期结束时间,数据创建时间
导入策略为全量
MYSQL的导入示例
#!/bin/bash
if [ $1 ];
then
host=$1
else
echo 'need mysql host'
exit
fi
if [ $2 ];
then
username=$2
else
echo 'need mysql username'
exit
fi
if [ $3 ];
then
pwd=$3
else
echo 'need mysql pwd'
exit
fi
if [ $4 ];
then
dt=$4
else
dt=`date -d "-1 day" +%F`
fi
if [ $5 ];
then
dt1=$5
else
dt1=`date -d "-1 day" +%F`
fi
echo "起始日期:$dt,结束日期:$dt1"
/opt/cloudera/parcels/SPARK2/bin/spark2-submit \
--class com.mingzhi.common.universal.load_all_from_mysql \
--master yarn \
--deploy-mode cluster \
--num-executors 3 \
--executor-memory 1G \
--executor-cores 1 \
--conf spark.default.parallelism=200 \
--conf spark.port.maxRetries=300 \
/mnt/db_file/wfs/jar/es_hdfs-1.0-SNAPSHOT-jar-with-dependencies.jar \
$host paascloud_uac t_uac_organization paascloud t_uac_organization $username $pwd $dt $dt1
参数列表:
MYSQL主机host,数据库,数据表,数仓库,数仓表,用户名,密码,日期起始时间,日期结束时间
数据采集中的其他点
作业模块的数据导入脚本根据自身导入策略需求,参考上述导入脚本
原始表保持和业务数据库表名一致
为提高效率,避免手动建表,采用saveAsTable算子自动建表
原始数据需要格式化,消除MYSQL数据制表符等特殊符号导致的导入问题
数据存储格式采用列式parquet
数据压缩算法采用snappy
对数据库的连接及时释放
数据sink到数仓过程中不允许小文件,需要先coalesce算子缩减分区,如果该分区缩减方式导致内存压力OOM,则使用repartition算子进行有shuffle的重分区
日期的标准格式采用 yyyy-MM-dd hh:mm:ss和yyyy-MM-dd
从ES导入数据时候,重新配置ES_SCROLL_SIZE,ES_MAX_DOCS_PER_PARTITION等参数,以增大吞吐量
数仓规范
所有环境,开发,测试,类生产,生产环境保持配置一致
host使用主机名,避免直接使用ip
HDFS,YARN等关键服务配置高可用
架构上需要分层,至少要有原始层,ODS层,明细层,汇总层,采用星型建模模型
ODS层做初步的处理,去重,过滤,异构数据结构统一等ETL操作
表命名规范:业务模块+层级+业务意义
建表时,手动明确指定数据目录所在层级,路径
SQL优化,谓词下推,先过滤,再进行其他操作
慎用cube全维度聚合函数,根据需求有选择性的使用grouping_set函数
hive自定义函数,spark自定义函数需要指定打包的版本
所有的时间区间,采用左闭右开,以避免数据的重复和遗漏
对于数仓表历史数据需要进行更新的场景,需要先计算涉及的变更记录,有变更的才进行更新,不要全量更新
历史数据批量计算的时候,按照需求的时间跨度,一层一层的计算,不要按照时间粒度烟囱式的计算,以避免大量的重复计算
数仓表升级方案:采用新表旧表共存,新表逐步替换旧表的方式进行升级
不要在map算子中进行数据库的连接或者对接外部存储系统,而应使用mapPartition算子实现
表进行join的时候,小表采用广播变量或者mapside join,需要指定join条件以避免笛卡尔积
长窗口的计算需要使用预计算,在预计算的基础上再计算
长窗口的数据量大,要注意内存压力,必要时候evictor
精确统计的数据,为避免精度损失,采用BigDecimal类型
ES规范
数据写入ES,对于幂等性写入的场景,需要指定数据的id并保持其唯一性
ES的索引,需要手动指定mapping,schema
ES索引的动态映射采用strict模式
ES对外提供的索引需要使用别名
数据导出规范
数据库的连接及时释放
对数据库锁表的情况,这种情况会导致连接阻塞,异常捕获失效,进而导致集群压力持续增大,需要对任务进行监控,杀掉长期无活动的任务
输出到业务系统的数据,需要带有last_update_time标识
任务调度规范
任务调度,每个大任务的提交需要间隔半个小时以上
任务提交过多时,为了避免端口抢占的问题,增大端口重试次数
任务提交executor数量根据集群情况,不超过3个,分区合并,不多于三个
shell脚本任务名称,所在层级+业务名称.sh
任务调度流flow节点名称和每层的表名保持一致,示例如下
- name: t_uac_organization
type: command
config:
command: ssh mz-hadoop-01 "source /etc/profile;/mnt/db_file/wfs/paascloud/t_uac_organization.sh 172.18.253.9 mzplatform Mingzhe@123456 ${dt} ${dt1}"
任务调度流flow节点名称和被执行的shell脚本名称保持一致
周期性的任务调度需要使用线程池时以手动指定参数的构造类进行构造,即使用ThreadPoolExecutor,不建议直接使用Executors,以避免其默认Integer.MAX的任务数量将会导致OOM的风险