大数据处理组件

HDFS : 数据存储		
	Hadoop项目的核心子项目,是分布式计算中数据存储管理的基础,是基于流数据模式访问和处理超大文件的需求而开发的
	具有的高容错、高可靠性、高可扩展性、高获得性、高吞吐率等特征为海量数据提供了不怕故障的存储,为超大数据集(Large Data Set)的应用处理带来了很多便利。

hdfs优点:
		1、高容错性
			1)数据自动保存多个副本。它通过增加副本的形式,提高容错性
			2)某一个副本丢失以后,它可以自动恢复,这是由 HDFS 内部机制实现的,我们不必关心。
		2、适合批处理
			1)它是通过移动计算而不是移动数据
			2)它会把数据位置暴露给计算框架。
		3、适合大数据处理
			1)处理数据达到 GB、TB、甚至PB级别的数据。
			2)能够处理百万规模以上的文件数量,数量相当之大。
			3)能够处理10K节点的规模	
		4、流式文件访问
			1)一次写入,多次读取。文件一旦写入不能修改,只能追加。
			2)它能保证数据的一致性。
		5、可构建在廉价机器上
			1)它通过多副本机制,提高可靠性。
			2)它提供了容错和恢复机制。比如某一个副本丢失,可以通过其它副本来恢复。

HDFS 缺点(不适用适用HDFS的场景):
		1、低延时数据访问 
			1)比如毫秒级的来存储数据,这是不行的,它做不到。
			2)它适合高吞吐率的场景,就是在某一时间内写入大量的数据。但是它在低延时的情况下是不行的,比如毫秒级以内读取数据,这样它是很难做到的。
		2、小文件存储 
			1)存储大量小文件的话,它会占用 NameNode大量的内存来存储文件、目录和块信息。这样是不可取的,因为NameNode的内存总是有限的。
			2)小文件存储的寻址时间会超过读取时间,它违反了HDFS的设计目标。
		3、并发写入、文件随机修改
			1)一个文件只能有一个写,不允许多个线程同时写。 
			2)仅支持数据 append(追加),不支持文件的随机修改。

HDFS原理剖析:
	1.HDFS工作机制:
		(1)概述:
			1)HDFS 集群分为两大主要角色:namenode、datanode (secondarynamenode 和 client)
			2)namenode 负责管理整个文件系统的元数据,并且负责响应客户端的请求
			3)datanode 负责管理用户的文件数据块,并且通过心跳机制汇报给 namenode
			4)文件会按照固定的大小(dfs.blocksize)切成若干块后分布式存储在若干台 datanode 上
			5)每一个文件块可以有多个副本,并存放在不同的 datanode 上
			6)datanode 会定期向 namenode 汇报自身所保存的文件 block 信息,而 namenode 则会负责
				保持文件的副本数量
			7)HDFS 的内部工作机制对客户端保持透明,客户端请求访问 HDFS 都是通过向 namenode
				申请来进行
				
		(2)写流程:
			1、客户端向namenode发送数据上传的请求(包含一个很重要的信息:数据长度信息)
            2、namenode接收客户端的请求后会进行一系列的检查工作:
            	<1>:文件是否存在,如果存在会报错
            	<2>:上传文件的父目录是否存在,如果不存在会报错
            	<3>:权限检查  等等
            3、namenode检查通过,会向客户端返回存储的节点信息
            	返回节点有一个原则:就近原则(内部有一个计算距离的公式)
            	优先返回客户端所在节点
            	返回同机架的节点
            	返回不同机架的节点
            	不同数据块的存储节点信息
            4、客户端接收到namenode返回的响应后,会进行一次逻辑切块(物理切分之前的准备)
            	切块分为物理切块(真实的切分)和逻辑切块(概念上的切分)
            5、开始准备文件上传
            6、构建文件上传的通道(pipeline):根据块id依次进行构建,将同一个块的所有存储节点
                 构建成一个数据流通道,
            7、开始真正进行文件上传,文件上传过程中会边进行上传边进行切分块,
                 上传的时候是以package(512kb)为单位进行文件上传,上传的过程中先上传到
                 一个节点中,先写到内存中,内存中每当接收到一个package就可以向下一个
                 节点传递,同时内存中的数据还会持续写向磁盘里;
            8、当第一个块的数据上传完成,则通道关闭
            9、开始上传第二个块,重复第6、7、8的动作
            10、所有的块上传完成之后,会向客户端返回结果:数据上传成功
            11、客户端向namenode返回信息,告知数据上传成功
            12、namenode更新元数据
		(3)读流程:
			1、客户端向namenode发送文件下载请求
			2、namenode在自己的元数据库中进行查询,如果查询到则会返回给客户端数据的块及副本存储节点,
				如果查询不到会报错。
			3、客户端拿到了数据块的存储节点,会先进行第一个数据块的下载,
				进行数据下载的时候也是就近原则
			4、第一块下载完成后会生成一个crc文件,和上传时候的.meta文件进行文件完整度校验
				(校验的是起始偏移量和末尾偏移量之间的内容),如果校验成功,则认为第一个块下载成功
			5、进行第二个块下载,重复第3、4
			6、所有的数据块下载成功后向namenode发送数据下载成功的响应

	2.NameNode工作机制:
		(1)NameNode职责:
			1)负责客户端请求(读写数据请求)的响应
			2)维护目录树结构(元数据的管理:查询,修改)
			3)配置和应用副本存放策略
			4)管理集群数据块负载均衡问题
		(2)NameNode元数据管理:
			元数据:抽象目录树,数据与块的映射,块的存储位置
			两种存储方式:
			1)内存:内存元数据 metadata	
				时刻保存着最新的元数据
				比磁盘中元数据多了块的存储位置
			2)磁盘:磁盘元数据镜像文件 fsimage_0000000000000000555
									   fsimage_0000000000000000555.md5   加密文件
					等价于	edits_0000000000000000001-0000000000000000018
							……
							edits_0000000000000000444-0000000000000000555
							合并之和
				    数据历史操作日志文件 edits_0000000000000000001-0000000000000000018
					数据预写操作日志文件 edits_inprogress_0000000000000000556
					seen_txid:合并点  记录的下次需要合并的edits文件的编号
			metadata = 最新 fsimage_0000000000000000555 + edits_inprogress_0000000000000000556
			metadata = 所有的 edits 之和(edits_001_002 + …… + edits_444_555 + edits_inprogress_556)
		(3)VERSION(存放 hdfs 集群的版本信息)文件解析:
			#Sun Jan 06 20:12:30 CST 2017 ## 集群启动时间
			namespaceID=844434736 ## 文件系统唯一标识符
			clusterID=CID-5b7b7321-e43f-456e-bf41-18e77c5e5a40 ## 集群唯一标识符
			cTime=0 ## fsimage 创建的时间,初始为 0,随 layoutVersion 更新
			storageType=NAME_NODE ##节点类型
			blockpoolID=BP-265332847-192.168.123.202-1483581570658 ## 数据块池 ID,可以有多个
			layoutVersion=-60 ## hdfs 持久化数据结构的版本号
		(4)查看文件:
			查看 edits 文件信息:
			hdfs oev -i edits_0000000000000000482-0000000000000000483 -o edits.xml
			cat edits.xml
			查看 fsimage 镜像文件信息:
			hdfs oiv -i fsimage_0000000000000000348 -p XML -o fsimage.xml
			cat fsimage.xml
	3.DataNode工作机制:
		(1)DataNode 作用:
			1)真正的存储数据
			2)处理客户端的真正的读、写的请求
			3)向namenode发送心跳报告
		(2)Datanode 掉线判断时限参数
				datanode 进程死亡或者网络故障造成 datanode 无法与 namenode 通信,namenode 不会立即
			把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长。HDFS 默认的超时时长
			为 2*5 分钟 + 10*3 秒。
	4.SecondaryNameNode工作机制:
		(1)secondarynamenode作用:
			1)备份元数据
			2)帮助namenode进行checkpoint,分担namenode的压力
		(2)checkpoint---元数据的合并流程
			checkpoint:每隔一段时间,会由 secondary namenode 将 namenode 上积累的所有 edits 和一个最新的
			fsimage 下载到本地,并加载到内存进行 merge 的过程。
			1)secondarynamenode 向 namenode 发送请求,询问有没有需要合并的文件
			2)namenode 对 secondarynamenode 响应,需要进行合并
			3)secondarynamenode 开启 checkpoint
			4)namenode 将正在编辑的文件进行回滚,提交,将编辑状态变为历史状态,同时会生成一个新的编辑日志文件
				来接收当前的请求日志
			5)secondarynamenode 会将历史日志文件和 fsimage 文件拉取过来
			6)secondarynamenode 会把edits文件和fsimage文件合并
			7)形成新的fsimage文件
			8)secondarynamenode将合并完成的fsimage文件发送给namenode
		(3)合并点:触发合并的条件
			1)时间节点  3600s=1h
			2)元数据条数节点    100万条数据
			两个条件只要满足一个就会触发checkpoint过程

