Hive及其相关的大数据组件
Hive架构
YARN和Hive的协作关系
客户端提交SQL作业到HiveServer2,HiveServer2会根据用户提交的SQL作业及数据库中现有的元数据信息生成一份可供计算引擎执行的计划。每个执行计划对应若干MapReduce作业,Hive会将所有的MapReduce作业都一一提交到YARN中,由YARN去负责创建MapReduce作业对应的子任务任务,并协调它们的运行。YARN创建的子任务会与HDFS 进行交互,获取计算所需的数据,计算完成后将最终的结果写入HDFS或者本地。
Hive自身主要是包含3部分
第一部分是客户端(client)
Hive支持多种客户端的连接,包括beeline、jdbc、thrift和HCatalog。早期的Hive Command Line(CLI)由于可以直接操作HDFS存储的数据,权限控制较为困难,支持的用户数有限,已经被废弃。
第二部分是HiveServer2
替代早期的HiveServer,提供了HTTP协议的141 Web服务接口和RPC协议的thrift服务接口,使得Hive能够接收多种类型客户端的并发访问,并将客户端提交的SQL进行编译转化可供计算引擎执行的作业。
借助于HiveServer2,Hive可以做到更为严格的权限验证。
- 在实际使用中需要注意HiveServre2服务Java堆大小的设置,默认情况下是50MB,在查询任务增多的情况下,容器发生内存溢出,导致服务崩溃,用户访问不了Hive。
第三部分是元数据及元数据服务
Hive的元数据记录了Hive库内对象的信息,包括表的结构信息、分区结构信息、字段信息及相关的统计信息等。
Hive元数据
Hive元数据主要是分为5个部分:
数据库相关的元数据
数据库的元数据及这些元数据之间的关系
DBS
描述HIve中所有的数据库库名、存储地址(用字段DB_LOCATION_URI表示)、拥有者和拥有者类型
通过命令“desc database库名”来查询DBS的信息
DATABASE_PARAMS
描述数据库的属性信息(DBPROPERTIES)
DB_PRIVS
描述数据库的权限信息
FUNCS
记录用户自己编写的函数信息(UDF),包括该函数的函数名、对应的类名和创建者等信息
用户可以通过命令“create function 函数名...”来创建自定义函数。
FUNCS_RU
记录自定义函数所在文件的路径
例如使用Java编写Hive的自定义函数,FUNCS_RU表会记录该函数所在JAR包的HDFS存储位置, 以及该JAR包引用的其他JAR包信息。
表相关的元数据
表的元数据及这些元数据之间的关系
TBLS
记录Hive数据库创建的所有表,包含表所属的数据库、创建时间、创建者和表的类型(包括内部表、外部表、虚拟视图等)
使用命令“desc formatted表名”,查看Detailed Table Information一节的信息
TABLE_PARAMS
表的属性信息,对应的是创建表所指定的TBLPROPERTIES内容或者通过收集表的统计信息
收集表的统计信息可以使用如下的命令:
Analyze table表名compute statistics
表的统计信息一般包含表存储的文件个数(numFiles)、总文件大小(totalSize)、表的总行数(numRows)、分区数(numPartitions)和未压缩的每行的数据量(rawDataSize)等。
TBL_PRIVS
表或者视图的授权信息,包括授权用户、被授权用户和授权的权限等
TBL_COL_PRIVS
表或者视图中列的授权信息,包括授权用户、被授权的用户和授权的权限等。
PARTITION_KEYS
表的分区列。
IDXS
Hive中索引的信息,Hive 3.0已经废弃。
分区相关的元数据
分区的元数据及这些元数据之间的关系
PARTITIONS
存储分区信息,包括分区列,分区创建的时间
PARTITION_PARAMS
存储分区的统计信息,类似于表的统计信息一样
PART_COL_STATS
分区中列的统计信息,类似于表的列统计信息一致。
PART_PRIVS
分区的授权信息,类似于表的授权信息。
PART_COL_PRIVS
分区列的授权信息,类似于表的字段授权信息。
PARTITION_KEY_VALS
分区列对应的值。
文件存储相关的元数据
数据存储的元数据及这些元数据之间的关系
SDS
保存数据存储的信息,包含分区、表存储的HDFS路径地址、输入格式(INPUTFORMAT)、输出格式(OUTPUTFORMAT)、分桶的数量、是否有压缩、是否包含二级子目录。
CDS、COLUMN_V2
表示该分区、表存储的字段信息,包含字段名称和类型等。
SORT_COLS
保存Hive表、分区有排序的列信息,包括列名和排序方式等。
BUCKETING_COLS
保存Hive表,分区分桶列的信息、列名等。
SERDES
保存Hive表、分区序列化和反序列化的方式。
SERDES_PARAMS
保存Hive,分区序列化和反序列化的配置属性,例如行的间隔符(line.delim)、字段的间隔符(filed.delim)。
SKEWED_COL_NAMES
保存表、分区有数据倾斜的列信息,包括列名。
SKEWED_VALUES
保存表、分区有数据倾斜的列值信息。
SKEWED_COL_VALUE_LOC_MAP
保存表、分区倾斜列对应的本地文件路径
SKEWED_STRING_LIST、SKEWED_STRING_LIST_VALUES
保存表,分区有数据倾斜的字符串列表和值信息。
其他
Hive的元数据还包含很多内容,例如Hive的事务信息、锁信息及权限相关的信息等
YARN组件
YARN的优点
(1)提高系统的资源利用率
不仅计算资源可以共享,由于允许多套系统部署在一个集群,也能增加系统存储资源的利用率。
(2)协调不同作业/不同系统的资源,减少不同作业和不同系统之间的资源争抢
(3)增强系统扩展性。资源管理和调度框架,允许硬件资源的动态伸缩,而不会影响作业的运行
(4)资源调度与管理工具把控着资源的分配和任务的调度,直接影响程序的运行效率
如何利用资源与调度管理工具?
YARN运行的基本组成和工作原理,能够基本理清程序运行的整体流程,知道哪些过程或者配置可能成为瓶颈,可以先不用了解,但一定要有意识。
知道YARN资源调度与分配算法
YARN基本组成
YARN的基本结构由一个ResourceManager与多个NodeManager组成。
YARN的基本工作流程
ResouceManager(简称RM)
- 资源管理器负责整个集群资源的调度,该组件由两部分构成:调度器(Scheduler)和ApplicationsMaster(简称ASM)
- 分配的资源将用容器(container) 形式提供,容器是一个相对封闭独立的环境,已经将CPU、内存及任务运行所需环境条件封装在一起
- YARN调度器目前在生产环境中被用得较多的有两种:能力调度器(Capacity Scheduler)和公平调度器(Fair Scheduler)
ApplicationMaster(简称AM)
- 负责进行数据切分,并为当前应用程序向RM去申请资源,当申请到资源时会和NodeManager通信,启动容器并运行相应的任务。
- AM还负责监控任务(task)的状态和执行的进度
NodeManage(简称NM)
- NodeManager负责管理集群中单个节点的资源和任务,每个节点对应一个NodeManager,NodeManager负责接收ApplicationMaster的请求启动容器, 监控容器的运行状态,并监控当前节点状态及当前节点的资源使用情况和容器的运行情况,并定时回报给ResourceManager。
YARN工作流程
YARN在工作时主要会经历3个步骤:
(1)ResourceManager收集NodeManager反馈的资源信息,将这些资源分割成若干组,在YARN中以队列表示。
(2)当YARN接收用户提交的作业后,会尝试为作业创建一个代理ApplicationMaster。
(3)由ApplicationMaster将作业拆解成一个个任务(task),为每个任务申请运行所需的资源,并监控它们的运行。
YARN在处理任务的工作流程
(1)客户端向YARN提交一个作业(Application)。 (2)作业提交后,RM根据从NM收集的资源信息,在有足够资源的节点分配一个容器,并与对应的NM进行通信,要求它在该容器中启动AM。 (3)AM创建成功后向RM中的ASM注册自己,表示自己可以去管理一个作业(job)。 (4)AM注册成功后,会对作业需要处理的数据进行切分,然后向RM 申请资源,RM会根据给定的调度策略提供给请求的资源AM。 (5)AM申请到资源成功后,会与集群中的NM通信,要求它启动任务。 (6)NM接收到AM的要求后,根据作业提供的信息,启动对应的任务。 (7)启动后的每个任务会定时向AM提供自己的状态信息和执行的进度。 (8)作业运行完成后AM会向ASM注销和关闭自己。
YARN资源调度器
资源调度器负责整个集群资源的管理与分配,是YARN的核心组件
YARN提供了3种调度器:先来先服务调度器(FIFO Scheduler)、能力调度器(Capacity Scheduler)和公平调度器(Fair Scheduler)。
生产环境中经常被使用到的是能力调度器和公平调度器。
内存和CPU资源可以通过下面的配置选项进行调整:
- yarn.nodemanager.resource.cpu-vcores,默认值为-1。默认表示集群中每个节点可被分配的虚拟CPU个数为8。
- 为什么这里不是物理CPU个数?因为考虑一个集群中所有的机器配置不可能一样,即使同样是16核心的CPU性能也会有所差异,所以YARN在物理CPU和用户之间加了一层虚拟CPU,一个物理CPU可以被划分成多个虚拟的CPU。
- yarn.nodemanager.resource.detect-hardware-capabilities为true,且该配置还是默认值-1,YARN会进行自动给计算可用虚拟CPU。
- yarn.nodemanager.resource.memory-mb,默认值为-1。当该值为-1时, 默认表示集群中每个节点可被分配的物理内存是8GB。
- yarn.nodemanager.resource.detect-hardware-capabilities为true,且该配置还是默认值-1,YARN会自动计算可用物理内存。
- yarn.nodemanager.vmem-pmem-ratio,默认值为2.1。该值为可使用的虚拟内存除以物理内存,即YARN中任务的单位物理内存相对应可使用的虚拟内存。例如,任务每分配1MB的物理内存,虚拟内存最大可使用2.1MB。
- yarn.nodemanager.resource.system-reserved-memory-mb,YARN保留的物理内存,给非YARN任务使用,该值一般不生效,只有当yarn.nodemanager.resource.detect-hardware-capabilities为true的状态才会启用,会根据系统的情况自动计算。 如果发现自身集群资源非常充裕,但是程序运行又较为缓慢,整个集群的资源利用率又很低,就需要关注上面的配置是否设置得过低。 用户提交给YARN的作业及所申请的资源,YARN最终是以容器的形式调播给作业,每个作业分解到子任务运行容器中,YARN分配给容器的相关配置可以通过如下配置项目调整:
- yarn.scheduler.minimum-allocation-mb:默认值1024MB,是每个容器请求被分配的最小内存。如果容器请求的内存资源小于该值,会以1024MB进行分配;如果NodeManager可被分配的内存小于该值,则该NodeManager将会被ResouceManager给关闭。
- yarn.scheduler.maximum-allocation-mb:默认值8096MB,是每个容器请求被分配的最大内存。如果容器请求的资源超过该值,程序会抛出InvalidResourceRequest Exception的异常。
- yarn.scheduler.minimum-allocation-vcores:默认值1,是每个容器请求被分配的最少虚拟CPU个数,低于此值的请求将被设置为此属性的值。此外,配置为虚拟内核少于此值的NodeManager将被ResouceManager关闭。
- yarn.scheduler.maximum-allocation-vcores:默认值4,是每个容器请求被分配的最少虚拟CPU个数,高于此值的请求将抛出160 InvalidResourceRequestException的异常。
- yarn.nodemanager.resource.percentage-physical-cpu-limit:默认值100。 一个节点内所有容器所能使用的物理CPU的占比,默认为100%。即如果一台机器有16核,CPU的使用率最大为1600%,且该比值为100%,则所有容器最多能使用的CPU资源为1600%,如果该比值为50%,则所有容器能使用的CPU资源为800%。
- yarn.nodemanager.linux-container-executor.cgroups.strict-resource-usage: 默认值为false,表示开启CPU的共享模式。共享模式告诉系统容器除了能够使用被分配的CPU资源外,还能使用空闲的CPU资源。
HDFS架构
常见HDFS优化
常见的关于HDFS的优化角度有:
- Hive作业生成的小文件,过多的小文件会加重NameNode的负担,导致集群整体性能下降。
- 设置合理的HDFS文件块的大小,可以减轻NameNode的负担,增加数据本地化操作的概率,提升程序性能。
- 适当增大NameNode的Java堆,调整JVM的参数可以提升NameNode性能。
- 在集群进行扩容和缩容的情况时,需要调整NameNode服务处理程序计数和NameNode处理程序计数。
- 在HDFS写入大数据文件的时候,可以尝试启用写入后清理缓存,启用写入后立即对磁盘数据排队。
- 在HDFS有比较多的随机读,或者一次性需要读取大数据文件时,可以启用读取后清理缓存。
- 集群的单机性能较高,可以适当增大处理程序计数。
- HDFS在读取数据时会开启HDFS快速读取。
HDFS基本架构和读写流程
HDFS基本架构
整个HDFS主要有3个组件
NameNode
NameNode(NN)维护整个HDFS文件系统的目录树,以及目录树里的所有文件和目录
- 一种是NameSpace镜像(FSImage):即HDFS元数据的完整快照,每次NameNode 启动时,默认加载最新的命名空间镜像;
- 另一种是命名空间镜像的编辑日志(EditLog),它主要有几个职能:
- 管理HDFS的NameSpace,如打开、关闭重命名文件和目录。
- 管理数据块与DataNode的映射关系。
- 处理客户端的读写请求。
- 管理副本的配置策略。
DataNode
DataNode节点(DN)的功能如下:
- 处理客户端的读写请求。
- 存储实际的数据。
- 接收NameNode指令创建数据块。
查看当前DataNode整体信息,可以采用如下命令: hdfs dfsadmin -report
Client
Client主要有以下几个职能:
- 与NameNode进行交互,获取文件位置信息和文件块信息。
- 与DataNode进行交互,读写数据文件。
- 访问并管理HDFS集群。
常见的访问HDFS客户端方式有:
- 命令行交互界面,在安装HDFS组件时自带。
- 使用HttpFs服务,HttpFs提供Rest风格的操作接口,用于访问HDFS。
- 访问NameNode提供的Web服务,默认端口是50070。
在获取文件存储块的位置时,通常会配置超时时间,减少作业因集群组件异常导致的作业长时间等待
配置项:dfs.client.file-blockstorage-locations.timeout,dfs.client.file-block-storagelocations.timeout.millis
HDFS的读流程
(1)Client先与NameNode进行交互,获取数据所在DataNode的地址和文件块信息。
(2)Client根据从NameNode得到的消息找到DataNode及对应的文件块,建立socket流。
(3)DataNode读取磁盘中的文件中回传给Client。
HDFS快速读取模式,Client会绕开DataNode自己去读取数据,实现方式是借助Linux操作系统中的Unix Domain Socket技术。
HDFS的写流程
(1)Client先与NameNode通信,表示要写入数据,NameNode会在NameSpace中添加一个新的空文件,并告知Client已经做好写的准备工作
(2)Client接到通知,向NameNode申请DataNode的数据块, NameNode会返回一个数据块,包含所有数据节点所在DataNode的位置信息。
(3)Client得到目标数据块位置,建立socket流,并向目标数据块写入数据。
HDFS高可用架构
HDFS引入了高可用(High Availability, HA)特性,在同一个集群引入多NN用来解决上述问题,允许如果出现故障启用备用的NN节点,快速进行故障转移(failover)。
HDFS提供了两种HA方案
- NameNode HA With QJM
- NameNode HA With NFS
第一种比较主流,去原理如下:
整个架构包含如下高可用设计:
NameNode服务的高可用设计
新增NN Standby节点。在HA集群中,要有两个或更多独立的机器节点被配置为Name Node。
在任何时间点,恰好有一个NameNode处于活动状态,而其他的NN处于备用状态。
活动NN负责集群中的所有客户端操作,而备用节点只是维护自己当前的状态和NN节点保持一致,以便在必要时提供快速故障转移。
JounalNode服务的高可用设计
新增一组JounalNode节点。为了让备用节点与活动节点保持同步状态, 两个节点都与一组称为Journal Nodes(简称JNs)的独立守护进程通信。JNs 是一个副本集,一般为3个副本,当有2个副本可以对外提供服务时,整个系统还处于可用状态。当活动节点执行任何的NameSpace内容修改时,它会持续地将修改记录写到这些JNs中。
备用节点能够从JNs读取日志,并不断监视它们对编辑日志的更改。当备用节点看到编辑时,会将它们应用到自己的名称空间。这样可确保在发生故障并在故障转移发生之前的两个NN状态完全同步。
服务存储状态的高可用设计
新增ZooKeeper(ZK)组件,使用多个副本用于存储HDFS集群服务状态信息。
故障转移控制服务的高可用设计
故障转移控制服务,发现监控的NN没有心跳,会尝试获取NN standy地址,并启动该服务,原先的standy状态变为active。但只有一个故障转移控制服务,如果不做高可用设计,也会出现单点问题,所以故障转移控制服务也被设计成支持服务的高可用。当工作的控制服务发生故障时,会启用备用的控制服务继续对集群提供服务。
上面的架构不管是在正常情况,还是异常发生在进行故障转移时,只允许一个NN处在工作状态,其他NN都处在备用(standy)状态。
这是为避免两个NN同时工作时,两个NN的NameSpace状态将会出现差异, 也就是“脑裂”现象,这可能导致数据丢失或其他错误结果。为了保证整个集群正常工作,JournalNodes只允许一个NameNode与它通信。在故障转移期间,变为活动工作状态的NameNode将接管向JournalNodes写入数据的角色。
NameNode联盟
- 当集群所管理的数据量逐渐增多时, 单个NameNode服务所要占用的内存空间也会随着增多,这会带来几个问题:
- NameNode服务垃圾回收(GC)运行时间变长,导致NameNode对外响应效率变低。Hive提交任务大部分都需要访问NameNode服务,这会影响Hive的运行效率。
- NameNode故障恢复时间变长或集群重启时间长。在进行故障恢复或重启时,单个NameNode需要将大量持久化在磁盘中的文件数据加载到内存中,并在内存构建出整个NameSpace目录树。
- 内存无法一直持续扩展,Hadoop是运行在廉价的服务器集群上,内存资源有限。
针对上面的问题,HDFS提出了NameNode联盟架构方案。原先一个NameNode管理一个HDFS集群中的所有数据,现在将一个HDFS集群的数据划分给几个NameNode同时进行管理,这几个NameNode可以分布在不同的机器上,在对外提供服务时这几个NameNode采用同一的接口提供服务
HDFS的基础架构
整个HDFS由两部分组成:命名空间和块存储。
命名空间(NameSpace)由目录、文件和块组成。它支持所有与名称空间相关的文件系统操作,如创建、删除、修改和列出文件和目录。
块存储(Block storage)也由两部分组成:块管理和数据存储。 DataNode提供本地文件系统数据存储和读写功能。
块管理功能如下:
- 管理DataNode集群,通过周期心跳信息,或者DataNode主动注册动作来判定能够对外提供服务的DataNode节点。
- 处理块信息并维护块的位置。
- 支持块相关操作,如创建、删除、修改和查询块位置。
- 管理块复制,并删除已过度复制的块。
NameNode联盟架构是怎样的呢?
Hadoop 为了保证能够提供横向扩展的能力,在NameSpace这一层运行创建多个NameSpace,这几个NameSpace通过块的管理,实现共用DataNode的集群。几个NameNode之间的操作不互相影响,只是共用数据存储空间。
每个块池(block pool)都是由单独的NameSpace进行管理, 每个Name Space对块的操作包括删除、创建,都是独立于其他NameSpace。当一个Namespace出现故障时不会影响其他NameSpace对外提供服务。每个NameSpace和其对应的块池被统称为一个NameSpace volumn,如果删除了DataNode或者NameSpace,则也会删除相应的块池。
NameNode联盟在一定程度上可以缓解单个NameNode的压力,但是在使用之前要对业务数据量有一个合理的预估和拆分,确保NameNode联盟中的单个NameNode的有足够资源满足需求。
计算引擎
目前Hive支持MapReduce、Tez和Spark 3种计算引擎。
Tez计算引擎
Apache Tez是进行大规模数据处理且支持DAG作业的计算框架,它直接源于MapReduce框架,除了能够支持MapReduce特性,还支持新的作业形式,并允许不同类型的作业能够在一个集群中运行。
Spark计算引擎
Apache Spark是专为大规模数据处理而设计的快速、通用支持DAG(有向无环图)作业的计算引擎,类似于Hadoop MapReduce的通用并行框架, 可用来构建大型的、低延迟的数据分析应用程序。Spark具有以下几个特性。
高效性
Spark会将作业构成一个DAG,优化了大型作业一些重复且浪费资源的操作,对查询进行了优化,重新编写了物理执行引擎,如可以实现MRR模式。
易用性
Spark不同于MapReducer只提供两种简单的编程接口,它提供了多种编程接口去操作数据,这些操作接口如果使用MapReduce去实现,需要更多的代码。Spark的操作接口可以分为两类:transformation(转换)和action(执行)。Transformation包含map、flatmap、distinct、reduceByKey和join等转换操作;Action包含reduce、collect、count和first等操作。
通用性
Spark针对实时计算、批处理、交互式查询,提供了统一的解决方案。 但在批处理方面相比于MapReduce处理同样的数据,Spark所要求的硬件设施更高,MapReduce在相同的设备下所能处理的数据量会比Spark多。所以在实际工作中,Spark在批处理方面只能算是MapReduce的一种补充。
兼容性
Spark和MapReduce一样有丰富的产品生态做支撑。例如Spark可以使用YARN作为资源管理器,Spark也可以处理Hbase和HDFS上的数据。 在实际生产环境中Spark都会被纳入同集群的YARN等资源管理器中进行调度,我们称之为Spark On YARN。
Spark On YARN提供了两种提交作业的模式:YARN Client和YARN Cluster。两个模式在运行计算节点,完成数据从读入、处理、输出的过程基本一样。不同的是,YARN Client作业的监控管理放在提交作业所在的节点,YARN Cluster则是交给YARN去决定,YARN会根据集群各个节点资源的使用情况,选择最为合适的节点来存放作业监控和管理进程。YARN 183 Client一般用于测试,YARN Cluster用于实际生产环境。