一、Linux
1、常用的高级命令
ps -ef 查看进程 (过滤出想要查看的进程 ps -ef | grep redis )
top 实时显示系统中各个进程的资源占用状况(CPU、内存和执行时间)
df -h 查看磁盘存储情况
free -m 查看系统内存使用情况
jmap -heap 查看某个进程内存
netstat -anp |grep 进程号 (功能描述:查看该进程网络信息)
netstat -nlp | grep 端口号 (功能描述:查看网络端口号占用情况)
2、查看XXX(内存、磁盘、端口、进程)的命令
3、Shell
3.1 常用工具 awk 文本分析处理 sort 默认按照字典顺序排序 sed 根据指定的规则对文本文件进行搜索、替换和转换 cut 对文本文件进行字段剪切提取 cut -d " " -f 1 cut.txt 以空格切分取第一列 3.2 写过哪些脚本 1) 启停,分发脚本 #!/bin/bash case $1 "start") for i in hadoop102 hadoop103 hadoop104 do ssh $i "start-xxx.sh" done ;; "stop") for i in hadoop102 hadoop103 hadoop104 do ssh $i "stop-xxx.sh" done ;; esac 2) DataX同步脚本 MySQL -> HDFS HDFS -> MySQL 3) ODS -----> ADS 数仓层级内部导入脚本 bin/hive -e "sql" 4) 业务数据库初始化脚本 Maxwell 5) '' 与 ""区别 嵌套:看外层
二、Hadoop
1、入门
1.1 端口号
NameNode ResourceManager HistoryServer 2.x 9000 50070 8032 8088 10020 19888 3.x 8020 9870 8032 8088 10020 19888
1.2 配置文件 2.x core hdfs yarn mapred slaves 3.x core hdfs yarn mapred workers
hadoop中重要的配置文件 一共9个 4个只读文件 core-default.xml yarn-default.xml hdfs-default.xml mapred-default.xml 4个site core-site.xml yarn-site.xml hdfs-site.xml mapred-site.xml 加上一个 wokers
2、HDFS
2.1 读写流程(笔试题)
HDFS写数据流程:
(1) 客户端创建Distributed FileSystem,通过Distributed FileSystem模块向NameNode请求上传文件。NameNode检查权限以及目录结构(目标文件是否已存在,父目录是否存在)。
(2) NameNode返回是否可以上传文件。
(3) 客户端请求上传第一个Block(0-128M),请返回DataNode。
(4) NameNode返回3个DataNode节点(按照副本数量挑选DN进行返回),分别为dn1、dn2、dn3节点,表示采用这三个节点存储数据。(按照负载均衡原则随机进行返回)
(5) 客户端通过FSDataOutputStream模块请求dn1上传数据,dn1收到请求会继续调用dn2,然后dn2调用dn3,将这个通信管道建立完成。
(6) dn1、dn2、dn3逐级应答客户端。
(7) 客户端开始往dn1上传第一个Block(先从磁盘读取数据放到一个本地内存缓存),以Packet为单位,dn1收到一个Packet就会传给dn2,dn2传给dn3;dn1每传一个packet会放入一个应答队列等待应答。
(8) 当一个Block传输完成之后,客户端再次请求NameNode上传第二个Block的服务器。(重复执行3-7步)。
深入解读拔高
(1) 在传输数据的过程中是以packet为单位进行读取。
一个packet的大小为64k,包括512byte的chunk和4byte的chunksum (64k*1024/512byte = 128 个 chunk)。
校验的结果和数据是分开放的,所以需要分开进行传输,在实际传输的过程中传输128M的chunks,而chunksum则像小尾巴一样跟在chunks后面进行传输。
(2) 在数据传输过程中运行ack确认成功机制。
(3) 如果DN没有成功读取数据,那么运行排除重发机制,遇到故障则全部删除重发。
(4) 如果DN1和DN3全部传输成功,但是DN2只传输一部分,那么删除DN2的全部数据,通过自动恢复机制使DN2读取全部数据。
(5) HDFS写入流程时候,某台dataNode挂掉如何运行?
当DataNode突然挂掉了,客户端接收不到这个DataNode发送的ack确认,客户端会通知NameNode,NameNode检查并确认该块的副本与规定的不符,NameNode会通知闲置的DataNode去复制副本,并将挂掉的DataNode作下线处理。等挂掉的DataNode节点恢复后, 删除该节点中曾经拷贝的不完整副本数据。
HDFS读数据流程:
(1) 客户端通过DistributedFileSystem向NameNode请求下载文件,NameNode检查权限以及目录结构(目标文件是否已存在,父目录是否存在),查询元数据,找到文件块所在的DataNode地址,返回目标文件的元数据。
(2) 客户端通过FSDataOutputStream模块挑选一台DataNode(就近原则,然后随机)服务器,请求读取数据。
(3) DataNode开始传输数据给客户端(从磁盘里面读取数据输入流,以packet为单位来进行传输)。
(4) 客户端以packet为单位接收,先在本地缓存,然后写入目标文件。
(5) 如果DN1上没有完整的数据,那么请求读取DN2上的数据,直至数据成功完整传输,依旧是以packet(64k)为单位进行传输。
2.2 小文件问题
1) 危害 (1) 存储:每一个块都会占用一个元数据 NN内存利用率下降 (2) 计算:默认是按照单个文件进行切片 每一个文件都会启动一个MapTask,浪费资源 [注解:HDFS上每个文件都要在NameNode上创建对应的元数据,当小文件比较多的时候,就会产生很多的元数据文件,一方面会大量占用NameNode的内存空间,另一方面就是元数据文件过多,使得寻址索引速度变慢。小文件过多,在进行MR计算时,会生成过多切片,需要启动过多的MapTask。每个MapTask处理的数据量小,导致MapTask的处理时间比启动时间还小,浪费资源。] 2) 解决 (1) 存储: a.不产生,源头上 Flume HDFS Sink:文件滚动参数,大小(128M)、时间(30Min)、事件个数(0) Hive: ADS层处理数据 insert into ads_t select * from dws_t where date = 当天; insert overwrite ads_t select * from dws_t where date = 当天 union all select * from ads_t; 输出合并,把每天的小文件数据和历史数据合并成一个大文件,再覆盖原来的数据。 b.Har归档
(2) 计算: CombineTextInputFormat CombineHiveTextInputFormat MR引擎:JVM重用 MR任务中MapTask和ReduceTask都是进程(YarnChild) Spark任务中ShuffleMapTask和ResultTask都是线程
2.3 副本数 3 2.4 块大小 128M Hive 256M 取决于磁盘的读写速度
3、MR
Shuffle+优化 Shuffle流程指的是从Map方法之后到Reduce方法之前
MR的工作流程,包括shuffle
第一部分:inputformat ------> map + sort
1、待处理文件(/home/atguigu/aaa.txt 200M)
2、客户端提交前,获取待处理数据的信息,根据参数配置,形成一个任务分配的规划(aaa.txt被划分为两块:0-128M,128-200M)
3、客户端提交信息(Job.split,wc.jar,Job.xml)
4、申请运行Mrappmaster计算出Map Task的数量
5、通过TextInPutFormat中的RecorderReader方法按行读取数据
6、通过Mapper中的map方法进行逻辑运算,再通过context.write(k,v)方法写出
7、MapTask收集map( )方法输出的kv对,向环形缓冲区(默认100M,80%后反向,反复使用)写入<k,v>数据
8、从内存环形缓冲区不断溢出本地磁盘文件,此过程中调用Partitioner进行分区和针对key进行排序,可能会溢出多个文件
9、多个溢出文件进行归并排序,此过程中同样调用Partitioner进行分区和针对key进行排序,最后被合并成大的溢出文件
第二部分:copy + sort + reduce ------> outputformat
10、ReduceTask根据自己的分区号,去各个MapTask机器上拷贝相应的结果分区数据
11、ReduceTask会抓取到同一个分区的来自不同MapTask的结果文件,ReduceTask会将这些文件再进行合并(归并排序)
12、进入ReduceTask的逻辑运算过程:从文件中一次读取一组的键值对Group
13、通过reduce默认的TextOutPutFormat方法输出结果
(Shuffle过程在Map之后Reduce之前,主要对数据做排序工作。流程为7~11)
Shuffle优化:
4、Yarn
4.1 提交流程 工作机制
(1)MR程序提交到客户端所在的节点。
(2)YarnRunner向ResourceManager申请一个Application,ResourceManager将该应用程序的资源路径返回给YarnRunner。
(3)该程序将运行所需资源提交到HDFS上。程序资源提交完毕后,申请运行MRAppMaster。
(4)RM将用户的请求初始化成一个Task。其中一个NodeManager领取到Task任务。该NodeManager创建容器Container,并产生MRAppmaster。
(5)Container从HDFS上拷贝资源到本地。
(6)MRAppmaster向RM 申请运行MapTask资源。
(7)RM将运行MapTask任务分配给另外两个NodeManager,另两个NodeManager分别领取任务并创建容器。MRAppmaster向两个接收到任务的NodeManager发送程序启动脚本,这两个NodeManager分别启动MapTask,MapTask对数据分区排序。
(8)MrAppMaster等待所有MapTask运行完毕后,向RM申请容器,运行ReduceTask。ReduceTask向MapTask获取相应分区的数据。
(9)程序运行完毕后,MRAppmaster会向RM申请注销自己。
4.2 调度器 三种: FIFO:单队列,先进先出 容量:多队列,队列内先进先出 队列可互相占用资源 公平:多队列,资源的缺额,队列内可多任务并行 队列可互相占用资源 队列的设置: 默认的队列:default 框架: hive spark 等 业务线(数据域): 不同数据域占据单独队列 部门(人员):菜鸟 防止任务简单但是耗费大量资源
三、Zookeeper
1、选举机制
半数机制
第一次启动 (myid 大的被选举为leader ,如果1,2,3,4,5同时启动,那么 5为 leader)
非第一次启动 (携带信息量多的被选举为leader)
2、机器台数
奇数台
3、常用命令
帮助其他框架存储核心数据辅助其他工作 create 4种 临时、永久 有无序列号 临时节点:创建节点的进程挂了,那么节点会自动删除
delete deleteall
ls get
四、Hive
1、Hive组成与HSQL翻译成MR(Spark、Tez)任务的流程
Hive组成: 外部:MySQL、HDFS、MR(Spark) 内部:驱动类:解析器、编译器、优化器、执行器 HSQL翻译成MR: 解析器:将HQL转换为抽象语法树(AST) 编译器: 将抽象语法树转换为查询块(最小的查询单元); 进一步将查询块转换为逻辑执行计划; 优化器:对逻辑执行计划进行逻辑优化(参数级别的优化) 编译器:将逻辑执行计划转换为物理执行计划(Task) 优化器:对物理执行计划进行优化(实现类有三个,MR、Spark、Tez) 执行器:提交任务执行
2、内外部表
区别:删除表的时候 内部表:元数据和数据本身都会删除 外部表:只删除元数据
可以互相转换
3、与MySQL的区别
数据量
存储、计算引擎、应用方式(Mysql:增删改查,Hive:一次写入,多次读取)
4、4个By
order by:全局排序,只能有一个Reducer sort by:分区内排序 distribute by:分区 cluster by:当sort by与distribute by的字段相同且为升序时,可以直接替换
5、 函数
1) 系统函数 (1) 时间类 date_add date_sub datediff date_format next_day('','MO'):下一个周几 last_day(''):月末 • (2) 窗口函数 • over() • 聚合函数:count sum avg... • 排名函数 • lead lag • last_value first_value • ntile • (3) 多维分析函数 • with cube • with rollup • grouping sets((),(),()) 2) 自定义函数 UDF UDTF
6、优化
1) 建表 分区、分桶 存储格式:orc 压缩 1) SQL CBO优化:3.x默认开启 成本优化器(join) [CBO是指Cost based Optimizer,即基于计算成本的优化。 在Hive中,计算成本模型考虑到了:数据的行数、CPU、本地IO、HDFS IO、网络IO等方面。Hive会计算同一SQL语句的不同执行计划的计算成本,并选出成本最低的执行计划。目前CBO在hive的MR引擎下主要用于join的优化,例如多表join的join顺序。] 谓词下推:[尽量将过滤操作前移,以减少后续计算步骤的数据量。] select * from t1 join t2 on t1.id=t2.id where t1.id>100; select * from (select * from t1 where t1.id>100) t3 join (select * from t2 where t2.id>100) t4 on t3.id=t4.id; select * from t1 join t2 on t1.id=t2.id where t1.age>100; select * from (select * from t1 where t1.age>100) t3 join t2 on t3.id=t2.id; select * from t1 left join t2 on t1.id=t2.id where t2.age>100; 2.x 版本 谓词下推失效 3.x 版本 谓词下推生效 select * from t1 join (select * from t2 where t2.age>100) t3 on t1.id=t3.id;
行列过滤:能过滤的就先过滤,尽量只写查询的列 vectorized:矢量计算 批量读取 1024 开启map join:大表 关联 小表 (默认开启,调整参数值25M可以提升到500M) 大表与大表: SMB (Sort Merge Bucket) MapSideCombine ---> 预聚合 3.整体 本地模式 [Hive可以通过本地模式在单台机器上处理所有的任务。对于小数据集,执行时间可以明显被缩短] 严格模式 [Hive可以通过设置某些参数防止危险操作 1、分区表不使用分区过滤 2、使用order by没有limit过滤 3、笛卡尔积] Fetch抓取:某些HQL可以不走MR任务 调整Mapper和Reducer数量 Mapper数量: 数据量/切片大小 切片大小=max(MIN_VALUE(1),min(blockSize,MAX_VALUE(long.maxValue))) 切片大小=blockSize Reducer数量: 1.直接指定 默认值为-1 2.如果Reducer数量<1 min(数据量/256M,1009)
7、数据倾斜
1) 现象 绝大部分Reducer已经结束,只有一个或者少数几个没有执行完,卡在95%-99%,甚至最后内存溢出报错,任务失败. 1) 原因 单表查询:group by 多表关联:join on 1) 解决 单表查询: 在不影响业务逻辑的前提下,预聚合 影响业务逻辑的前提下,加随机数实现双重聚合 select dept_id,avg(salary) from dept group by dept_id; ===> select dept_id,随机数,salary from dept;t1 select dept_id,随机数,sum(salary) salary,count(*) ct from t1 group by dept_id,随机数;t2 select dept_id,sum(salary)/sum(ct) from t2 group by dept_id; 多表关联: 大表 小表:MapJoin 没有了Reduce阶段 大表 大表:相对大表加随机数打散,相对小表加随机数扩容 1) 场景 (1) 数据倾斜场景:公司针对某些商品(城市)做活动,我们需要了解活动的具体情况; (2) 业务场景:需要按照商品(城市)分组计算各种指标; (3) 发现问题:针对这些SQL,绝大部分Reducer已经结束,只有一个或者少数几个没有执行完,卡在95%-99%,甚至最后内存溢出报错,任务失败 (4) 定位问题:group by造成的数据倾斜 (5) 解决:在不影响业务逻辑的前提下,预聚合。影响业务逻辑的前提下,加随机数实现双重聚合。 (6) 效果:平时这些任务在半个小时计算完成,发生数据倾斜时发现2个小时都没有计算完,在处理以后在1个小时左右结束。
8、其他
union:去重 union all:不去重 如果没有重复数据,用union all
五、Flume
1、基本组成
1) Source TairDirSource:多目录多文件,实时,断点续传 断点续传:读取数据后需要保存位置信息 [(inode,绝对路径),pos] • 2023-07-29 • aa.log 2356 • 2023-07-30 • aa.log.2023-07-29 2356 • aa.log 0 • 问题:更名的日志框架在凌晨时会完整的重复一份昨天的数据 • 解决: • (1) 替换日志打印框架,使其不更名 • logback log4j2 • 2023-07-29 • aa.log.2023-07-29 2356 • 2023-07-30 • aa.log.2023-07-29 2356 • aa.log.2023-07-30 0 • (2) 修改源码,只按照iNode值做key • KafkaSource: • AvroSource:复杂拓扑,Flume对接Flume 2) Channel Memory File Kafka 3) Sink HDFS Sink 小文件 压缩 KafkaSink
2、拦截器
时间戳拦截器:防止零点漂移 时间戳和表名拦截器: 如何自定义拦截器: 实现接口 初始化方法、单个事件、多个事件、关闭 静态内部类 帮助创建拦截器 打包上传lib目录 在文件中配置时,需要写到静态内部类
3、 Channel选择器
副本(默认) 多路复用:结合拦截器添加头信息
4、Sink处理器
default:只允许有一个Sink 故障转移: 负载均衡:
5、监控器
Ganglia
Source尝试Put事件数 Source成功Put事件数 Sink尝试Take事件数 Sink成功Take事件数 Channel中现有的事件数
Source尝试Put事件数 》 Source成功Put事件数 资源 Sink尝试Take事件数 》 Sink成功Take事件数 资源 Source成功Put事件数 > Sink成功Take事件数 + Channel中现有的事件数 丢数据
5.6 优化 资源 内存调整 20M flume-env.sh 4G HDFS Sink 解决小文件问题、以压缩流写出 TairDirSource:修改日志框架 修改源码(不会重复消费数据) 拦截器:零点漂移 丢数据: 通过监控发现没有丢数据! Source成功Put事件数 = Sink成功Take事件数 + Channel中现有的事件数 说明:组件 TairDirSource+KafkaChannel (可能会有重复数据) KafkaSource+FileChannel+HDFSSink
六、Kafka
1、基本信息
1) 生产者 发送流程:2个线程(main sender) 拦截器、序列化器、分区器 分区策略 指定分区 没有指定分区,但是指定了Key,按照Key的Hash 没有指定分区,也没有指定Key,按照粘性分区 ACK 0:丢数据 1:丢数据 -1:重复 如果ISR队列中只有Leader时 不丢数据:保证副本数>=2且ISR队列中>=2 幂等性、事务 2) 集群 topic-partition 副本:高可靠 LEO:每个副本最大的Offset HW:同一个分区多个副本中的最小的LEO HW是消费者可见的最大的Offset:保证了消费者消费数据的一致性 Leader挂掉重启后需要截取自身数据到HW位置,重新与新Leader同步数据: 保证数据存储的一致性 ISR + OSR = AR 分区:负载均衡 提高并行能力(生产与消费) 3) 消费者 (1) 消费者组 分区分配策略 范围、轮询、粘性(很少单独使用):尽量保证原有的绑定关系不变 轮询:同一个消费者组中不同的消费者消费的主题需要相同 重分区(重新分配):条件为消费者组中消费者的个数发生变化 (2) Offset存储 ZK、__consumer_offsets 手动维护:Flink CK 4) 数据量 100万日活 100条 1亿条数据 1K 100G 平均值:1亿/24*3600 = 1150 1M/s 高峰期:2-20倍 20000 5) 机器台数 3台 峰值速度/min(生产、消费) 6) 分区数 副本数 topic_log:6个分区 其他主题:2-3分区 副本:2-3 7) 保存天数 默认7天,修改为3天 8) 压测 读写速度 自带脚本 9) 监控
2、挂了
副本 上游是Flume,再上游为文件
3、丢了
生产者:ACK设置为0或者1 解决:ACK设置为-1,不丢数据:保证副本数>=2且ISR队列中>=2 消费者:先保存Offset,再保存数据本身 解决:先保存数据本身,再保存Offset
4、 重复了
生产者:ACK设置为-1 解决:幂等性、事务 消费者:先保存数据本身,再保存Offset 解决:事务 下游去重(幂等性)
5、积压了
消费速度 < 生产速度 提高消费速度 单次拉取的数据量 提高下游处理能力:并行度、内存 增加分区数同时增加消费者数量:分区数只能增不能减
6、优化
内存 4-6G 挂了、丢了、重复、积压 7天 -> 3天 副本数 分区数
7、其他
突然来了一条特别大的数据:卡死 默认1M 能不能消费到3天前的数据?
Maxwell监控业务数据写入Kafka,然后通过Flink消费Kafka数据写入HBase,先写入了更新数据,再写入新增数据,数据乱序(Kafka如何保证 数据有序) [当数据到达三天以后删除能不能消费到
因为按照文件去删除 那么等所有数据全部到达三天才会被删除 这样就可以消费到三天前的数据]
七、Spark
1、入门
1) 运行(部署)模式 local StandAlone Yarn(Client Cluster) 2) 端口号 18080 4040递增 3) WordCount SparkContext sc sc.textFile("") .flatMap() .mapToPair() .reduceByKey() .saveAsTextFile("")
2、 SparkCore RDD
1) 五大属性 一个分区列表 作用于每个分区的一个函数 与其他RDD的依赖关系 []分区器:只有PairRDD才有分区器 []位置信息:优先将计算任务调度到数据所在节点,宁愿移动计算也不移动数据 2) 算子 (1) 直接法 常用的算子有哪些? 常用的转换算子有哪些? 常用的行动算子有哪些? 常用的带有Shuffle的算子有哪些? (2) 比较法 map与mapPartition foreach与foreachPartitions:写库操作时使用foreachPartitions map与foreach:有无返回值 repartition与coalesce:repartition调用的就是coalesce(numPartitions,true) reduceByKey与groupByKey:是否预聚合 (3) 计算法 aggregateByKey(初始值)(区内合并,区间合并):转换算子 初始值:给每个分区内每种Key一个初始值 区内合并:分区内部逐条计算 区间合并:分区结果逐条计算 • aggregate(初始值)(区内合并,区间合并):行动算子 • 初始值:给每个分区一个初始值,同时在区间合并时给定初始值 • 区内合并:分区内部逐条计算 • 区间合并:分区结果逐条计算 • val rdd = sc.makeRDD(Array("12","234","345","4567"),2) • rdd.aggregate("0")((a,b)=>Math.max(a.length,b.length).toString,(x,y)=>x+y) • "034"/"043" • rdd.aggregate("")((a,b)=>Math.min(a.length,b.length).toString,(x,y)=>x+y) • "11" 3) 血缘(依赖)关系 宽依赖:父RDD的一个分区被多个子RDD分区所依赖 窄依赖:父RDD的一个分区被单个子RDD分区所依赖 4) 任务切分 Application SC Job 行动算子 Stage 宽依赖 Task 当前阶段的最后一个RDD的分区数 5) 分区器 Hash Range(sortBy sortByKey) 6) 持久化 Cache CheckPoint 血缘 不切断 切断 位置 内存 一般HDFS 任务数 1 额外一个任务 使用场景: RDD复用 任务链很长且中间有一个Shuffle操作,那么需要在Shuffle后持久化 使用方式: 结合使用 rdd.cache() rdd.checkPoint() 7) 序列化 Java Kryo:比Java序列化快10倍 8) 共享变量 (1) 累加器 共享写操作:分布式求和 (2) 广播变量 优化方式:较大变量 <500M 变量特别大:第三方存储
3、SparkSQL DataFrame DataSet
数据读写 读数据:SparkSession对象 spark spark.read().json("path") spark.read().format("json").load("path") spark.read().load("path") //默认格式:parquet 写数据:df ds type DataFrame = DataSet[Row] DataSet[T] df.write().json("path") df.write().format("json").save("path") df.write().save("path") //默认格式:parquet
RDD DF DS:三者之间可以互相转换
自定UDF UDAF flatMap
4、Spark内核
内存模型 动态: 存储内存:Cache、广播变量 执行内存:计算 淘汰机制:不能是同一个RDD的不同分区,内存相同(同属于对内或者对外),LRUCache(最近最少使用) 提交流程 Yarn-Cluster模式
通信: Yarn:RPC 邮局模型: Spark:2.0之前 Akka 2.0之后 Netty Flink:Akka
Drive(ExecutorClient/ExecutorRef) -> Executor Executor(driverRef/DriverClient) -> Driver send()/ask() receive/receiveAndReply
Shuffle
HashShuffle(优化后的HashShuffle) 3.0没有了 与MR相同 n*m SortShuffle 2.0引入 2.3默认 n*2 ByPassSortShuffle:不做排序 不能是预聚合算子:死的,不可修改 Reducer个数在200以下:可以自己设置 UnSafeXXXShuffle
5、其他
1、Spark的提交流程: YarnCluster模式的提交流程
1>脚本启动执行
解析参数,创建客户端
提交任务信息到RM
2>RM启动AM
3>AM根据参数,启动Driver线程并初始化SparkContext
4>注册AM,申请资源
5>RM返回资源可用列表
6>主线程启动Executor
7>注册Executor,注册成功
8>创建Executor计算对象
9>告知Executor启动成功
10>Driver进行任务切分,分配任务
11>Executor通过线程池启动Task任务
12>AM向RM申请注销自己