MapReduce : 基于磁盘的分布式数据计算引擎
	MapReduce:
	1.概念:
		MapReduce 是一个分布式运算程序的编程框架,是用户开发"基于 Hadoop 的数据分析应用"
	的核心框架
		MapReduce 核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布
	式运算程序,并发运行在一个Hadoop集群上 
	2.整体结构:
		MRAppMaster:MapReduce Application Master,分配任务,协调任务的运行
		MapTask:阶段并发任务,负责 mapper 阶段的任务处理 YARNChild
		ReduceTask:阶段汇总任务,负责 reducer 阶段的任务处理 YARNChild
	3.shuffle过程:
		(1)将文件按照文件大小计算分成多个块,每个块随机放入datenode中,一般为一个datanode放一个块
		(2)按照默认的分片,每个块分一个切片
		(3)每一个切片对应着每一个maptask,maptask里面有继承Mapper的自定义类,然后将数据写入到
			收集器中(context.write(k,v))
		(4)收集器再将数据写入到环形缓冲区中
		(5)环形缓冲区有赤道,在赤道的两边一边进行元数据存储,一边进行原始数据存储,当环形缓冲区
			(默认是100M)达到阈值80%时,开始往磁盘中溢写,剩下的20%继续接收数据,当20%也满了之后,
			进入阻塞状态,直到溢写结束
		(6)文件溢写到磁盘之前先进行二次排序,先按分区排再在每个分区内按key排,一个索引,一个数据文件
		(7)溢写完成之后,可能会产生多个溢写文件,将多个溢写文件进行归并排序,
			合成一个溢写文件spill_finish
		(8)MRAppMaster获取到maptask的进度完成后,返回给reduce
		(9)reduce默认会开启5个线程池,用来抓取数据
		(10)将map中分好区的溢写文件按区号分别抓取,然后进行归并排序合成一个分好区分好key的文件,
			将这些数据进行默认或者自定义分组
		(11)reducetask读取分组的数据,有几个区就有几个reducetask,reducetask里面有继承Reduce的自
			定义类,然后将数据写出到hdfs中(context.write(k,v)),通过FileOutputFormat设置的路径,
			文件格式是part-r(reduce)-00000,part-r(reduce)-00001,有几个区就有几个文件,map输出的文件
			是part-m(map)-00000。

YARN   : 资源调度
	YARN是Hadoop 2.0中的资源管理系统,它的基本设计思想是将MRv1中的JobTracker拆分成了两个独立的服务:一个全局的资源管理器ResourceManager和每个应用程序特有的ApplicationMaster。

其中ResourceManager负责整个系统的资源管理和分配,而ApplicationMaster负责单个应用程序的管理
resourcemanager:
主节点:
ASM:ApplicationsManager
负责管理所有的application----mr计算程序----wordcount程序
负责管理application的状态,分配application的运行的资源
调度器:
负责每一个application任务的资源调度
负责application的调度
FIFO:
FIRST IN FIRST out
单一队列调度器
先提交的任务先执行 后提交的任务后执行
FAIR:
公平调度器:
第一个任务来了 全量跑 所有的资源全部跑
第二个任务来了:
两个任务平均分配资源 各占用一半的资源
第三个任务: 各占1/3
CAPACITY:
计算能力调度器:
多个队列 每个队列都是先进先出模式
手动设置
任务1:1T 任务2:9T
根据实际的任务量进行资源配置
10% 90%
根据不同的业务部门:
报表:60% 其他:40%
路面:70%
桥梁:30%
nodemanager:
从节点:真正负责跑数据的 给计算程序提供资源的
虚拟资源容器的方式:
Container:封装了一定的cpu io 网络 及内存等一些资源
服务器:
128G 8*12=96T
Container:内存:2g 磁盘:1T

Container----1个maptask任务/1个reducetask任务
				小文件执行的时候:
					container的启动和销毁过程的时间大于计算的时间  不划算
					大量小文件的时候:
						uber:false/true
						拼车模式运行-----一个container中可以运行10个maptask的小任务

