1、数据仓库的概念
数仓就是数据仓库,数仓用于数据存储、分析、清洗、聚合等操作
2、项目需求
1、数据采集平台[业务、日志]
2、数仓的维度建模
3、根据主题进行统计分析
4、即席查询
5、集群性能监控
6、元数据管理
7、数据质量监控
8、可视化
3、技术选型
1、采集传输: Flume、kafka、Sqoop、logstash、datax
flume、logstash: 主要用于采集日志
logstash一般是结合ELK技术栈一起使用
sqoop、datax: 用于将业务数据库的数据与HDFS的数据导入导出
datax支持的数据源更加丰富[比如redis、mongdb、hbase]
kafka: 一般用于实时数据的传输
2、数据存储: Mysql、Hdfs、redis、hbase、mongdb
mysql: 主要用于存储业务数据
HDFS: 主要用于存储离线数据
redis、hbase、mongdb: 主要用于存储实时数据
3、计算引擎: Hive、tez、spark、flink、storm
Hive、tez、spark: 主要用于离线的统计分析
flink、storm、sparkstreaming: 主要用于实时的统计分析
4、即席查询: impala、kylin、presto、durid
impala、presto: 基于内存计算
presto、durid: 基于预计算
5、可视化: echarts、superset、quikbi
echarts: 一般自己写web可视化的时候使用
superset: apache开源,使用方便
6、集群性能监控: zabbix
7、元数据管理: atlas
4、系统数据流程设计
业务数据->数据保存在mysql->sqoop->
->HDFS->HIVE[数仓分层]->sqoop->mysql->可视化
日志数据->数据保存在本地磁盘->flume->kafka->flume->
5、框架版本
Apache: 使用Apache必须考虑框架之间的兼容性[大公司一般用apache]
CDH: 对于框架的兼容以及调研完成,只需按照即可[中小型公司一般使用CDH]
HDP: 国内使用比较少
具体技术的版本选型:
1、要选择最少半年前的稳定版本
2、选择大的稳定版本之后,对于小版本考虑选大不选小
6、服务器选型
物理机[大公司、资金充足的公司选用]
优点: 数据安全性更高
缺点: 成本比较高[运维、机房、恒温、网络...]
云主机[中小型公司、融资的公司选用]
优点: 成本比较低
缺点: 数据安全性相对比较低
7、集群规模的设计
服务器的台数 = 日活用户数 * 平均每个用户每天产生的数据条数 * 每条数据大小 * 数据保存周期 * HDFS副本数 / 0.7 * 数仓分层[2-3倍] * 压缩[压缩比例一般为0.6] / 服务器的磁盘容量
8、hadoop相关
1、HDFS存储多目录
1、好处:
1、提高HDFS并发度以及吞吐量
2、提高HDFS存储容量
2、如何实现存储多目录?
在hdfs-site.xml中配置
<property>
<name>dfs.datanode.data.dir</name>
<value>file://磁盘挂载点1/路径,file://磁盘挂载点2/路径,...</value>
</property>
2、数据均衡
1、原因:数据有可能集中在某几台机器上或者说集中在某个磁盘上,此时会造成数据客户端请求数据的时候负载均衡,所以需要将数据均匀分配在每台服务器以及磁盘上。
2、如何数据均衡?
1、节点的数据不均衡的处理
1、开启数据均衡: start-balancer.sh -threshold N
N代表每个节点之间磁盘的利用率不能超过N%
2、停止数据均衡: stop-balancer.sh
2、磁盘的数据不均衡的处理
1、对指定主机生成磁盘均衡计划: hdfs diskbalancer -plan 主机名 [执行之后会生成一个 主机名.plan.json 文件]
2、执行均衡计划: hdfs diskbalancer -execute 主机名.plan.json
3、查看数据均衡的进度: hdfs diskbalancer -query 主机名
4、停止数据均衡: hdfs diskbalancer -cancel 主机名.plan.json
3、何时进行数据均衡: 一般选在集群资源比较空闲的时候进行,因为进行数据均衡的时候其实就是迁移数据,此时需要占用大量的磁盘IO以及网络IO
3、hadoop支持lzo压缩
hadoop默认不支持lzo压缩
让hadoop支持lzo压缩
1、需要将hadoop-lzo的包放入hadoop的jar包目录
2、在core-site.xml中配置让hadoop支持lzo压缩
<property>
<--!指定hdaoop支持的压缩格式-->
<name>io.compression.codecs</name>
<value>
org.apache.hadoop.io.compress.GzipCodec,
org.apache.hadoop.io.compress.DefaultCodec,
org.apache.hadoop.io.compress.BZip2Codec,
org.apache.hadoop.io.compress.SnappyCodec,
com.hadoop.compression.lzo.LzoCodec,
com.hadoop.compression.lzo.LzopCodec
</value>
</property>
<property>
<--!hadoop默认使用的lzo的压缩格式-->
<name>io.compression.codec.lzo.class</name>
<value>com.hadoop.compression.lzo.LzoCodec</value>
</property>
com.hadoop.compression.lzo.LzoCodec与com.hadoop.compression.lzo.LzopCodec:
com.hadoop.compression.lzo.LzopCodec的压缩文件后续MR在读取时候会根据块的大小分为多个切片
com.hadoop.compression.lzo.LzoCodec的压缩文件后续MR在读取的时候只有一个切片
com.hadoop.compression.lzo.LzopCodec压缩文件只有创建索引之后,MR在读取的时候才会有多个切片
lzo文件创建索引:
hadoop jar /opt/module/hadoop/share/hadoop/common/hadoop-lzo-0.4.20.jar com.hadoop.compression.lzo.DistributedLzoIndexer 待创建索引的lzo文件的路径
4、基准测试
HDFS吞吐量的测试:
1、读吞吐量测试:
hadoop jar /opt/module/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -read -nrFiles N -size 128MB
N=在测试的是一般是集群总CPU核数-1
测试结果:
2020-04-16 13:43:38,857 INFO fs.TestDFSIO: ----- TestDFSIO ----- : read
2020-04-16 13:43:38,858 INFO fs.TestDFSIO: Date & time: Thu Apr 16 13:43:38 CST 2020
2020-04-16 13:43:38,859 INFO fs.TestDFSIO: Number of files: 10 [读取的文件数]
2020-04-16 13:43:38,859 INFO fs.TestDFSIO: Total MBytes processed: 1280 [读取的数据总大小MB]
2020-04-16 13:43:38,859 INFO fs.TestDFSIO: Throughput mb/sec: 85.54 [单个map的读取的速率]
2020-04-16 13:43:38,860 INFO fs.TestDFSIO: Average IO rate mb/sec: 100.21 [单个map的读取的速率]
2020-04-16 13:43:38,860 INFO fs.TestDFSIO: IO rate std deviation: 44.37 [所有map读取的速率的标准差]
2020-04-16 13:43:38,860 INFO fs.TestDFSIO: Test exec time sec: 53.61
HDFS集群的读取的吞吐量 = 单个map的读取的速率 * map个数[nrFiles]
2、写吞吐量测试
hadoop jar /opt/module/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -write -nrFiles N -size 128MB
N=在测试的是一般是集群总CPU核数-1
测试结果:
2020-04-16 13:43:38,857 INFO fs.TestDFSIO: ----- TestDFSIO ----- : read
2020-04-16 13:43:38,858 INFO fs.TestDFSIO: Date & time: Thu Apr 16 13:43:38 CST 2020
2020-04-16 13:43:38,859 INFO fs.TestDFSIO: Number of files: 10 [写入的文件数]
2020-04-16 13:43:38,859 INFO fs.TestDFSIO: Total MBytes processed: 1280 [写入的数据总大小MB]
2020-04-16 13:43:38,859 INFO fs.TestDFSIO: Throughput mb/sec: 85.54 [单个map的写入的速率]
2020-04-16 13:43:38,860 INFO fs.TestDFSIO: Average IO rate mb/sec: 100.21 [单个map的写入的速率]
2020-04-16 13:43:38,860 INFO fs.TestDFSIO: IO rate std deviation: 44.37 [所有map写入的速率的标准差]
2020-04-16 13:43:38,860 INFO fs.TestDFSIO: Test exec time sec: 53.61
HDFS集群的写入的吞吐量 = 单个map的写入的速率 * map个数[nrFiles]
5、hadoop参数调优
1、namenode线程中线程数的调整
1、原因: namenode中有一个线程池,线程池中线程主要用于处理datanode的心跳以及client的读取写入的请求,所以如果client并发度比较高或者datanode机器数比较多,此时线程数可能不太够用,导致请求需要进行排队的情况,影响效率
2、如何调整:
在hdfs-site.xml中配置
<property>
<name>dfs.namenode.handler.count</name>
<value>线程数</value>
</property>
3、配置多少? 线程数 = 20 * log(集群机器数) 【以e为底】
2、nodemanager资源数的调整
1、原因: nodemanager默认只能使用服务器8G的内存,在真实的生产中8G的内存不够用,所以需要调整nodemanager能够使用的内存、cpu资源.一般调整为服务器资源总数的80%
2、如何调整:
通过yarn.nodemanager.resource.memory-mb配置nodemanager能够使用的内存数
9、zookeeper
常用指令:
1、查看节点: ls path
2、创建节点: create path
3、节点中保存数据: set path data
4、获取节点保存的数据: get path
5、删除节点
1、delete: 只能删除没有子节点的节点[叶子节点]
2、deleteall: 能删除有子节点的节点
10、kafka
1、常用指令
1、topic相关
1、创建topic: bin/kafka-topics.sh --create --topic topic名称 --partitions 分区数 --replication-factor 副本数 --bootstrap-server broker主机:9092,..
2、查看集群所有的topic: bin/kafka-topics.sh --list --bootstrap-server broker主机:9092,..
3、查看topic详细信息: bin/kafka-topics.sh --describe --topic topic名称 --bootstrap-server broker主机:9092,..
4、修改topic[只能修改分区数,而且是只能增加分区数]: bin/kafka-topics.sh --alter --topic topic名称 --bootstrap-server broker主机:9092,.. --partitions 分区数
5、删除topic: bin/kafka-topics.sh --delete --topic topic名称 --bootstrap-server broker主机:9092,..
2、生产者相关: bin/kafka-console-producer.sh --topic topic名称 --broker-list broker主机:9092,..
3、消费者相关:
1、消费数据: bin/kafka-console-consumer.sh --topic topic名称 --bootstrap-server broker主机:9092,.. [--from-beginning] [--group 消费者组的id]
--from-beginning: 指定消费者组第一次消费topic的时候从最开始一个offset开始消费
2、查看消费者消费到了topic每个分区哪个offset: bin/kafka-consumer-group.sh --all-groups --all-topics --describe--bootstrap-server broker主机:9092,..
4、查看分区数据: bin/kafka-dump-log.sh --files 数据文件路径 --print-data-log
2、项目经验
1、吞吐量测试
好处: 识别集群是否满足业务需要
1、读吞吐量: bin/kafka-consumer-perf-test.sh --topic topic名称 --messages N --broker-list broker主机:9092,..
messages: 代表消费的消息的条数
测试结果:
start.time, end.time, data.consumed.in.MB, MB.sec, data.consumed.in.nMsg, nMsg.sec
2019-02-19 20:29:07:566, 2019-02-19 20:29:12:170, 9.5368, 2.0714, 100010, 21722.4153
开始测试时间,测试结束数据,共消费数据9.5368MB,吞吐量2.0714MB/s,共消费100010条,平均每秒消费21722.4153条
其中2.0714就是读取的吞吐量
2、写吞吐量: bin/kafka-producer-perf-test.sh --topic topic名称 --num-records N --throughput -1 --record-size M --producer-props bootstra.servers=broker主机:9092
num-records:指向topic中写入多少条消息
throughput:代表是否限制写入的速率[-1代表不限制]
record-size: 写入topic的每条消息的大小[单位是byte]
测试结果:
100000 records sent, 95877.277085 records/sec (9.14 MB/sec), 187.68 ms avg latency, 424.00 ms max latency, 155 ms 50th, 411 ms 95th, 423 ms 99th, 424 ms 99.9th.
其中9.14 MB/sec就是写入的吞吐量
2、kafka机器数计算: 2 * N + 1
N = 目标吞吐量 * 副本数 / 100 [目标吞吐量的单位必须是MB/s]
3、topic分区数计算: 目标吞吐量/min(集群写吞吐量,集群读吞吐量)
11、flume项目经验
flume内存一般在工作中需要进行设置,一般设置为4G或者更高
-Xms: 代表程序启动时的内存大小
-Xmx: 代表程序运行时的最大内存
在设置flume内存的时候,最好将Xms与Xmx设置的一样。如果不一样,程序启动运行一段时间之后,内存不够用,此时需要扩容内存,但是在扩容内存之前会进行GC影响效率
12、sqoop导入导出常用参数:
sqoop 导入常用参数:
bin/sqoop import
------------------------------公有参数-----------------------------------
--connect 指定mysql url连接
--username 指定mysql账号
--password 指定mysql的密码
-------------------------------导入HDFS的时候使用---------------------------
--append 追加数据到HDFS
--as-textfile 将数据以文本格式保存在HDFS
--as-parquetfile 将数据以parquet文件格式保存在HDFS--columns 指定从mysql导出哪些列的数据到HDFS
--delete-target-dir 指定导入数据之前先删除目标路径
--num-mappers[-m] 指定maptask的个数,这多maptask并行从mysql导数据
--split-by 指定数据切分的依据字段
--query[-e] 通过sql语句指定从mysql导哪些数据 [select 字段,... from 表名 where ...]
--where 指定导入mysql指定条件的数据
--table 指定导mysql哪个表的数据
--columns 指定从mysql导出哪些列的数据到HDFS
--target-dir 指定数据存储在HDFS的路径
--compress[-z] 指定数据导入HDFS的时候是否压缩
--compression-codec 指定数据保存在HDFS的时候压缩格式
--null-string 指定mysql字符串列值如果为null的时候导入HDFS以哪种格式保存
--null-non-string 指定mysql非字符串列值如果为null的时候导入HDFS以哪种格式保存
--fields-terminated-by 指定数据保存在HDFS的时候列之间的分隔符
--lines-terminated-by 指定数据保存在HDFS的时候行之间的分隔符
-------------------------------------增量导入------------------------------
--check-column 指定通过哪个字段判断数据为新增/修改数据
--incremental append[只导mysql每天新增的数据]/lastmodified[导入新增和修改的数据]
--last-value 指定通过哪个值判断数据为新增/修改的数据
------------------------------------数据导入HIVE--------------------------
--hive-import 指定数据导入HIVE中
--hive-table 指定数据导入hive哪个表
--create-hive-table 如果hive表不存在可以自动创建
--hive-overwrite 指定数据导入hive的时候直接覆盖hive数据
--hive-partition-key 指定数据导入hive分区表的时候分区字段名是什么
--hive-partition-value 指定数据导入hive分区表的时候分区字段的值是什么
sqoop 导出常用参数:
bin/sqoop export
------------------------------公有参数-----------------------------------
--connect 指定mysql url连接
--username 指定mysql账号
--password 指定mysql的密码
--columns 指定数据导入到mysql哪些列中
--export-dir 指定HDFS数据路径
--num-mappers[-m] 指定maptask个数
--table 指定数据导入到mysql哪个表
--update-key 指定HDFS导入数据到mysql的时候,通过哪个字段判断HDFS与mysql的数据是同一条数
--update-mode updateonly[如果update-key的数据在mysql中已经存在则更新,不存在则忽略]/allowinsert[如果update-key的数据在mysql中已经存在则更新,不存在则插入]
--input-null-string 指定HDFS字符串数据如果为null,保存在mysql的时候以哪种形式保存
--input-null-non-string 指定HDFS非字符串数据如果为null,保存在mysql的时候以哪种形式保存
--input-fields-terminated-by 指定HDFS中数据字段之间的分隔符
--input-lines-terminated-by 指定HDFS中数据行之间的分隔符
13、表的同步策略
全量同步: 每天都将mysql表所有数据导入到hive一个分区中[hive的每个分区都是当天的mysql表的所有数据]
场景: mysql表数据量比较小,每天既有新增也有修改数据
增量同步: 每天将mysql表当天新增的数据导入到hive一个分区中
场景: mysql表数据量比较大,每天只有新增数据
新增及修改同步: 每天将mysql表当天新增以及修改的数据导入到hive一个分区中
场景: mysql表数据量比较大,每天既有新增也有修改数据
特殊策略同步: mysql表的数据不会经常变动,所以只需要导入一次即可,后续如果数据发生变动,此时重写导入覆盖原来的数据即可
场景: mysql表的数据不会经常变动
14、多维聚合: 多个组合维度聚合查询
grouping sets: 自由组合维度聚合查询
语法: select 字段1,...,聚合函数,.. from 表 group by 字段1,.. grouping sets( (字段1,.),(字段2,..),.. )
grouping sets后面的字段必须是group by里面的字段
比如:
select A,B,C,count(1) num from P group by A,B,C grouping sets( (A),(B),(A,B),())
等价于:
select A,null B,null C,count(1) num from P group by A
union all
select null A,B,null C,count(1) num from P group by B
union all
select A,B,null C,count(1) num from P group by A,B
union all
select null A,null B,null C,count(1) num from P