CDH 6.3.3
hadoop 3.0.0
hbase 2.1.0
hive 2.1.1
impala 3.2.0
spark 2.4.0
kafka 2.2.1
scala 2.11.12
读:client请求namenode ,获取目标文件的元数据信息,namenode校检无误后,返回给client,client根据元数据与就近的datanode建立连接,获取block 块,并将block 块合并后,返回给client。
写:client 向 namenode发出写 的请求,namenode 检查是否路径存在,权限等,通过后,将操作写入editLog,并返回一个节点列表,给client,client根据元数据与列表中就近的DataNode进行连接,并将data与返回的节点列表一并发送给它,此后,client就与所有的DataNode节点建立 piepline管道,一个DataNode写完后会传给下一个DataNode,每个DataNode写完一个 block 后,会返回确认信息给namenode。同时进行下一个 block的写入,直到全部写入完成。
MR把拿到的 split 分配给相应的 task,每个task处理对应的split,split 以line的方式读取每一行数据,将这些数据加载到一个环形缓冲区中,当环形缓冲区达到 80%的时候,会将这些数据溢写到磁盘中,同时按照 k-v的方式进行分区,(默认采用hashpartition),同时在每个分区内进行排序,如果这时设置了setcombinerclass,则会对每个分区的数据进行combiner操作,还可以设置 output-compress,对数据进行压缩,最后merge,根据分区规则,将数据归并到同一个文件中,等待reduce端拉取,等到所有的maptask 任务结束后,会根据分区数量启动相应的数量的reduceTask,每个reducetask 从mapTask机器上拷贝相应分区的数据到本地的缓冲区,缓冲区不够就溢写到磁盘,待所有数据拷贝完毕后,进行归并排序,之后按照相同的key分组,最后调用 reduce() 方法进行聚合处理,生成的结果将以文件形式在hdfs中体现。
1.client 提交一个任务到Yarn,包括用户程序、 相关文件、applicationMasrer程序、启动AM(applicationMaster)命令。
2.RM(Resource Manager)分配第一个 container,并与所在的 NM(nodeManager)进行 通信,要求NM在container中启动 AM。
3.AM向RM注册自己,这样用户可以通过 RM查看程序的运行状态等,然后它准备为程序的各个任务申请资源,并监控他们的 运行状态直到任务结束。
4.AM以轮询的方式通过RPC协议与RM通信,申请和领取资源。
5.AM领取到资源后,会向申请到的Container所在的NM进行通信,要求NM在container中启动任务。
6.任务启动。NM为要启动的任务配置好环境变量、jar包、二进制文件等,并将启动命令写在一个脚步中,通过改脚步运行任务。
7.NM与相应的AM保持RPC通信,汇报自身任务的运行进度与状态,以让AM在任务失败时,可以重启任务。
8.任务结束,AM向RM通信,要求注销和关闭自己。
NameNode: 集群的主节点,保存元数据、副本数、文件目录树等信息
DataNode:真正存放数据的节点,汇报block块的状态
SceondNameNode: 检查点节点,NameNode日志高可用的关键,定期的对 edits 文件和 FsImage 文件进行合并,防止元数据丢失
Edits:记录数据的写操作,体现了HDFS的最新状态
fsImage: 集群中元数据的一个永久性检查点,用于故障恢复
因为只有集群重启时,edits 才会和 FsImage 文件进行合并,因此为了防止 edit文件越来越大,导致重启时,文件的合并耗时过长,因此引入 检查点机制。
“Fsimage" 和”Edits",SecondaryNameNode 定期 对 FsImage 和 Edits文件的合并来保证NameNode中数据的高可用
此时我们会找到block另外的副本(一个block块有3个副本),并且通过FSData InputStream进行记录,以后就不再从中断的副本上读了。
由于心跳机制的存在,dataNode 会定时向 nameNode 发送blockReport ,一旦dataNode 挂掉后,nameNode,会在其余副本所在节点向 nameNode 报告时,向其他的副本所在的任一节点发送指令,使其拷贝本身的副本给另外的正常节点,保证副本数量为设定的值。
因为从DataNode上读数据是通过网络来读取的,这说明会存在读取过来的数据是不完整的或者是错误的情况。
DataNode上存储的不仅仅是数据,数据还附带着一个叫做checkSum检验和(CRC32算法)的概念,针对于任何大小的数据块计算CRC32的值都是32位4个字节大小。此时我们的FSData InputStream向DataNode读数据时,会将与这份数据对应的checkSum也一并读取过来,此时FSData InputStream再对它读过来的数据做一个checkSum,把它与读过来的checkSum做一个对比,如果不一致,就重新从另外的DataNode上再次读取。
之后FSData InputStream会告诉NameNode,这个DataNode上的这个block有问题了,NameNode收到消息后就会再通过心跳机制通知这个DataNode删除它的block块,然后再用类似上面3中的做法,让正常的DataNode去copy一份正常的block数据给其它节点,保证副本数为设定值。
粗略来说:Hbase 主要由 ZooKeeper,HMaster , HRegion Server 三部分组成。
Hbase Master 负责Region的分配,DDL(创建,删除table)等操作
Region Server 负责处理数据的读写请求,客户端请求数据时直接和 Region Server 交互
zookeeper 负责维护和记录Hbase集群状态
1.长度限制 (最好16字节内)
2.散列原则(rowKey要打散,避免热点写)
3.唯一性
1.加盐 (rowKey 前添加随机数)
2.hash
3.反转、时间戳反转追加到 key的末尾
实例: 主键+“|”+加密后的时间戳
参考: https://www.talkwithtrend.com/Question/432297
https://segmentfault.com/a/1190000019959411
读:
1.Client 请求ZK 获取 Meta Table 所在的Region Server的地址
2.Client 查询这台管理 meta table 的Region Server,获取本次查询的 rowKey 由哪台Region Server管理。Client会缓存这个信息,以及Meta Table 的位置信息。
3.Client 直接向目标 Region Server 进行访问,先从MemStroe 上读,没有再从StroeFile 上读 获取数据。
写:
1.Client 请求 ZK 获取Meta Table 所在的 Region Server 所在的位置
2.根据 nameSpace 、表名、rowKey、以及meta 表,找到写入数据对应的 Region 信息。
3.找到对应的 Region Server ,把数据先写到 WAL(Wrtie Ahead Log),然后写到 MemStroe。
4.当 MemStroe 达到阈值后,会把数据刷成磁盘上的StroeFile 文件。
5.当多个 StroeFile 文件达到一定大小后,会触发 compact 合并操作,合并为一个 Store File ;而当 这个文件大小超过一定的阈值后,会把当前的 Region 分割为两个,并由 Hmaster 分配给相应的 HRegion Server ,实现负载均衡。
1.提交SQL到hive
2.查询元数据
3.生成逻辑计划,优化逻辑计划
4.生成物理计划,优化物理计划
5.执行物理计划
6.封装结果集,返回数据
1.内部表:创建时,数据会被移动到数仓指定的目录下;删除时,元数据和数据一并删除
2.外部表:创建时,仅记录数据所在的位置,不进行移动;删除时,只删除元数据,不删除数据
3.分区表:根据表中的某个字段进行分区,类似于文件夹。例如:日志文件,根据时间,每天一个分区
4.分桶表:相比分区表,更加细粒度的划分,根据表中某个字段的hash值进行分割,类似于一个文件拆分为多个文件。
5.临时表:储存在用户的暂存目录中,并在会话结束后进行删除
order by :全局排序,只有一个 reduce 耗时长
sort by : 局部有序,不保证多个reduce之间有序,只是单个reduce有序
distribute by: 控制map的分发结果,具有相同字段的map分发到同一个reduce
cluster by: 相当于是 distribute by + sort by 【只能是降序】
数据倾斜:数据分布不均匀,有的过分多,有的太少,导致处理数据的时候,有的很快,有的特别慢,从而导致任务一直无法完成。
根本原因:key 的分布不均匀。
解决办法:1: 合理设置map数
①.小文件合并:CombineHiveInputFormat
②.复杂文件增加map数:调整切片最大值,maxsize,使其小于 block size
2.: 合理设置 reduce 数
①:set mapreduce.job.reduces= N
3.打乱集中的key,使其进入不同的reduce
https://blog.csdn.net/qq_43259670/article/details/105927827?spm=1001.2014.3001.5506
hive调优,一般通过 hive-site.xml 或者 客户端配置完成,一般的调优策略有:
①:jvm重用
②:合并block 减少 task 数量
③:开启小文件合并
④:开启数据压缩
⑤:有数据倾斜时进行负载均衡
1.producer : ①磁盘顺序写 ② MMF 内存映射文件
2.consumer: ①zero-copy
幂等性:一般而言是指,对于同一个资源,一次请求和多次请求的结果对资源本身应该是完全一致的。
(比如电子支付,由于网络延迟或者手机卡顿等原因,超市的收银员扫了你2次收款码,这时候,你的电子钱包应该要做到只被扣除一次,不能多次扣除,而要做到这一点,①要保证订单有唯一的id ②处理端要记录下已经处理过的请求,如果下一条来的id已经存在,则丢弃掉不能处理)kafka的幂等性是对生产者而言的,具体做法是 kafka对每一条消息添加一个 sequence number,(每条消息对应一个分区,不同分区的消息不会存在重复)而broker会储存这个sequence number,当下一条消息来的时候,只有 sequence number 比上一条的>1,则保留,否则丢弃。
消息丢失:
produce:
①ack设置了0,导致生产者发送消息后,不确认分区副本是否收到,如果失败,就会丢失。 ②ack设置了1,只有leader保存了消息,就返回成功,follower未同步,leader就挂掉。
解决办法: 设置 ack = all
consumer:
①自动提交了offset,但是后续业务逻辑未处理完就失败 解决办法:手动提交偏移量,待业务逻辑处理完后提交
消息重复:
producer:
①发送一条消息,副本已保存,但是因为网络等多种原因未返回成功,多次重试 解决办法:开启kafka的幂等性
consumer:
①消费端在消费过程中挂掉没有及时提交offset,另一个消费端拿取了之前的记录进行消费 解决办法:在下游程序做幂等性
https://blog.csdn.net/weixin_43230682/article/details/107317839
ISR: 与leader保持同步的follower集合 (In-Sync Replicas)
AR:每个分区下的所有副本统称 (Assigned Replicas)
LEO:每个分区最后一条消息的位置 (log Eed Offset)
HW: 一个分区对应的ISR中最小的LEO作为 HW (High Watermark)
1.kafka的每一个分区内部是有序的,因此只要保证需要有顺序的数据都向同一个分区写就可以。
kafka自身的分区策略:
①用户给定分区号,发送数据到指定分区
②没有给定分区号,但是有Key,根据key取hash进行分区
③ 没Key没分区号,轮询分区
④ 自定义分区
2.一个分区只能对一个消费者使用,因此要保证顺序消费,就要:
①:消费者单线程处理消息
②:写N个队列,将具有相同Key的消费储存在同一个队列里,对于N个线程,一 个线程消费一个队列即可
1.用户通过 Spark-Submit 提交代码至服务器,创建SparkContext,在SparkContext初始化的时候会创建DAGScheduler 和 TaskScheduler
2.初始化的同时,向ClusterManager注册Application并申请资源
3.ClusterManager 会使用自己的资源调度算法,在集群的worker 节点上,启动多个 Executor
4.Executor 会反向注册给Driver ,结束sparkcontext 的初始化。
5.调用 DAGScheduler 完成任务阶段的划分
6.每一个stage 创建一个 taskset
7.taskScheduler 将 taskset 分发给 executor 进程,完成计算。
弹性分布式数据集,是spark中最基本的数据抽象,它代表一个不可变,可分区,内部元素可并行计算的集合
创建方式:①makeRdd,通过集合创建
②使用外部数据源创建,如HDFS
③通过其他RDD的结果创建
转换算子: map、flatmap、filter、join、repartition、coalsece、distinct 、groupByKey 、reduceByKey
动作算子:collect 、 foreach 、take 、first 、count、 saveAsTextFile
宽依赖:多个子RDD的分区依赖同一个父RDD的分区
窄依赖:每一个父RDD的分区最多被子RDD的一个分区使用
根据RDD之间的依赖关系,遇到一个宽依赖就划分一个stage,宽依赖表示数据有shuffle过程,即可以认为遇到数据shuffle就产生一个stage,划分stage有利于形成DAG图,方便在一个stage内达到数据执行效率的最大化,实现流水线计算。
job : 遇到一个action 操作,就划分一个job,一个job中包含一个或多个stage
stage:遇到一次shuffle就划分一个stage
task:RDD的有多少的partition就有多少task,是stage中的一个执行单元,一个stage就是一个taskset
1.修改序列化机制,采用 Kryo优化序列化性能
2.提高并行度
①:设置 task的数量
②:repartition ,给rdd重新分区
3.RDD的重用和持久化
4,使用广播变量,广播小数据
5,减少使用会产生shuffle的算子
6.使用高性能的算子
①:如用 reduceByKey 替代 groupByKey
②:用mapPartitiond 替代 map
③:用 foreachPartitions 替代 foreach