yarn的资源调度:
		1)客户端向rm发送提交job命令
		2)rm会为该job分配一个节点,并在这个节点启动MRAppMaster
		3)这个节点会先启动container,并在这个container中启动mrappmaster
		4)mrappmaster向rm申请资源,启动maptask和reducetask任务
		5)rm向mrappmaster返回maptask或reducetask对应的节点(优先数据本地化原则,同机架,同机房)
		6)到对应的节点启动maptask任务(具体在节点中先启动container,在container中启动maptask)
		7)启动reducetask任务(原则是有一个maptask执行完成,也是在container中启动)
		8)maptask和reducetask需要向mrappmaster汇报运行进度和状态
			(当maptask或reducetask运行完成对应的container会销毁)
		9)mrappmaster向rm汇报(都完成的时候mrappmaster销毁)
		
	job提交过程:
		1)客户端向rm发送job提交的请求
		2)rm会向当前客户端返回application Id(application_时间戳_id)和共享资源路径(存储共享资源的)
			共享资源:<1>jar文件   <2>切片信息   <3>配置文件信息
			共享资源路径:/tmp/hadoop/staging...
		3)客户端会将共享资源放在共享资源路径下
		4)客户端向rm发送响应,告知共享资源放置完成,开始真正的提交job
		5)rm会为当前的job分配一个节点,并在这个节点启动mrappmaster
		6)在这个节点上先启动container,在container中启动mrappmaster
		7)mrappmaster会初始化这个job的工作簿(工作簿为了记录maptask和reducetask进度的)
		8)mrappmaster去共享资源路径下下载共享资源,获取maptask(切片)和reducetask(job.xml)的个数
		9)mrappmaster向rm申请资源运行maptask和reducetask(优先提交的是maptask的资源申请)
			采用的rpc通信	轮询式申请
		10)rm向mrappmaster返回相应的资源节点
		11)mrappmaster到对应节点上启动container,再启动maptask任务
		12)maptask任务到共享资源路径下 下载共享资源(应用程序:jar包)
		13)执行maptask任务
		14)maptask在运行过程中向mrappmaster汇报自己进度和状态
		15)当mrappermaster获取一个maptask执行完成,到对应的节点启动container,然后启动reducetask
			(reducetask开始进行数据的fetch  默认5个线程)
		16)reducetask到对应的共享资源下下载共享资源
		17)执行reducetask任务
		18)reducetask在运行过程中向mrappmaster汇报自己的进度和状态
		19)mrappmaster获取到maptask或者reducetask任务运行完成的时候,到对应的节点上销毁资源(销毁container)
		20)mrappmaster向rm汇报运行完成并注销自己

Hive  : 数据仓库
	hive仅仅相当于一个hdfs上的结构化数据管理的工具
			将hdfs上的结构化数据映射为一张二维表
	hive的元数据用关系型数据库存储的  默认的使用的是derby数据库
			一般情况下我们都会进行修改   改为mysql数据库进行元数据存储
	适用于离线的批量数据计算
	数据倾斜
	hive中的数据倾斜说白就是mapreduce的数据倾斜
	reducetask
	数据倾斜:每个reducetask计算的数据不均匀  每个分区中的数据不均匀造成的

hive中可以不产生数据倾斜的场景:1.select *    2.聚合函数    sum   count   avg  max
											hive中聚合函数会默认的在map端执行combine
	hive中可以产生数据倾斜的场景:
	1)group by不和聚合函数使用的时候
	2)join过程
	3)count(distinct)
	join中容易产生数据倾斜的场景:
		mapjoin----maptask的并行度---split----128M----并行度高    
		reducejoin----reducetask的并行度----分区---reducetask  datanode*0.95
			FileInbputFormat.addinputpath(/orderin)
			map端一次性读取到两个文件   按行解析   key:关联条件  value:打标记
		1)null参与连接
		id   昵称   null
			join的关联条件中出现了大量的null值     关联条件-----map端发送的key  on
			map端发送的key  大量的数据null   关联不上    分区,排序,分组
			所有的null值被分到一个分区中------一个reducetask中  剩下 的非null的数据
			数据中30%的数据null    10个分区   9个分区----70%  每个分区8%   1个分区===30%
			怎么解决:
				1)null值不参与连接
				select a.*,b.* from a join b on a.id=b.id and a.id is not null;

				select a.*,b.* from a join b on a.id=b.id and a.id is not null 
				union all 
				select a.* from a where a.id is null;
				2)将null值做特殊处理  null==新值
					null=====随机数  null+随机数
					nvl()
					null=====进行散列
					null123   null234   null456
					进行关联的时候
					map端进行发送的时候  分区的时候null123就会被分到不同的分区中
		2)数据类型不统一的时候
			a   id  int   name string
			b   id  string  age int    “23”    “23a”==null
			a.id=b.id    null
				解决方案:将数据类型进行修改   改成统一的数据类型
		3)大小表关联的时候
			reducejoin
			map---key
			淘宝数据  性别   男1:女3   男:数据少  女性数据中  数据多
			怎么办:
				mapjoin
				缺陷:大*小
			hive中默认的关联的  
			select * from a join b on a.id=b.id;
			mapjoin ?   reducejoin?
			1)hive.auto.convert.join  true:默认开启map端的join  false:不开启
				Default Value: false in 0.7.0 to 0.10.0; true in 0.11.0 and later (HIVE-3297)  
				Added In: 0.7.0 with HIVE-1642
				默认开启并不一定走   满足条件的时候才会走mapjoin
			2)hive.smalltable.filesize or hive.mapjoin.smalltable.filesize
			hive中参与连接的表中的最小表的大小限定
				Default Value: 25000000     25M
				hive中参与关联的表中小表大小不超过25M   -----mapjoin
				两个表都超过25M   ------   reducejoin
				Added In: Hive 0.7.0 with HIVE-1642: hive.smalltable.filesize (replaced by hive.mapjoin.smalltable.filesize in Hive 0.8.1)
				Added In: Hive 0.8.1 with HIVE-2499: hive.mapjoin.smalltable.filesize
				The threshold (in bytes) for the input file size of the small tables; if the file size is smaller than this threshold, it will try to convert the common join into map join.
			users:------30M   256G
			ratings:------1G------reducejoin
			可以强制执行mapjoin  强制将小表加载在内存中  执行mapjoin
			select * from user users a join ratings b on a.userId=b.userId;
			select 
			/*+mapjoin(users)*/
			* from user users a join ratings b on a.userId=b.userId;
			好处:避免数据倾斜

hive的优化:
		hive的优化---MR的优化
		1)合理选择排序:
			order by  全局排序
			sort by   局部排序
			cluster by   
			distribute by + sort by
		2)避免使用笛卡尔积    
		3) in/exists   性能低  left semi join
		4)maptask的合理设计
			maptask过小:启动或销毁的时间过长  真正处理数据的时间较少   不划算
			maptask过大:并行度不高  没有合理利用资源  128M
			针对小文件:
				1)先进行小文件的合并
				jvm重用的:
				一个maptask----yarnchild----container----jvm
				set mapred.job.reuse.jvm.num.tasks=5
		5)小文件合并
		6)		reducetask   datanode*0.95
		7)合理设计分区
			数据量比较大的时候,当我们需要频繁的访问某一个或某几个字段进行过滤分组  排序等查询
			这个时候需要将他建委分区表
			不建分区表:所有的数据都在一个表中  全表扫描  性能比较低  崩溃
			兼分区表的时候:分区字段   需要进行频繁过滤的字段   地区--》村落
			日志数据    日--日期--时间戳    month   day --- h
		8)合理设计分桶:
			生产中使用的比较少
			1)便于取样  提升取样的性能
			抽样语法:
				select * from student_bk TABLESAMPLE(bucket x out of y);
				x:取的第几个桶簇数据作为样本数据
				y:总共分成多少个桶簇  桶簇:多个桶或一个桶 半个桶  y=3   代表分3个桶簇   1个桶簇--1个桶   x=1   代表去的第一个桶簇的数据
				select * from student_bk TABLESAMPLE(bucket 1 out of 3);
				y=6     1个桶簇---0.5个桶   x=4
				select * from student_bk TABLESAMPLE(bucket 2 out of 6);

				32个桶    y=16   桶簇1:1   1+16   桶簇2:2 2+16
				桶簇的要求:一般是桶个数的因子或倍数
			2)提升join的性能
				大*小    mapjoin  /*+mapjoin()*/
				小*小   mapjoin
				大*大   reducejoin
					小*小----分桶
		9)join优化   mapjoin

ZooKeeper : 服务协调	分布式一致性算法的最完美实现  
	1.心跳机制
		集群主从模式,主节点namenode   从datanode,datanode和namenode直接是需要通信的,通信通过心跳的方式进行通信的,datanode向namenode会定期发送心跳报告,报告自己的存活状态,(和自己存储的块信息???)
		如果一个datanode宕机了,namenode怎么判定datanode一定宕机了?
			10次心跳报告接收不到,如果10次都接受不到这个时候namenode会主动检查,这个时候namenode向datanode发送检查报告,检查datanode是否真的宕机了,一次检查报告中可能存在网络延时或通信问题,namenode会发送两次检查,如果两次检查都没有得到回应,这个时候才认为datanode宕机。
			时间是多少?
				一次心跳报告的时间3s
				<property>
				  <name>dfs.heartbeat.interval</name>
				  <value>3</value>
				  <description>Determines datanode heartbeat interval in seconds.</description>
				</property>
				10次心跳报告  3*10=30s

				namenode向datanode发送一次检查的时间300000ms=300s=5min
				<property>
				  <name>dfs.namenode.heartbeat.recheck-interval</name>
				  <value>300000</value>
				  <description>
				    This time decides the interval to check for expired datanodes.
				    With this value and dfs.heartbeat.interval, the interval of
				    deciding the datanode is stale or not is also calculated.
				    The unit of this configuration is millisecond.
				  </description>
				</property>
				2次检查的时间  10min
			namenode判定一个datanode宕机时间:3*10+300*2=630s
			datanode前8次心跳报告都没有,第九次有了,不能判定宕机    下次再次进行判定宕机需要重新判定

分布式数据的一致性:
		CAP理论:
			1、一致性(Consistency)(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。        
				分布式系统中的数据怎么保证一致性    强一致性
				分类:
					强一致性:
						分布式系统中所有备份必须在每一时刻保持一致  有一个备份发生改动  
						其他的备份必须同时改动  要求最高的  实现上是最难的
					弱一致性:
						分布式系统中大部分备份只要在一定的时间延迟范围内达到一致就可以了         
					最终一致性:
						分布式系统中所有备份只要在最后的时间节点 可以达到一致就可以
						(等同于所有节点访问同一份最新的数据副本)
			2、可用性(Availability)(A):在集群中一部分节点故障后,在一定时间内,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
				分布式系统是否可以持续对外提供服务,如果集群中的某一台服务发生故障的时候,是否可以在有效的时间内返回有效结果   namenode的ha
			3、分区容错性(Partition tolerance)(P):在不同的网络分区内进行数据或计算的备份	hdfs的数据备份(机架策略  不同机架   不同的数据中心)
		CAP:强一致性   高可用性    高容错性

两大核心:
		文件系统:
			进入zookeeper的客户端:zkCli.sh
			help  查看所有的命令
			1)zookeeper的文件系统同linux的文件系统的相似 根目录是/
			2)zookeeper中文件系统的访问方式只有绝对路径的访问方式 没有相对路径的访问方式
			3)linux文件系统:文件   目录
			zookeeper中不存在文件的概念也不存在文件夹的概念   他有一个概念叫znode,既有文件的功能(存储数据),又有文件夹的功能(创建子节点)
			4)znode的分类:
				按照存储周期分:
					临时的节点:EPHEMERAL
						创建:create -e /test ''
					永久的节点:persistent 默认创建的节点
						创建:create /test ''
					临时节点只对当前客户端有作用  客户端退出临时节点会自动删除
					永久节点不会自动删除  要想删除 需要手动删除
				按有无编号分:
					永久无编号:
						create /bd1804 ''
						节点只能创建一次  在创建就会报节点已存在
					永久有编号:SEQUENTIAL  编号的  -s
						create -s /test01 ''
						Created /test010000000002
						create -s /test01/test001 ''
						系统会自动分配一个编号  编号是有父节点维护的  无论改父节点下创建的节点有无编号这个编号都会顺序递增  从0开始的   用于记录改父节点下子节点的个数
						有编号的节点可以创建多次  每次都会生成一个全新的编号
					临时无编号:
						create -e /test02 ''
						只能创建一次
					临时有编号:
						create -e -s /test03 ''
						可以创建多次
			5)临时节点不可以有子节点
				有子节点的节点一定是永久节点
			6)linux中每个目录存储的大小   有限制----磁盘
				znode存储的时候 每个znode存储的数据大小不要超过1M 最好不要超过1kb
				1)存储能力有限  只需要存储核心信息就可以了  状态信息
				2)最终要达到每个节点的数据一致性   如果存储的数据量过大一致性越难保证
			7)znode上的数据的存储份数  ==  节点个数
				zookeeper中节点有几个数据就存储了多少份 每个节点存储的数据是一摸一样的         	zookeeper的最终的存储能力仅仅只有一台机器的  取决于集群中最小的节点的存储
			8)可以对zookeeper的文件系统添加监听
				添加监听的对象是znode	
		监听机制:
			如果客户端对zookeeper上的数据感兴趣,那么就需要对这个数据添加监听,数据一旦发生变化  就会通知客户端
			监听事件:
				4类:
					nodedatachanged:节点内容发生改变的事件
					nodecreated    节点创建的事件
					nodedeleted    节点删除的事件
					nodechildrenchanged:子节点发生变化事件
			添加监听:watch  添加监听
				ls(getchidren)  查看节点下的子节点的列表
				get(getdata)
				stat
				exists(api)
			触发监听:
				create
				delete
				set
			注意:添加一次监听  监听只生效一次
				ls----NodeChildrenChanged
				get----NodeDataChanged	  NodeDeleted
		zookeeper就是运用自己的监听机制,监听自身的数据变化,最后将变化发送给感兴趣的客户端

zookeeper的应用场景:
	1.命名服务  很多场景下  需要命名全局唯一
		mysql中id字段    唯一的   递增的  维护比较好维护
		分布式的系统   id  赋值   唯一的  全局递增的 怎么办
			node01   node02   node03
			id=34 35   35
			这个时候可以使用zookeeper    有编号的永久节点
		命名服务的:
			节点名   添加监听
			value值上   对value值添加监听	
	2.配置文件管理:
		hadoop搭建的时候   3台机器   修改一台机器的配置文件  scp发送
			500台机器  499次  5min
			集群运行过程中修改配置文件   副本配置
			文件系统+监听  
	3.集群管理:
		1.datanode的上下线:
			namenode判断datanode宕机  -----  630s
			临时节点
		2.选主:
			zookeeper内置的选主的过程
	4.锁管理:
		读锁:共享锁  所有人都可以访问   有编号的节点
		写锁:排它锁    一个人访问    无编号的节点
	5.队列管理:
		fifo     有编号的节点

zookeeper的角色:
	文件系统(读+增删改/写)+监听机制
	leader:
		处理客户端的写请求  写请求被follower或observer接收,没有权利处理的,将这个请求转发给leader  
		为了保证集群的数据的最终一致性
		发起投票  公布决议
	follower(跟随者):
		处理客户端的读请求  并在主节点失效的时候发起选主  投票的权利 有选举权和被选举权  
		接收到客户端的读请求的时候  直接处理的投票
	observer(观察者):
		配置:server.4=hadoop04:2888:3888:observer
		没有投票权  也没有被投票的权利
		分担集群的压力   分担集群的读的压力
		对于zookeeper的文件系统来说:读》》》》写

zookeeper集群中节点的状态:
		looking(竞选状态)
		leading
		following
		observing
	对于一个已经运行了一段时间的zk集群来说,突然发现有一天leader挂了,这个时候集群面临一个重新选主的
	过程:
		当前的集群中存储了一定的数据  集群中理想状态下每个节点存储的数据一样的  
		zk的数据一致性是最终一致性  有可能节点之间的数据不一致的可能性,这个时候进行重新选主  
		仅仅依靠serverid可以吗?不合理  因为根据serverid选中的那个节点数据不一定是最新的数据,
		这个时候如果将这个节点作为主节点会造成数据丢失,这个情况是不允许   
	非全新集群的选主的依据:
			1)逻辑时钟:选举的过程中需要投票   逻辑时钟标志的就是投票的次数   
						 就是记录当前节点的投票的次数   每次投票就会自增
			2)数据版本:zxid   czxid mzxid pzxid  全局唯一的  顺序递增的   标志事件的提交顺序的   
						 zxid越大证明数据版本越新
			3)serverid
	过程:
		先根据逻辑时钟,如果逻辑时钟不统一,则先统一逻辑时钟
		当逻辑时钟一致的情况下,在进行比较数据版本,数据版本高的胜出,数据版本新的节点中比较serverid,
		最终serverid大的胜出
		
		如果是非全新集群选主:最终肯定数据版本最新的serverid大的胜出        
		最终选出来的leader肯定是集群中拥有最新数据的

zookeeper的数据同步:
	对于非全新集群重新选主之后  必然会面临数据同步问题	
	leader:集群中的最新的数据
	其他follower节点|observer节点数据同步的问题????
	1)follower向leader进行连接,并发送自己最大的zxid
	2)leader开始进行比较,将这个zxid和自己最大的进行比较
		确定同步点,follower zxid+1 ---leader zxid
	3)follower开始同步数据,同步数据的时候,不能对外提供服务的
	4)follower一旦完成同步,leader将follower的状态切为updated,
		这个时候follower就可以对外提供服务了

zk的数据更新:
	对于zk的数据更新leader的判断标准:
		如果有一半以上的节点更新数据完成,则认为数据更新完成;
		剩下的节点如果没有更新完成的,是不能对外提供服务的,什么时候更新完成,
		再对外提供服务。
	对于zk来说,最大能够承受多少个节点同时宕机?
		一半以下,如果是5台-----2台宕机

hadoop的ha:	ha(高可用high-avalible)
		解决完全分布式的namenode的单点故障问题
		ha中有两个namenode,两个namenode互为备份,一个active的另一个是standby的,active宕机的时候
		standby的namenode可以随时切换为active,保证集群可以正常运行   
		没有secondarynamenode(standby namenode)
	如果要想随时切换active namenode,必须保证:
		1)standby的元数据信息和active的元数据信息近实时一致
			fsimage:原始的是namenode格式化的时候生成的
					在一个主节点上进行格式化,将这个主节点的初始的
					fsimage发送给另外一个主节点;
					集群一开始运作,保证这两个namenode的数据一致的。
			edits:
					hdfs的操作日志
					active的namenode记录, 1h产生一个edits文件,
					standby怎么保证edits文件一致 ?      实时同步...
					将这个edits文件放在共享的文件系统上:
					high avalible with QJM(Quorum Journal Manager)
					QJM:共享文件存储的,这个系统的节点数最好是奇数台(3)
					只要挂掉不超过一半就可以接着运行
					hadoop自带了
		2)standby可以实时感知active的上下线
			zkfc:对namenode进行健康监控
				一个zkfc----1个namenode
			脑裂:一个集群中存在多个active namenode

HBase : 分布式数据库
	产生背景:
	GFS------HDFS    海量网页信息的分布式存储
	MAPREDUCE------MAPREDUCE         -------HADOOP   海量数据的计算问题
	BIGTABLE  大表------HBASE
		快速的查询----BIGTABLE-----索引的机制

nosql的分布式数据库	
	面向列存储的数据库:以列为单位进行存储  统一‘列’的数据会被存储在一个文件中
	mysql、oracle面向行存储的  一行数据不会被拆分的  肯定存储在一个文件中
	hbase的底层数据来存储在hdfs上

	hbase的特点:
		面向列存储的分布式的数据库
		1)介于传统关系型数据库和nosql之间
		2)不支持join等复杂查询
		3)支持事物  仅支持简单事物(行级)  不支持复杂事物
		4)底层数据存储格式byte[]  hbase擅长非结构化数据和半结构化数据存储  可以用于结构化数据的存储
			生产上hbase主要用于存储		结构化数据
		5)hbase无模式
			mysql----写
			hive-----读
	存储数据的特点:
		1.大:
			相对于传统数据库的   mysql数据库   千万级别的数据的时候  查询性能很低
			存储的数据量大   千亿级别  底层存储在hdfs  (hdfs可以无限进行横向扩展)
		2.面向列:面向列簇
			淘宝数据:100字段   20个
			行式存储   查询的时候  对所有的字段进行扫描查询
			1)减少数据扫描的范围
			2)数据存储的时候可以进行数据压缩  压缩比大
		3.稀疏存储
			30-40   null   行式存储中这些字段需要进行存储  会浪费存储空间
			null值不占用存储空间的
	hbase的存储数据的视图:
		主:hmaster   从:hregionserver
		region概念:
			类似于数据存储的文件个数
		行式存储中每一行包含相同的字段  字段名必须一致

	基本概念:
		行键(rowkey):
			一行的标识  行键相同的数据为同一行数据  类似于关系型数据库的主键
			特点:
				1)行键在hbase中默认的是按照字典顺序进行排序的
				2)行键设计的时候最好是长度8的倍数
			插入数据时候指定
		列簇/列族(family):  桶簇(一个或多个桶)
			一个或多个列  hbase底层存储的基本划分单元   一个列簇对应一个物理存储文件
			建表的时候指定  --  表结构的一部分
			每一行中的每个列簇下的列的名字可以不同

		列:列族下的单位    不需要建表的时候指定,他不属于表结构的一部分   插入数据的时候指定就可以
			不同的行指定不同的列名字
			特点:
				1)列簇中的列通常情况下具有相同io特性的一组列
					相同io特性:经常性一起访问(查询)的列  这些列就叫做相同的io(读写)特性
						人为划分的
					作用:减少磁盘io   跨文件查询的io
					经验告诉我们列族的个数最好不要超过3个  通常情况下我们存储1个列簇  多了2个
					一个列簇---一个物理存储文件
						原因:
							1)列簇越多存储的物理文件个数越多
							2)进行数据访问的时候跨文件查询的几率就越大
				2)列簇个数不要超过3个
		时间戳:
			没插入一个数据  都会有一个时间戳  作用:标识数据的版本  在hbase中同一个数据可以保存多个版本
			默认情况下版本信息就是当前系统时间戳
			默认情况下只保存最新版本的数据信息
		单元格:
			定位一个单元格需要哪些条件:
				行键+列簇+版本信息(列名)
	hbase中标扫描的3中方式:
		1)全表扫描
		2)按照rowkey的range(范围)进行扫描  hbase中数据按照rowkey字典顺序进行升序排序
		3)按照指定的某一个rowkey进行扫描  扫描一行
	hbase中数据查询流程:
		rowkey-----列簇-----列----时间戳

hbase的相关理论:
	几个概念:
		一个hregionserver----一个物理节点
		1.region概念:
			不是hbase物理存储的最小单元,hbase进行负载均衡和分布式存储的最小单元
			理解成一个逻辑概念===一定rowkey范围的数据(所有列族、列的数据)  hbase中按照rowkey的字典顺序进行排序的
			一个region只能存储在一个regionserver上,一个regionserver上可以管理多个region
			一个region只能包含一个表的数据
			默认情况下建表的时候只有一个region,这个region大小到达10G进行split(分裂) 取中间的rowkey进行一分为二   min_rowkey 00001      max_rowkey=06666   10G-----进行分裂  分裂成2个  去中间的rowkey=03333   将原来的region分成2个
				region1:rowkey 00001-03333     region2:03333-06666
					<property>
				    <name>hbase.regionserver.regionSplitLimit</name>
				    <value>1000</value>
				    <description>
				      Limit for the number of regions after which no more region splitting should take place.
				      This is not hard limit for the number of regions but acts as a guideline for the regionserver
				      to stop splitting after a certain limit. Default is set to 1000.
				    </description>
				  </property>
				 上面的参数是进行region分裂的限制  指的是当一个regionserver上的region达到这个值(1000)的时候,这个时候region将不再进行分裂

		2.Store:
			是物理存储的基本单元  一个store对应的就是一个列族
			有一个表两个列族    ---  2个store
		3.memstore:
			存储内存缓存  对应于一个store  作用:提升读写性能
			数据写入的时候先写入memstore   从memstore中进行数据的溢写
		4.StoreFile:
			一个store中会包含多个storefile(最终存储的文件)
			Hfile(hdfs)---StoreFile
	hbase的架构:
		store=memstore+多个storefile
		WALs(HLog--hbase log):write ahead logs   写前日志文件、预写日志
			写数据的时候先先写入到memstore(内存),存在数据安全的问题,这个时候需要记录一份写前日志数据,作用防止数据丢失  进行数据恢复   wals达到一定的阈值的时候也会进行日志回滚,将其回滚为oldwals  oldwals有一个存储周期
			  	<property>
				    <name>hbase.master.logcleaner.ttl</name>
				    <value>600000</value>
				    <description>Maximum time a WAL can stay in the .oldlogdir directory,
				    after which it will be cleaned by a Master thread.</description>
				  </property>
				达到这个周期的时候数据进行删除
		hbase的寻址机制:  查询某一个行键的时候的怎么找到对应的region
		0.96之前的:
			原始数据存储的时候行的方向上按region进行切分的  那么一个表会被切分成多个region,多个region可能存储在不同的regionserver上,这个时候在进行查询的时候最好可以先定位到某一个region,怎么定位?
			.meta表:原始数据region的索引
				原始数据存储的region地址  以及对应的rowkey范围
				mregion01:
				region01----<00000      hadoop02
				region02----00000--33333  hadoop03

				mregion02:
				region03----33333-66666   hadoop01
				region04----66666--99999  hadoop03
				region05---->99999     hadoop01
			原始数据中的一个region相当于.meta表中的一条数据,随着数据的不断增大,.meta表也是hbase中的一个表,存储的时候行的方向上也是以region进行划分,.meta表最初始的时候只有一个region,随着原始数据的region越来越多,.meta表越来越大,.meta表的数据达到region分裂的标准就会进行region分裂,这个时候.meta表会对应多个region
			-root-表:索引.meta表的  记录的是.meta表的region存储位置  以及rowkey范围
			-root-表也是hbase中的表  不过这个表示不会进行分裂的一个表   只有一个region
			-root-文件的region的存储位置存在zookeeper中
			mregion01   <33333   hadoop02
			mregion02   >33333  hadoop03   
			
			
			给定rowkey查询一个数据的时候:寻址的过程  
				1)先去访问zookeeper  获取-root表的存储地址   regionserver
				2)先找-root-文件  作用找.meta表的对应的region的存储位置     
				3)找.meta表所在的region   目的是找原始数据对应的region的存储位置
				4)找原始数据的对应的region  返回结果给客户端
					66666---->-root  发现mregion02---hadoop03
					hadoop03--mregion02---->region04----66666--99999  hadoop03
					hadoop03----region04  返回结果
		0.96之后  少-root文件
			寻址的时候:
				zookeeper--.meta
				1)zookeeper---.meta----原始数据的regionserver

hbase的几个角色的作用:
		zookeeper:
			1)存储寻址入口  -root-
			2)帮助hbase集群选主
			3)监控regionserver的存活状态  通知master
			4)hbase表中的schema(表结构  表有哪些列族)
		hmaster:
			1)负责hregionserver的负载均衡
				一个regionserver上管理几个hregion  平衡
			2)负责为分裂的region分配regionserver
			3)负责重新分配掉线的reginserver上的region的数据
		hregionserver:
			1)负责自己管理的region的分裂
			2)负责管理自己存储的region
		hmaster在没有region分裂,掉线的情况下可以允许一定时间的宕机的   不影响数据的访问的
	hbase的读写过程:
		写:put /delete   put 'stu_info','rk0034','info:name','zs'
			1)请求发送给zookeeper   经过3(zookeeper---root---.meta---原始数据)次往返定位定位需要插入的region的位置regionserver
			2)客户端找到对应的regionserver中的region进行数据的插入
				写入数据之前进行一系列的检查  检查表  列族是否正确  如果正确则允许插入
				写入的时候没有指定版本自动插入版本信息  获取的当前系统的时间
			3)将操做写到WALs  做灾难备份使用
			4)写入数据的时候根据列族信息确定写入哪一个Store中,先写入到memstore中,memtore写满的时候进行写出到磁盘---StoreFile

		读:  get 'stu_info','rk0034','info:name'
			1)请求发送给zookeeper   经过3(zookeeper---root---.meta---原始数据)次往返定位定位需要插入的region的位置regionserver
			2)客户端到对应的regionserver上进行数据读取
			3)找到这个regionserver中对应的region的列族的store,先在这个regionserver的store的memstore进行查找  如果memstore存在则直接返回
			4)如果memstore中没有  这个时候去磁盘的hfile文件读取  返回
	rowkey设计问题:
		1)唯一的原则  行标识
		2)长度不要过长   10-100byte  8的倍数
			1)因为写数据的时候先写入内存中  如果行键太长占用很多的内存存储空间
			2)每一个列族文件中storeFile中都会存储行键的相关信息,行键太长占用大量的空间
		3)*****尽量散列
			为了避免写数据热点问题  如果rk过于集中  就很可能造成某一个region的数据写入时候数据热点问题

			数据散列的方式有哪些:
				1)hash值  散列算法
				2)加盐   将原来的  随机数+rowkey
				3)翻转   手机号  13552785495    59458725531
							时间戳	  时间戳翻转	
				4)加密  md5   uuid	
	列族的设计:
		不要太多   2-3个就可以
		原则上一个列族存储的数据是具有相同的IO特性的

Sqoop :  数据迁移工具
	客户端工具
	大数据平台数据(hadoop   hive   hbase等)  迁移  传统数据库的数据
	迁入:关系型数据库到大数据平台  import
	迁出:大数据平台导出到传统的关系型数据库  export
	底层转化为MR任务
	本质:将数据迁移的命令转化为MR
	安装的时候只需要一个节点
	MR程序:功能将mysql中的数据导入到hdfs目录  数据输入---传统的关系型数据库的数据输入
		将hdfs的数据写出mysql中   输出----输出到传统的关系型数据库
		sqoop底层只需要重新定义输入inputformat  输出outputformat

	sqoop的使用:
	sqoop help	
	  codegen            生成java代码  pojo
	  create-hive-table  导入数据到hive表中
	  eval               
	  export             导出
	  help               
	  import             导入   关系型数据库----大数据平台
	  import-all-tables  将库下的所有的表导入hdfs
	  import-mainframe   Import datasets from a mainframe server to HDFS
	  job                Work with saved jobs
	  list-databases     显示所有数据库
	  list-tables        显示所有表
	  merge              Merge results of incremental imports
	  metastore          Run a standalone Sqoop metastore
	  version            版本信息
	mysql----hdfs中   导入
		自己实现mr	map   part-m-00000
功能:
	导入:help_keyword
	--connect  mysql连接url
	--driver   驱动  不需要指定
	--username   mysql的用户名
	--password    mysql的密码
	-m  maptask的并行度
		1.mysql--导入-hdfs
		--table指定mysql中的表

sqoop import
–connect jdbc:mysql://localhost:3306/mysql
–username root
–password 123456
–table help_keyword
-m 2
默认路径:/user/hive/warehouse
默认的分割符:,
指定分割符 指定存储路径

Azkaban/oozie/HUE : 任务调度系统

flume : 数据采集工具
	Flume是分布式,高可用,基于流式计算的,用于收集、聚合、移动大量日志数据的框架
	Flume 的优势:可横向扩展、延展性、可靠性
	Flume 的数据流由事件(Event)贯穿始终。事件是 Flume 的基本数据单位,
	它携带日志数据(字节数组形式)并且携带有头信息,这些 Event 由 Agent 外部的 Source 生成,
	当 Source 捕获事件后会进行特定的格式化,然后 Source 会把事件推入(单个或多个)Channel 中。
	你可以把Channel 看作是一个缓冲区,它将保存事件直到 Sink 处理完该事件。
	Sink 负责持久化日志或者把事件推向另一个 Source。
	Flume 以 agent 为最小的独立运行单位。一个 agent 就是一个 JVM。单 agent 由 Source、Sink和 
	Channel 三大组件构成,
	flume三大核心组件:
		Event:
			Event 是 Flume 数据传输的基本单元。
			Flume 以事件的形式将数据从源头传送到最终的目的。
			Event 由可选的 header 和载有数据的一个 byte array 构成。
			载有的数据度 flume 是不透明的。
			Header 是容纳了 key-value 字符串对的无序集合,key 在集合内是唯一的。
			Header 可以在上下文路由中使用扩展
		Client:
			Client 是一个将原始 log 包装成 events 并且发送他们到一个或多个 agent 的实体
			目的是从数据源系统中解耦 Flume
			在 flume 的拓扑结构中不是必须的。
			Client 实例
			flume log4j Appender
			可以使用 Client SDK(org.apache.flume.api)定制特定的 Client
		Agent:
			一个 Agent 包含 source,channel,sink 和其他组件。
			它利用这些组件将 events 从一个节点传输到另一个节点或最终目的地
			agent 是 flume 流的基础部分。
			flume 为这些组件提供了配置,声明周期管理,监控支持。
		Source:
			Source 负责接收 event 或通过特殊机制产生 event,并将 events 批量的放到一个或多个
		Channel:
			包含 event 驱动和轮询两种类型。
			不同类型的 Source
			与系统集成的 Source:Syslog,Netcat,监测目录池
			自动生成事件的 Source:Exec
			用于 Agent 和 Agent 之间通信的 IPC source:avro,thrift
			source 必须至少和一个 channel 关联
		Agent 之 Channel:
			Channel 位于 Source 和 Sink 之间,用于缓存进来的 event
			当 sink 成功的将 event 发送到下一个的 channel 或最终目的 event 从 channel 删除
			不同的 channel 提供的持久化水平也是不一样的
			Memory channel:volatile (不稳定的)
			File Channel:基于 WAL(预写式日志 Write-Ahead logging)实现
			JDBC channel:基于嵌入式 database 实现
			channel 支持事务,提供较弱的顺序保证
			可以和任何数量的 source 和 sink 工作
		Agent 之 Sink:
			Sink 负责将 event 传输到吓一跳或最终目的地,成功后将 event 从 channel 移除
			不同类型的 sink存储 event 到最终目的地终端 sink,比如 HDFS,HBase
			自动消耗的 sink 比如 null sink
			用于 agent 间通信的 IPC:sink:Avro
			必须作用于一个确切的 channel

Flume经典部署方案:
		1).单Agent采集数据
		2).多Agent串联
		3).多Agent合并串联
		4).多路复用

kafka : 分布式消息系统
	JMS 是什么:JMS 是 是 Java  提供的一套技术规范 ,即Java  消息服务(Java Message Service )

应用程序接口。用于在两个应用程序之间或分布式系统中发送消息,进行异步通信。提高系统的伸缩性增强系统用户体
验,使得系统模块化和组件化变得可行并更加灵活。
生产消费者模式(生产者、服务器、消费者)通常消息传递有两种类型的消息模式可用一种是点 点对点
queue 队列模式(p2p),另一种是 topic 发布- 订阅模式(public-subscribe)。

点对点模式(一对一,消费者主动拉取数据,消息收到后消息清除):
	点对点模型通常是一个基于拉取或者轮询的消息传送模型,这种模型从队列中请求信息,而不是将消息推送到
客户端。这个模型的特点是发送到队列的消息被一个且只有一个接收者接收处理,即使有多个消息监听者也是如此
	
	发布/ 订阅模式(一对多,数据生产后,推送给所有订阅者):

发布订阅模型则是一个基于推送的消息传送模型。发布订阅模型可以有多种不同的订阅者,临时订阅者只在主动监听主
题时才接收消息,而持久订阅者则监听主题的所有消息,即时当前订阅者不可用,处于离线状态。

kafka工作原理?
		Kafka对消息保存时根据Topic进行归类,发送消息者称为 Producer , 
		消息接受者称为Consumer , 此外 Kafka  集群有多个 Kafka  实例组成,每个实例(server) 成为 
		broker
	kafka特性:
		1).高吞吐量、低延迟:kafka 每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个 topic
			可以分多个 partition,consumer group 对 partition 进行消费操作
		2).可扩展性:kafka 集群支持热扩展
		3).持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失
		4).容错性:允许集群中节点失败(若副本数量为 n,则允许 n-1 个节点失败)
		5).高并发:支持数千个客户端同时读写

	kafka核心组件概述:	
		Kafka 是 LinkedIn 用于日志处理的分布式消息队列,同时支持离线和在线日志处理。
		Kafka 对消息保存时根据 Topic 进行归类:
			发送消息者就是 Producer ,消息的发布描述为 Producer
			消息接受者就是 Consumer ,消息的订阅描述为 Consumer
			每个 Kafka  实例称为 Broker ,将中间的存储阵列称作 Broker( 代理),
			然后三者都通过 Zookeeper 进行协调
	Kafka 的大致工作模式:
		1).启动 ZooKeeper 的 server
		2).启动 Kafka 的server
		3).Producer  生产数据,然后通过 ZooKeeper  找到 Broker ,再将 数据 push 到Broker  保存
		4).Consumer  通过 ZooKeeper  找到 Broker ,然后再主动 pull

redis  : 分布式NoSQL数据库 
	存储在redis的所有数据,在磁盘中都会存储一份。
		部分经常使用的数据放置在内存中。

	三大特点:
		1、Redis 支持数据的 持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
		2、Redis 不仅仅支持简单的 key-value 类型的数据,同时还提供 list,set,zset,hash 等 
			数据结构的存储。
		3、Redis 支持数据的 备份,即 master-slave 模式的数据备份。
	优势:
		1).性能极高:Redis 能读的速度是 110000 次/s,写的速度是 81000 次/s 
		2).丰富的数据类型:Redis 支持二进制案例的 String, List, Hash, Set 及 Sorted Set 数据类型操作
		3).原子 操作:Redis 的所有操作都是原子性的,同时 Redis 还支持对几个操作全并后的原子性执行
		4).丰富的特性:Redis 还支持 Publish/Subscribe,通知 key 过期,支持高可用集群等等特性
		5).数据持久化机制
			持久化机制有两种:
			(1).RDB 方式:定期将内存数据 dump 到磁盘
			(2).AOF(append only file)持久化机制:用记日志的方式记录每一条数据更新操作,
				一旦出现灾难事件,可以通过日志重放来恢复整个数据库
	入门教程:http://www.runoob.com/redis/redis-tutorial.html
	命令搜索:http://redisdoc.com/

scala  : 面向对象和函数式编程语言
	RDD:弹性分布式数据集

sparkcore  : 基于内存的分布式计算引擎

sparksql  :  基于sparkCore的结构化数据处理引擎

sparkstreaming  : 流式计算处理引擎

ambari/CDH : 安装部署工具

Spark任务提交过程
Spark on standalone模式
一、Spark on Standalone
1.spark集群启动后,Worker向Master注册信息
2.spark-submit命令提交程序后,driver和application也会向Master注册信息
3.创建SparkContext对象:主要的对象包含DAGScheduler和TaskScheduler
4.Driver把Application信息注册给Master后,Master会根据App信息去Worker节点启动Executor
5.Executor内部会创建运行task的线程池,然后把启动的Executor反向注册给Dirver
6.DAGScheduler:负责把Spark作业转换成Stage的DAG(Directed Acyclic Graph有向无环图),根据宽窄依赖切分Stage,然后把Stage封装成TaskSet的形式发送个TaskScheduler;同时DAGScheduler还会处理由于Shuffle数据丢失导致的失败;
7.TaskScheduler:维护所有TaskSet,分发Task给各个节点的Executor(根据数据本地化策略分发Task),监控task的运行状态,负责重试失败的task;
8.所有task运行完成后,SparkContext向Master注销,释放资源;

二.Spark on Yarn模式
ResourceManager:负责将集群的资源分配给各个应用使用,而资源分配和调度的基本单位是Container,其中封装了集群资源(CPU、内存、磁盘等),每个任务只能在Container中运行,并且只使用Container中的资源;
NodeManager:是一个个计算节点,负责启动Application所需的Container,并监控资源的使用情况汇报给ResourceManager
ApplicationMaster:主要负责向ResourceManager申请Application的资源,获取Container并跟踪这些Container的运行状态和执行进度,执行完后通知ResourceManager注销ApplicationMaster,ApplicationMaster也是运行在Container中;
1).yarn-client模式,Dirver运行在本地的客户端上
1.client向ResouceManager申请启动ApplicationMaster,同时在SparkContext初始化中创建DAGScheduler和TaskScheduler
2.ResouceManager收到请求后,在一台NodeManager中启动第一个Container运行ApplicationMaster
3.Dirver中的SparkContext初始化完成后与ApplicationMaster建立通讯,ApplicationMaster向ResourceManager申请Application的资源
4.一旦ApplicationMaster申请到资源,便与之对应的NodeManager通讯,启动Executor,并把Executor信息反向注册给Dirver
5.Dirver分发task,并监控Executor的运行状态,负责重试失败的task
6.运行完成后,Client的SparkContext向ResourceManager申请注销并关闭自己
2).yarn-cluster模式中,当用户向yarn提交应用程序后,yarn将分为两阶段运行该应用程序:
第一个阶段是把Spark的Dirver作为一个ApplicationMaster在yarn中启动;
第二个阶段是ApplicationMaster向ResourceManager申请资源,并启动Executor来运行task,同时监控task整个运行流程并重试失败的task;


Yarn-client和Yarn-cluster的区别:
	yarn-cluster模式下,Dirver运行在ApplicationMaster中,负责申请资源并监控task运行状态和重试失败的task,当用户提交了作业之后就可以关掉client,作业会继续在yarn中运行;

	yarn-client模式下,Dirver运行在本地客户端,client不能离开。

Spark调优方案:
最终目的是提高CPU利用率,降低带宽IO,提高缓存命中率,减少数据落盘
1.参数优化
1).设置合适的资源量
2).Spark JVM 参数的优化
3).调整并行度
4).小文件合并
5).大小表join
6).设置offheap内存
2.代码优化
1).filter操作后进行caolesce操作
2).优化数据结构,使用基础类型
3).处理数据倾斜
4).RDD复用
5).选择合适的算子
6).使用DaTaSet
3.集群优化
1).存储格式选择
2).数据本地性
3).资源隔离(打标签)

Spark的发展过程就是通过让数据操作更简单,执行优化智能,类型检查更安全