- 由 ElasticSearch、FileBeat、LogStash、Kibana 组成
- ElasticSearch:用于存储日志
- FileBeat:是一个轻量级的日志收集处理工具(Agent),Filebeat 占用资源少,适合于在各个服务器上搜集日志后传输给 Logstash,官方也推荐此工具
- LogStash:主要是用来日志的搜集、分析、过滤日志的工具,支持大量的数据获取方式。一般工作方式为 c/s 架构,client 端安装在需要收集日志的主机上,server 端负责将收到的各节点日志进行过滤、修改等操作再一并发往 elasticSearch 上去
- Kibana:一个开源的数据可视化工具,可以帮助汇总、分析和搜索重要数据日志
- MapReduce 最早是由 Google 公司研究提出的一种面向大规模数据处理的并行计算模型和方法。Google 公司设计 MapReduce 的初衷主要是为了解决其搜索引擎中大规模网页数据的并行化处理
- MapReduce 是一种编程模型,用于大规模数据集(大于 1TB)的并行运算
- 概念"Map(映射)"和"Reduce(归约)",是它们的主要思想
- 简介
- 2004 年,开源项目 Lucene(搜索索引程序库)和 Nutch(搜索引擎)的创始人 Doug Cutting 发现 MapReduce 正是其所需要的解决大规模 Web 数据处理的重要技术,因而模仿 Google MapReduce,基于 Java 设计开发了一个称为 Hadoop 的开源 MapReduce 并行计算框架和系统
- Hadoop 实现了一个分布式文件系统(Hadoop Distributed File System),简称 HDFS
- HDFS 有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上;而且它提供高吞吐量(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序
- HDFS 放宽了(relax)POSIX 的要求,可以以流的形式访问(streaming access)文件系统中的数据
- Hadoop 的框架最核心的设计就是:HDFS 和 MapReduce
- HDFS 为海量的数据提供了存储,而 MapReduce 则为海量的数据提供了计算
- Hadoop 框架包括以下四个模块:
- Hadoop Common:这些是其他 Hadoop 模块所需的 Java 库和实用程序。这些库提供文件系统和操作系统级抽象,并包含启动 Hadoop 所需的必要 Java 文件和脚本
- Hadoop YARN:这是作业调度和集群资源管理的框架
- Hadoop 分布式文件系统(HDFS)
- 提供对应用程序数据的高吞吐量访问的分布式文件系统
- 保存多个副本,且提供容错机制,副本丢失或宕机自动恢复。默认存 3 份。为防止某个主机失效读取不到该主机的块文件,它将同一个文件块副本分配到其他某几个主机上
- HDFS 会将一个完整的大文件平均分块存储到不同计算机上,默认会将文件分割成 block,64M 为 1 个 block。然后将 block 按键值对存储在 HDFS 上,并将键值对的映射存到内存中。如果小文件太多,内存的负担会很重
- Block:将文件分块,通常为 64M
- 流式数据访问,一次写入多次读写,和传统文件不同,它不支持动态改变文件内容,而是要求让文件一次写入就不做变化,要变化只能在文件末尾添加
- Hadoop MapReduce: 这是基于 YARN 的大型数据集并行处理系统
- HDFS(Hadoop Distributed File System)分布式文件系统主要组成:
- Client:
- 切分文件
- 与 NameNode 交互,获取文件位置信息
- 与 DataNode 交互,读取和写入数据
- NameNode
- 作为 Master 服务,负责管理文件系统的命名空间和客户端对文件的访问
- NameNode 会保存文件系统的具体信息,包括文件信息、文件被分割成具体 block 块的信息、以及每一个 block 块归属的 DataNode 的信息
- 对于整个集群来说,HDFS 通过 NameNode 对用户提供了一个单一的命名空间
- NameNode 内存中存储的了 fsimage(文件镜像)和 edits(操作日志)
- fsimage:元数据镜像文件(文件系统的目录树)
- edits:元数据的操作日志(针对文件系统做的修改操作记录)
- DataNode
- 作为 Slave 服务,在集群中可以存在多个。通常每一个 DataNode 都对应于一个物理节点
- 负责存储实际的数据,它将存储划分为多个 block 块,管理 block 块信息,同时周期性的将其所有的 block 块信息发送给 NameNode
- Secondary NameNode
- 定期合并 NameNode 的 fsimage 和 edits,再推送给 NameNode,减少 NameNode 的工作量
- 是 NameNode 的冷备份,可辅助恢复 NameNode
- Client:
- 文件写入流程
- Client 将文件按 64M 分块。分成多个 block
- Client 向 NameNode 发送写数据请求,获取文件位置信息
- NameNode 节点,记录 block 信息。并返回可用的 DataNode 信息给 Client
- Client 向 DataNode 发送 block,发送过程是以流式写入,每个 block 会拆分成多个 64k 的 package,写入到其中一个 DataNode 后,该 DataNode 会将 package 再同步写入到其他两个 DataNode(作为备份的副本),每个 Block 写入完之后,DataNode 会向 Client 发送消息
- Client 收到 DataNode 写入完成的消息后,向 NameNode 发送消息,通知 NameNode 数据写入完毕
- 当所有 Block 写入完毕后,文件写入完毕
- 文件读取流程
- Client 向 NameNode 发起文件读取的请求
- NameNode 返回文件存储的 block 块信息、及其 block 块所在 DataNode 的信息
- Client 读取文件信息
- MapReduce 分布式计算框架
- JobTracker:管理所有作业,将任务分解成一系列任务,并分派给 TaskTracker
- TaskTracker:运行 Map Task 和 Reduce Task;并与 JobTracker 交互,汇报任务状态
- Map Task:解析每条数据记录,传递给用户编写的 map(),将输出结果写入本地磁盘
- Reducer Task:从 Map Task 的执行结果中,远程读取输入数据,对数据进行排序,将数据按照分组传递给用户编写的 reduce 函数执行
- MapReduce 的缺陷
- JobTracker 是 Map-reduce 的集中处理点,存在单点故障
- JobTracker 需要完成的任务太多,既要维护 job 的状态又要维护 job 的 task 的状态,造成过多的资源消耗。业界普遍总结出老 Hadoop 的 Map-Reduce 只能支持 4000 节点主机的上限
- 在 TaskTracker 端,以 map/reduce task 的数目作为资源的表示过于简单,没有考虑到 cpu/ 内存的占用情况,如果两个大内存消耗的 task 被调度到了一块,很容易出现 OOM
- 在 TaskTracker 端,把资源强制划分为 map task slot 和 reduce task slot, 如果当系统中只有 map task 或者只有 reduce task 的时候,会造成资源的浪费,也就是前面提过的集群资源利用的问题
- Yarn 运行原理
- Yarn 是 Hadoop 集群的分布式资源管理系统。Hadoop2.0 对 MapReduce 框架做了彻底的设计重构,我们称 Hadoop2.0 中的 MapReduce 为 MRv2 或者 Yarn
- Yarn 是为了提高分布式的集群环境下的资源利用率,这些资源包括内存、IO、网络、磁盘等。其产生的原因是为了解决原 MapReduce 框架的不足
- 在 Yarn 中把 job 的概念换成了 application,因为在新的 Hadoop2.x 中,运行的应用不只是 MapReduce 了,还有可能是其它应用如一个 DAG
- Yarn 的另一个目标就是拓展 Hadoop,使得它不仅仅可以支持 MapReduce 计算,还能很方便的管理诸如 Hive、Hbase、Pig、Spark/Shark 等应用。各种应用就可以互不干扰的运行在同一个 Hadoop 系统中,共享整个集群资源
- YARN 组件与架构
- ResourceManager:Global(全局)的进程
- NodeManager:运行在每个节点上的进程
- ApplicationMaster:Application-specific(应用级别)的进程。ApplicationMaster 是对运行在 Yarn 中某个应用的抽象,它其实就是某个类型应用的实例,ApplicationMaster 是应用级别的,它的主要功能就是向 ResourceManager(全局的)申请计算资源(Containers)并且和 NodeManager 交互来执行和监控具体的 task
- Scheduler:是 ResourceManager 的一个组件。Scheduler 是 ResourceManager 专门进行资源管理的一个组件,负责分配 NodeManager 上的 Container 资源,NodeManager 也会不断发送自己 Container 使用情况给 ResourceManager
- Container:节点上一组 CPU 和内存资源。Container 是 Yarn 对计算机计算资源的抽象,它其实就是一组 CPU 和内存资源,所有的应用都会运行在 Container 中
- YARN 执行过程
- 应用程序提交
- 启动应用的 ApplicationMaster 实例
- 执行 ApplicationMaster 实例管理应用程序
- Pig 是一款数据装载、处理、存储的工具,是一种探索大规模数据集的脚本语言,底层基于 MapReduce 实现
- 我们可以使用 pig 将数据装载到内存中成为一个关系,然后再通过 PigLatin 语言对数据进行操作,最后再将数据转换的结果存储到一个文件中,适合用于 ETL(Extract-Transform-Load)
- 简介
- Hive 定义了一种类似 SQL 的查询语言(HQL),可以将 SQL 转化为 MapReduce 任务在 Hadoop 上执行
- 实现了按字段多层 Partition(分区)的功能
- 通常用于离线分析
- Hive 本身提供了一系列对数据进行提取、转换、加载(ETL)的工具,可以存储、查询和分析存储在 Hadoop 中的大规模数据
- 支持自定义 UDF 函数或者计算脚本
- 支持 MapReduce,Tez,Spark 等多种计算引擎
- 可以直接访问 HDFS 文件以及 HBase
- 不支持列级别的数据添加、更新、删除操作
- 可以创建托管表和外部表,外部表可以访问仓库目录以外的文件
- 支持流量控制
- Hive 分为三个角色:HiveServer、MetaStore、WebHcat
- HiveServer:将用户提交的 HQL 语句进行编译,解析成对应的 Yarn 任务,Spark 任务或者 HDFS 操作,从而完成数据的提取,转换,分析
- MetaStroe:提供元数据服务
- WebHcat:对外提供基于 Htpps 协议的元数据访问、DDL 查询等服务
- 简介
- HBase(Hadoop Database)是建立在 Hadoop 文件系统之上的分布式面向列的数据库,支持横向扩展,基于 JAVA 语言实现
- 该技术来源于 Fay Chang 所撰写的 Google 论文“Bigtable:一个结构化数据的分布式存储系统”
- HBase 在列上实现了 BigTable 论文提到的压缩算法、内存操作和布隆过滤器。HBase 的表能够作为 MapReduce 任务的输入和输出,可以通过 Java API 来访问数据,也可以通过 REST、Avro 或者 Thrift 的 API 来访问
- 逻辑存储模型
- namespace:命名空间,一般就是逻辑上用于表的区分,类似数据库中的 database。在最终物理文件存储的时候,会根据 namespace 切分目录
- table:表,类似于数据库中的 table
- column family:列族,相同列族的列会存放在一起
- row:由基于字符串的 rowkey 唯一指定,rowkey 全局不能重复,按照字典序顺序存储,rowkey 的设计对最终的查询起到关键性作用
- column:列,用于存放字段的数据内容
- Cell
- HBase 中通过 rowkey 和 columns 确定的为一个存储单元称为 cell
- 每个 cell 都保存着同一份 数据的多个版本。版本通过时间戳来索引
- Timestamp:时间戳一般写在 value 的旁边,代表某个值的版本号,默认的时间戳是你写入数据的那一刻,但是你也可以在写入数据的时候指定不同的时间戳
- RowKey:Hbase 使用 Rowkey 来唯一的区分某一行的数据
- HBase 是三维有序存储的,通过 rowkey(行键),column key(column family 和 qualifier)和 TimeStamp(时间戳)这个三个维度可以对 HBase 中的数据进行快速定位
- HBase 架构
- HBase 中的组件包括 Client、Zookeeper、HMaster、HRegionServer、HRegion、Store、MemStore、StoreFile、HFile、HLog 等
- HBase 有两张特殊表:
- .META.:记录了用户所有表拆分出来的的 Region 映射信息,.META.表可以有多个 Regoin,.META.表存储了每张表每个 Region 的起始 RowKey
- -ROOT-:记录了.META.表的 Region 信息,-ROOT-只有一个 Region,无论如何不会分裂
- Client
- Client 访问用户数据前需要首先访问 ZooKeeper,找到-ROOT-表的 Region 所在的位置,然 后访问-ROOT-表,接着访问.META.表,最后才能找到用户数据的位置去访问,中间需要多次 网络操作,不过 client 端会做 cache 缓存
- ZooKeeper
- ZooKeeper 为 HBase 提供 Failover 机制,选举 Master,避免单点 Master 单点故障问题
- 存储所有 Region 的寻址入口:-ROOT-表在哪台服务器上。-ROOT-这张表的位置信息
- 实时监控 RegionServer 的状态,将 RegionServer 的上线和下线信息实时通知给 Master
- 存储 HBase 的 Schema,包括有哪些 Table,每个 Table 有哪些 Column Family
- HMaster
- 把 HRegion 分配到某一个 RegionServer
- 对 HRegionServer 进行负载均衡
- 如果有 RegionServer 宕机,HMaster 可以把这台机器上的 Region 迁移到 active 的 RegionServer 上
- 过 HDFS 的 dfs client 接口回收垃圾文件(无效日志等)
- 处理 Schema 更新请求(表的创建,删除,修改,列簇的增加等等)
- HMaster 没有单点问题,HBase 中可以启动多个 HMaster,通过 Zookeeper 的 Master Election 机制保证总有一个 Master 运行
- RegionServer
- RegionServer 维护 Master 分配给它的 Region,处理对这些 Region 的 IO 请求
- RegionServer 负责 Split 在运行过程中变得过大的 Region,负责 Compact 操作
- HRegion
- table 在行的方向上分隔为多个 HRegion,Region 是 HBase 中分布式存储和负载均衡的最小单元
- 同的 region 可以分别在不同的 Region Server 上,但同一个 Region 是不会拆分到多个 server 上
- Region 按大小分隔,随着 Region 增大,当 region 的某个列族达到一个阈值时就会分裂成两个新的 region
- Store
- 每个 HRegion 由多个 Store 构成,每个 Store 保存一个列族(Columns Family)
- table 有几个列族,则有几个 Store
- 每个 Store 由一个 MemStore 和多个 StoreFile 组成
- MemStore:MemStore 是放在内存里的。保存修改的数据即 keyValues。当 MemStore 的大小达到一个阀值(默认 128MB)时,MemStore 会被 flush 到文 件,即生成一个快照。目前 HBase 会有一个线程来负责 memStore 的 flush 操作
- MemStore 内存中的数据写到文件后就是 StoreFile,StoreFile 底层是以 HFile 的格式保存
- StoreFile 是只读的,一旦创建后就不可以再修改。因此 HBase 的更新/修改其实是不断追加 的操作
- 当一个 Store 中的 StoreFile 达到一定的阈值后,就会进行一次合并(minor_compact, major_compact),将对同一个 key 的修改合并到一起,形成一个大的 StoreFile
- 当 StoreFile 的大小达到一定阈值后,又会对 StoreFile 进行 split,等分为两个 StoreFile
- HBase 以 store 的大小来判断是否需要切分 region
- HFile
- HBase 中 KeyValue 数据的存储格式,HFile 是 Hadoop 的 二进制格式文件,实际上 StoreFile 就是对 Hfile 做了轻量级包装,即 StoreFile 底层就是 HFile
- HFile 分为六个部分:
- Data Block:保存表中的数据,这部分可以被压缩(Gzip、LZO)
- Meta Block:可选的,保存用户自定义的 kv 对,可以被压缩(Gzip、LZO)
- File Info:Hfile 的元信息,不被压缩,用户也可以在这一部分添加自己的元信息
- Data Block Index:Data Block 的索引。每条索引的 key 是被索引的 block 的第一条记录的 key
- Meta Block Index:可选的,Meta Block 的索引
- Trailer:这一部分是定长的。保存了每一段的偏移量,读取一个 HFile 时,会首先读取 Trailer, Trailer 保存了每个段的起始位置(段的 Magic Number 用来做安全 check),然后,DataBlock Index 会被读取到内存中,这样,当检索某个 key 时,不需要扫描整个 HFile,而只需从内存中找 到 key 所在的 block,通过一次磁盘 io 将整个 block 读取到内存中,再找到需要的 key。DataBlock Index 采用 LRU 机制淘汰
- HLog
- HLog(HBase write ahead log),用来做灾难恢复使用,HLog 记录数据的所有变更,一旦 region server 宕机,就可以从 log 中进行恢复
- HLog 文件就是一个普通的 Hadoop Sequence File, Sequence File 的 value 是 key 时 HLogKey 对象,其中记录了写入数据的归属信息,除了 table 和 region 名字外,还同时包括 sequence number 和 timestamp,timestamp 是写入时间,sequence number 的起始值为 0,或者是最近一次存入文件系统中的 sequence number。 Sequence File 的 value 是 HBase 的 KeyValue 对象,即对应 HFile 中的 KeyValue
- HBase 有两张特殊表:
- HBase 中的组件包括 Client、Zookeeper、HMaster、HRegionServer、HRegion、Store、MemStore、StoreFile、HFile、HLog 等
- 数据读取流程
- Client 请求 ZooKeeper 获取.META.所在的 RegionServer 的地址
- Client 请求.META.所在的 RegionServer 获取访问数据所在的 RegionServer 地址,Client 会将.META.的相关信息 cache 下来,以便下一次快速访问
- Client 请求数据所在的 RegionServer,获取所需要的数据
- RegionServer 定位到目标数据所在的 Region,发出查询请求
- Region 先在 Memstore 中查找,命中则返回
- 如果在 Memstore 中找不到,则在 Storefile 中扫描 为了能快速的判断要查询的数据在不在这个 StoreFile 中,应用了 BloomFilter
- Client 会将 RegionServer 与 Region 的映射关系缓存到本地,只有在发生读取错误的情况下才会重新走一遍前面的查询流程
- 数据写入流程
- Client 先根据 RowKey 找到对应的 Region 所在的 RegionServer
- Client 向 RegionServer 提交写请求
- RegionServer 找到目标 Region
- Region 检查数据是否与 Schema 一致
- 如果客户端没有指定版本,则获取当前系统时间戳作为数据版本
- 将数据写入 HLog(HBase write ahead log)
- 将数据写入 MemStore
- 判断 MemStore 的是否需要 flush 为 StoreFile 文件
- Region 分裂(split)机制
- 当 MemStore 的数据超过阈值时,将数据写入磁盘,生成一个 StoreFile 文件。当 Region 中最大 Store 的大小超过阈值时,Region 分裂,等分成两个 Region,实现数据访问的负载均衡。新的 Region 的位置由 HMaster 来确定在哪个 RegionServer 中
- 整个分裂的流程如下:
- Region 所在 RegionServer 创建 splits 目录
- 关闭要分裂的 Region 的读写请求
- 在 splits 目录中创建所需要的文件结构
- 移动两个新 Region 文件目录到目录表中,并更新.META 表
- 异步复制父 Region 中的数据到两个子 Region 中(最主要的消耗时间)
- 复制完成后、打开两个新产生的 Region,并上线,可以接收新的读写请求
- 异步任务把定时把原来被分裂的 Region 从.META 表中清除掉,并从文件系统中删除该 Region 所占用的空间
- HFile 合并(Compact)机制
- HBase 是一种 LSM-Tree(Log-Structured Merge Tree)存储模式,用户数据写入先写 HLog,再写 MemStore,满足一定条件后缓存数据会执行 flush 操作真正落盘到 StoreFile 中,形成一个数据文件 HFile
- 随着数据写入不断增多,flush 次数也会不断增多,进而 HFile 数据文件就会越来越多
- 然而,太多数据文件会导致数据查询 IO 次数增多,因此 HBase 尝试着不断对这些文件进行合并,这个合并过程称为 Compaction
- HFile 合并分为两种,Minor Compact 和 Major Compact
- Minor Compact:按照策略,将一部分文件合并为一个 HFile
- Major Compact:把一个 Store 中的所有 HFile 文件合并为一个 HFile 文件
- Minor Compact 策略:
- RatioBasedCompactionPolicy(0.94 版本的默认策略)
- 对同一个 Store 的文件,从旧到新逐一扫描所有候选文件,满足以下条件之一便停止扫描:
- 当前文件大小 < 比它更新的所有文件大小总和 * ratio,其中 ratio 是一个可变的比例,在高峰期时 ratio 为 1.2,非高峰期为 5,也就是非高峰期允许 compact 更大的文件
- 当前所剩候选文件数 >= hbase.store.compaction.min(默认为 3)
- 当前所剩候选文件数 <= hbase.store.compaction.max(默认为 5)
- 停止扫描后,待合并文件就选择出来了,即为当前扫描文件+比它新的所有文件进行合并
- 缺点:经常引起大面积的合并,因为 3 太小了,经常因为满足当前文件大小 < 比它更新的所有文件大小总和 * ratio,发生大面积合并。注意合并的时候就不能写入数据,经常合并就会引起 IO,所以 HBase 在 0.96 版本之后就修改了合并算法
- 对同一个 Store 的文件,从旧到新逐一扫描所有候选文件,满足以下条件之一便停止扫描:
- ExploringCompaction(0.96 版本后的默认策略)
- 根据【该文件<(所有文件大小-该文件大小)*比例因子】公式,比例因子默认为 1.2,该公式不再强调顺序性,而是把所有的文件都遍历一遍,若满足公式就把该文件放进待合并队列组合中
- 根据 hbase.store.compaction.min 和 hbase.store.compaction.max 两个参数选挑选出多个文件组合
- 在得到多个组合后,组合里面选择文件数最多的组合进行合并,文件数一样多时进一步选择文件总 size 最小的组合(尽可能多地合并文件并尽量降低 Compact 带来的 IO 压力)
- Exploring 策略比 Ratio 策略在 IO 方面会有 10%左右的提升
- FIFOCompationPolicy(删除策略)
- 因为 MemStore 在 LSM 整理时,对于 TTL 过期只要不写入 HFile 文件就算是删除了
- 所以 FIFOCompationPolicy 策略在合并时直接删除所有单元格都过期的块(不落盘而已),可以看到过期的块被整个删除掉了,没有过期的块完全没有操作。整体上只有删除没有复制和移动,优点就是对 CPU/IO 几乎没有压力
- 适合 TTL 特别短,容易出现整个块的每一个单元格都过期的场景
- 不适用场景:
- 表没有设置 TTL,或者 TTL=FOREVER
- 表设置了 MIN_VERSIONs,并且 MIN_VERSIONs>0
- DateTieredCompactionPolicy
- 1.3 版本 HBase 增加了基于时间戳的分层 compact 策略,该方法借鉴自 Cassandra
- 基本思想就是将数据按时间戳分区,使得新老数据在不同的分区,定时(默认 6 小时)执行 Compact 操作,使得 Compact 行为在不同的分区内发生,这样相当于把 Compact 也按时间戳进行了拆分
- 同一个时间窗口里的文件,如果达到最小合并数,文件就会合并,合并策略使用的 ExploringCompaction 策略
- 当文件太老了,老到超过所定义的时间范围(以天为单位)就直接不合并了,但是也会存在问题:在这个最老的 HFile 文件没有 TTL 过期,当用户手动删除该文件时,因为不会发生 Major Compaction,所以这个数据根本就不会真正的删除,而是一直占着磁盘空间
- 优点:
- 提高了按时间读取数据时候的效率,因为从指定的时间分区就可以获取数据,而不再需要遍历所有的文件进行查找
- 防止旧文件和新文件合并在一起,因为新文件往往是热点数据
- 适用场景:
- 根据时间排序存储,且专注于读写最新的数据的场景
- 手动删除可能会失效,所以更适用于那些基本不删除数据的场景
- 不适合数据频繁改动的场景
- StripeCompactionPolicy(文件分层合并,综合性能最好)
- 分层 Compact 是将所有的文件分成多个层(实际只有 2 层),最顶层的叫 L0,其下分别是 L1、L2 依此类推,同一层内各个数据文件覆盖的 rowkey 区间不会重叠,相邻层之间的数据文件可以进行 Compaction
- 由于区间不重叠每个 key 处于哪个数据文件是确定的,因此 compact 过程中,只需部分文件参与即可,而不需要所有文件参与,有助于提高 compaction 执行效率
- 新写入的数据会首先落到 L0 层,从 L0 层向下依次执行合并
- 随着数据的写入,MemStore flush 形成的 hfile 会首先落到 level 0 层,一旦 level 0 层的文件数量超过了用户的设置值,则将这些文件写入到 level 1 层
- Level 1 层的数据按照 rowkey 覆盖的范围划分成多个互不重叠的区间,每个区间称为 stripe
- 优点:
- 由于 level 的存在,get 数据时会从依据 block cache、MemStore、level 0 和 level 1 下 HFile 文件的顺序依次寻找,而 Compact 会细化为 level 0 中的数据上升到 level 1 的过程以及 level 1 层内部数据文件的合并,具体的 Compact 策略复用了前面的 Exploring 策略
- 每一个 stripe 相当于划分出的 subregion,这样的设计使得 compact 的粒度变细(从 region 细化到 sub-region 级别),冷热数据的 compact 相隔离,避免了 Compact 时一次扫描整个 Region 下所有的 HFile 文件进行合并,提高了执行合并的效率,同时减少因 Compact 带来的阻塞时间
- 读取链路变长,性能会有损耗,但是提高了查询速度的稳定性
- 本来要牵涉全部 HFile 才能执行 Major Compaction,现在可以分 Strip 执行了,一次 Major Comapction 只会牵涉一个 Strip 中的所有文件,所以克服了 IO 不稳定的缺点
- 适合场景:
- Region 较大。小 region 没有必要切分为 stripes,一旦切分,反而会带来额外的管理开销。一般默认如果 region 大小小于 2G,就不适合使用 stripe compaction
- RowKey 具有统一格式,stripe compaction 要求所有数据按照 Key 进行切分,切分为多个 stripe。如果 rowkey 不具有统一格式的话,因为数据不均匀分布会导致无法进行切分
- RatioBasedCompactionPolicy(0.94 版本的默认策略)
- RowKey 设计原则
- 唯一性原则:RowKey 必须能够唯一的识别一行数据
- 长度原则:rowkey 是一个二进制码流,可以是任意字符串,最大长度 64kb ,实际应用中一般为 10-100bytes,以 byte[] 形式保存,一般设计成定长,越短越好,可以降低磁盘占用率,提高 MemStore 的内存利用率,最好符合操作系统位数特性,4/8 的整数倍
- 散列原则:确保数据均衡分布在各个 RegionServer,避免数据倾斜,影响查询效率
- 合理的 Region 数量与大小
- Region 数量
- 通常较少的 region 数量可使群集运行的更加平稳
- Region 太多,会降低查询效率,提高 MemStore 往 StoreFile 进行 flush 的频率,提高了 HFile 的 Compact 频率
- 官方推荐单个 RegionServer 的 Region 数量控制在 20-300 之间
- Region 大小
- 如果设置太小,容易出现自动分裂(split),影响集群性能
- 如果设置太大,自动合并(Compact)的几率会增大,影响集群性能
- 官方推荐单个 Region 大小控制在 10~30G 之间
- Region 数量
- Presto 是由 Facebook 开发的开源大数据分布式高性能 SQL 查询引擎,专门为交互式查询所设计,提供分钟级乃至亚秒级低延时的查询性能
- 结构
- Client(客户端):提交数据操作的窗口
- Discovery Server(服务发现者):存储可用的 Server 列表
- Coordinator(协调者): 接收数据操作,解析 SQL 语句,生成查询计划,分发任务至 Worker 机
- Connector Plugin(连接插件):连接 Storagr,提供元数据,支持 Hive、Kafka、MySQL、MonogoDB、Redis、JMX 等数据源,可自定义
- Worker(执行者):执行查询计划
- 查询流程:
- Client 发送请求给 Coordinator
- SQL 通过 ANTLR 进行解析生成 AST
- AST 通过元数据进行语义解析
- 语义解析后的数据生成逻辑执行计划,并且通过规则进行优化
- 切分逻辑执行计划为不同 Stage,并调度 Worker 节点去生成 Task
- Task 生成相应物理执行计划
- 调度完后根据调度结果 Coordinator 将 Stage 串联起来
- Worker 执行相应的物理执行计划
- Client 不断地向 Coordinator 拉取查询结果,Coordinator 从最终汇聚输出的 Worker 节点拉取查询结果
- Presto 为何高性能
- ipeline, 全内存计算
- SQL 查询计划规则优化
- 动态代码生成技术
- 数据调度本地化,注重内存开销效率,优化数据结构,Cache,非精确查询等其它技术
- 优点:
- 支持多数据源,如 Hive、Kafka、MySQL、MonogoDB、Redis、JMX 等,也可自己实现 Connector,支持的数据规模大
- 易用性强,灵活性高,能随意查询数据,高度支持 ANSI SQL,支持 JDBC/ODBC 连接,支持窗口函数,join,聚合,复杂查询等,分析能力极强
- 处理方式简单,无需预处理,全部后处理,没有冗余数据
- 缺点:
- 没有容错能力,当一个 query 分发到多个 Worker 去执行时,当有一个 Worker 因为各种原因查询失败,Master 感知到之后,整个 query 也会失败
- 内存限制,由于 Presto 是纯内存计算,所以当内存不够时,Presto 并不会将结果 dump 到磁盘上,所以查询也就失败了(新版本的 Presto 已经支持写盘操作)
- 并行查询,因为所有的 task 都是并行执行,如果其中一台 Worker 因为各种原因查询很慢,那么整个 query 就会变得很慢
- 并发能力弱,因为全内存操作+内存限制,能同时处理的数据量有限,因而导致并发能力不足
- 实时性较差,不支持数据的实时导入,偏离线处理
- 文档地址
- 简介
- Apache Druid 是一个分布式的、支持实时多维 OLAP 分析的数据处理系统
- 支持高速的数据实时摄入处理
- 支持实时且灵活的多维数据分析查询
- 支持根据时间戳对数据进行预聚合摄入和聚合分析
- 亚秒响应的交互式查询,支持较高并发
- 结构
- Master
- Coordinator:负责集群 Segment 的管理和发布,并确保 Segment 在 Historical 集群中的负载均衡
- Overlord:负责接受任务、协调任务的分配、创建任务锁以及收集、返回任务运行状态给客户端;在 Coordinator 节点配置 asOverlord,让 Coordinator 具备 Overlord 功能,这样可以减少一个组件的部署和运维
- Query
- Router 节点:可选节点,在 Broker 集群之上的 API 网关,有了 Router 节点 Broker 不再是单点服务了,提高了并发查询的能力
- Broker:负责从客户端接收查询请求,并将查询请求转发给 Historical 节点和 MiddleManager 节点。Broker 节点需要感知 Segment 信息在集群上的分布
- Data
- Middle Manager:主要是负责数据索引,生成索引文件,并把索引文件先发布到一个共享的存储系统里
- Historical:主要负责加载索引文件,同时提供历史数据的查询服务
- Metastore Storage:用于存储 Druid 的各种元数据信息,属于 Druid 的外部依赖组件,生产环境中可用 MySQL
- Zookeeper:分布式协调服务,用于节点管理和事件监控
- Deep Storage:用于存储 Segment 文件供 Historical 节点下载。Deep Storage 不属于 Druid 内部组件,用户可根据系统规模来自定义配置。单节点可用本地磁盘,分布式可用 HDFS
- Master
- 数据结构
- DataSource:DataSource 是一个逻辑概念,表示 Druid 的基本数据结构,可以理解为关系型数据库中的表。它包含时间、维度和指标三列
- 时间(TimeStamp):表明每行数据的时间值,默认使用 UTC 时间格式且精确到毫秒级别。这个列是数据聚合与范围查询的重要维度
- 维度(Dimension):标识数据行的各个类别信息
- 指标(Metric):用于聚合计算的列,这些指标列通常是一些数字,主要操作包括 Count、Sum 和 Mean 等
- Segment:Segment 是 Druid 中数据的实际物理存储格式,Druid 正是通过 Segment 实现了对数据的横纵向切割(Slice and Dice)操作
- 横向:通过参数 segmentGranularity 的设置,将不同时间范围内的数据存储在不同的 Segment 数据块中。这样在指定时间范围内查询时,可以不用扫全表
- 纵向:即列式存储,对每个列进行切分并压缩,且利用 Bitmap 构建索引从而优化数据访问
- DataSource:DataSource 是一个逻辑概念,表示 Druid 的基本数据结构,可以理解为关系型数据库中的表。它包含时间、维度和指标三列
- Druid 为何高性能
- 数据预聚合
- Druid 可以按照给定的时间粒度和所有维度列,进行最细粒度的指标聚合运算,并加以保存为原始数据
- 列式存储
- 对部分列进行查询时可以显著提高效率
- Bitmap 索引
- 利用位图对所有维度列构建索引,可以快速定位数据行
- mmap
- 通过内存映射文件的方式加快对于 Segment 的访问
- 查询结果的中间缓存
- 支持对于查询级别和 segment 级别的缓存
- 数据预聚合
- 适合场景
- 网络流量分析、监控系统、APM
- 数据运营和营销
- BI 分析/OLAP
- 优点:
- 性能高,列存压缩,预聚合加上倒排索引以及位图索引,亚秒级查询速度,并发能力强
- 易用性强,支持 JSON 查询,支持 ANSI-SQL,支持 HDFS 离线数据导入,支持 Kafka 实时数据导入,有强大的管理后台工具
- 支持的数据规模大,扩展性强,占用硬件空间小
- 支持根据时间戳对数据进行预聚合摄入和聚合分析
- 并发能力强
- 缺点:
- 不支持大表 join
- 不支持更新
- 简介
- 2016 年 6 月,俄罗斯的搜索引擎 Yandex 公司开源的一款高性能的分布式数据库,C++实现
- 采用列式存储、多核并行化处理和向量化
- 支持实时数据写入,能够支持万亿级别的数据量
- 它在大数据领域没有走 Hadoop 生态,而是采用 Local attached storage 作为存储
- 优点:
- 易用性强,支持 ANSI-SQL,支持 MySQL、HDFS 等数据源离线数据导入,支持 Kafka 实时数据导入
- 并发能力强,查询速度极快(尤其是单表查询),支持索引
- 关系型数据库,支持批量删除或修改数据
- 缺点:
- 不支持二级索引
- SQL 支持有限
- 简介
- 2017 年 8 月,百度公司终于开源的分布式数据分析数据库,在 2018 年贡献给 Apache 社区,并将名字改为 Apache Doris(incubating)进行正式孵化
- 于列式存储、向量化执行、MVCC 的实现,结合了谷歌 mesa 以及 Impala 的优势
- 结构
- Doris 由 frontend(FE)和 backend(BE)组成
- FE 提供横向扩展和高可用:
- FE 节点分为 follower 和 observer 两类。各个 FE 之间,通过 bdbje(BerkeleyDB Java Edition)进行 leader 选举,数据同步等工作
- follower 节点通过选举,其中一个 follower 成为 leader 节点,负责元数据的写入操作。当 leader 节点宕机后,其他 follower 节点会重新选举出一个 leader,保证服务的高可用
- observer 节点仅从 leader 节点进行元数据同步,不参与选举。可以横向扩展以提供元数据的读服务的扩展性
- BE 负责数据存储与管理
- FE 提供横向扩展和高可用:
- Doris 由 frontend(FE)和 backend(BE)组成
- 优点:
- 易用性强,高度支持 ANSI-SQL
- 支持数据列式存储,对数据列的动态增减方便
- BE、FE 的扩容简单
- 支持离线数据导入(hadoop 和文件)和近实时数据导入(kafka)
- 缺点:
- Doris 数据格式支持较简单
- 简介
- Apache Kylin 是一个开源的分布式分析引擎
- 提供 Hadoop/Spark 之上的 SQL 查询接口及多维分析(OLAP)能力以支持超大规模数据
- 最初由 eBay Inc 开发并贡献至开源社区
- 它能在亚秒内查询巨大的 Hive 表
- Kylin 的核心思想是预计算,将数据按照指定的维度和指标,预先计算出所有可能的查询结果,利用空间换时间来加速查询模式固定的 OLAP 查询
- 基本原理
- 利用 MapReduce/Spark 将原始数据进行聚合计算,转成了 OLAP Cube 并加载到 HBase 中,以 Key-Value 的形式存储
- Cube 按照时间范围划分为多个 segment,每个 segment 是一张 HBase 表,每张表会根据数据大小切分成多个 region
- 优点:
- 易用性强,支持 ANSI-SQL,可通过 ODBC,JDBC 以及 RESTful API 进行访问,提供了管理后台
- 支持百亿、千亿甚至万亿级别交互式分析
- 查询速度快,Kylin 的 Cube 预处理会大幅减小在线数据规模,对于超大规模数据更有优势
- 缺点:
- 多维索引要对多维度的各种组合作预计算,离线建索引需要较大计算量和时间,最终索引也会占用较多磁盘空间
- Pinot 是一个类 druid 的分布式分析引擎。由 LinkedIn 开发和维护
- 支持离线数据导入(hadoop 和文件)和近实时数据导入(kafka)
- 结构
- Pinot Controller
- 管理集群中的节点
- 处理 Table 和 Segment 的上的所有创建,更新,删除操作
- 计算表及其段到 Pinot 服务器的分配
- PinotServer
- 保存一个或者多个物理的 Segment
- 当被分配一个预先创建的 segment,下载并且装载这个 Segment
- 当被分配一个 Kafka Topic,从 kafka 的 partion 的一个子集中消费数据 执行查询请求并将结果返回给 PinotBroker
- Pinot Broker
- 接收客户端的查询请求,并且将他们路由到多个服务上(根据路由策略), 合并接收的查询结果并返回给客户端
- Pinot Controller
- 优点:
- 性能高,提供多种压缩模式,如运行长度、固定比特长度
- 可插入式的索引技术,包括可排序索引、Bitmap 索引和反向索引
- 数据聚合查询能力和数据写入能力极强,实时性好,近乎实时的从 Kafka 获取数据,以及批量从 Hadoop 获取数据,扩展性强
- 易用性强,支持 JDBC,有完整的管理工具
- 缺点:
- 不支持 join
- Impala 是 Cloudera 由 C++编写的基于 MPP(massively parallel processing)理念的查询引擎
- 由运行在 Apache Hadoop 集群上的不同的守护进程组成,它跟 Hive 的 metastore 集成,共用 database 和 tables 等信息
- 实时性能一般,只能用于 HDFS 的离线计算
- 简介
- Spark 是一种快速、通用、可扩展的大数据分析引擎,2009 年诞生于加州大学伯克利分校 AMPLab,2010 年开源,2013 年 6 月成为 Apache 孵化项目,2014 年 2 月成为 Apache 顶级项目。项目是用 Scala 进行编写
- Spark 是基于内存计算的大数据并行计算框架
- 目前,Spark 生态系统已经发展成为一个包含多个子项目的集合,其中包含 SparkSQL、Spark Streaming、GraphX、MLib、SparkR 等子项目
- 核心组件
- Spark Core
- 实现了 Spark 的基本功能,包含任务调度、内存管理、错误恢复、与存储系统 交互等模块
- Spark Core 中还包含了对弹性分布式数据集(resilient distributed dataset,简称 RDD)的 API 定义
- Spark SQL
- 是 Spark 用来操作结构化数据的程序包。通过 Spark SQL,我们可以使用 SQL 或者 Apache Hive 版本的 SQL 方言(HQL)来查询数据
- Spark SQL 支持多种数据源,比 如 Hive 表、Parquet 以及 JSON 等
- Spark Streaming
- 是 Spark 提供的对实时数据进行流式计算的组件。提供了用来操作数据流的 API,并且与 Spark Core 中的 RDD API 高度对应
- Spark MLlib
- 提供常见的机器学习(ML)功能的程序库。包括分类、回归、聚类、协同过滤等,还提供了模型评估、数据 导入等额外的支持功能
- Cluster Manager
- Spark 设计为可以高效地在一个计算节点到数千个计算节点之间伸缩计 算。为了实现这样的要求,同时获得最大灵活性,Spark 支持在各种集群管理器(cluster manager)上运行,包括 Hadoop YARN、Apache Mesos,以及 Spark 自带的一个简易调度 器,叫作独立调度器
- Spark Core
- Spark 运行模式
- Local:多用于本地测试
- Standalone:即独立模式,自带完整的服务,可单独部署到一个集群中,无需依赖任何其他资源管理系统。它是 Spark 实现的资源调度框架,其主要的节点有 Client 节点、Master 节点和 Worker 节点
- Spark On Yarn:yarn 是统一的资源管理机制,在上面可以运行多套计算框架,如 map reduce、storm 等根据 driver 在集群中的位置不同,分为 yarn client 和 yarn cluster。生产环境上一般使用 yarn cluster 模式
- Spark On Mesos:mesos 是一个更强大的分布式资源管理框架,它允许多种不同的框架部署在其上,包括 yarn
- 结构
- Client:客户端进程,负责提交作业到 Master
- Master:Standalone 模式中主控节点,负责接收 Client 提交的作业,管理 Worker,并命令 Worker 启动 Driver 和 Executor,控制整个集群,监控 worker
- Worker:负责管理本节点的资源,定期向 Master 汇报心跳,接收 Master 的命令,启动 Driver。Executor,即真正执行作业的地方,一个 Executor 可以执行一到多个 Task
- Driver: 一个 Spark 作业运行时包括一个 Driver 进程,也是作业的主进程,负责作业的解析、生成 Stage 并调度 Task 到 Executor 上。包括 DAGScheduler,TaskScheduler
- Executor:即真正执行作业的地方,一个集群一般包含多个 Executor,每个 Executor 接收 Driver 的命令 Launch Task,一个 Executor 可以执行一到多个 Task
- 优点:
- 速度快
- 与 Hadoop 的 MapReduce 相比,Spark 基于内存的运算要快 100 倍以上,基于硬盘的运算也要快 10 倍以上。Spark 实现了高效的 DAG 执行引擎,可以通过基于内存来高效处理数据流
- 易用性强
- Spark 支持 Java、Python 和 Scala 的 API,还支持超过 80 种高级算法,使用户可以快速构建不同的应用。而且 Spark 支持交互式的 Python 和 Scala 的 shell,可以非常方便地在这些 shell 中使用 Spark 集群来验证解决问题的方法
- Spark 提供了统一的解决方案。Spark 可以用于批处理、交互式查询(Spark SQL)、实时流处理(Spark Streaming)、机器学习(Spark MLlib)和图计算(GraphX)。这些不同类型的处理都可以在同一个应用中无缝使用
- Spark 可以非常方便地与其他的开源产品进行融合。比如,Spark 可以使用 Hadoop 的 YARN 和 Apache Mesos 作为它的资源管理和调度器,器,并且可以处理所有 Hadoop 支持的数据,包括 HDFS、HBase 和 Cassandra 等
- Spark 也可以不依赖于第三方的资源管理和调度器,它实现了 Standalone 作为其内置的资源管理和调度框架,这样进一步降低了 Spark 的使用门槛,使得所有人都可以非常容易地部署和使用 Spark
- Spark 还提供了在 EC2 上部署 Standalone 的 Spark 集群的工具
- 速度快
- 缺点:
- 占用内存过大,不能处理过大的数据
- 简介
- Apache Storm 是一个开源的、实时的、分布式以及具备高容错的分布式实时计算系统
- Storm 支持水平扩展,具有高容错性
- 它与 Spark Streaming 的最大区别在于它是逐个处理流式数据事件,而 Spark Streaming 是微批次处理,因此,它比 Spark Streaming 更实时
- 核心概念
- Nimbus:即 Storm 的 Master,负责资源分配和任务调度。一个 Storm 集群只有一个 Nimbus
- Supervisor:即 Storm 的 Slave,负责接收 Nimbus 分配的任务,管理所有 Worker,一个 Supervisor 节点中包含多个 Worker 进程
- Worker:工作进程,每个工作进程中都有多个 Task
- Task:任务,在 Storm 集群中每个 Spout 和 Bolt 都由若干个任务(tasks)来执行。每个任务都与一个执行线程相对应
- Topology:计算拓扑,Storm 的拓扑是对实时计算应用逻辑的封装,它的作用与 MapReduce 的任务(Job)很相似,区别在于 MapReduce 的一个 Job 在得到结果之后总会结束,而拓扑会一直在集群中运行,直到你手动去终止它。拓扑还可以理解成由一系列通过数据流(Stream Grouping)相互关联的 Spout 和 Bolt 组成的的拓扑结构
- Stream:数据流
- 简介
- Apache Flink 是一款分布式的流式计算引擎,它同时支持了批处理和流处理
- 支持 java 和 scala api
- 支持 Kafka、RabbitMq 等多种数据源,也可以自定义扩展数据源,读取其他类型的数据库作为数据源
- 兼容 Hadoop 的 MapReduce 和 Storm
- 集成了 Yarn、HDFS、HBase 和其它 hadoop 生态系统的组件
- 简介
- Apache Flume 是 Cloudera 公司开源出来的一个分布式、可靠性和高可用的流式日志采集工具
- Flume 采用了三层架构,分别为 agent,collector 和 storage,每一层均可以水平扩展。其中,所有 agent 和 collector 由 master 统一管理,这使得系统容易监控和维护,且 master 允许有多个(使用 ZooKeeper 进行管理和负载均衡),避免了单点故障问题
- FLume 提供对数据进行简单处理并且写到各种数据接收方(可定制)的能力
- Flume 提供从本地文件(spooling directory source)、实时日志(taildir、exec)、REST 消息、Thift、Avro、Syslog、Kafka 等数据源上收集数据的能力
- Flume Agent 架构
- source
- source 组件是专门用来收集数据的,可以处理各种类型、各种格式的日志数据,包括 avro、thrift、exec、jms、spooling directory、netcat、sequence generator、syslog、http、legacy、自定义数据等
- channel
- source 组件把数据收集以后,临时存放在 channel 中,即 channel 组件在 agent 中是专门用来存放临时数据的——对采集到的数据进行简单的缓存,可以存放在 memory、jdbc、file 等
- Memory Channel:不会持久化。消息存放在内存中,提供高吞吐,但提供可靠性;可能丢失数据
- File Channel:对数据持久化;基于 WAL(预写式日志 Write-Ahaad Log)实现。但是配置较为麻烦,需要配置数据目录和 checkpoint 目录;不同的 file channel 均需要配置一个 checkpoint 目录,且性能一般
- JDBC Channel:基于嵌入式 Database 实现。内置 derby 数据库,对 event 进行了持久化,提供高可靠性;可以取代同样持久特性的 file channel
- sink
- sink 组件是用于把数据发送大目的地 的组件,目的地包括 hdfs、logger、avro、thrift、ipc、file、null、hbse、solr、自定义
- source
- 运行机制
- source 接收到数据之后,将数据发送给 channel
- channel 作为一个数据缓冲区会临时存放这些数据
- 随后 sink 会将 channel 中的数据发送到指定的地方——例如 hdfs 等
- 只有在 sink 将 channel 中的数据发送成功后,channel 才会将临时的数据进行删除,这种机制保证了数据传输的可靠性与安全性
- 彩虹表是一个用于加密散列函数逆运算的预先计算好的表,常用于破解加密过的密码散列
- 彩虹表常常用于破解长度固定且包含的字符范围固定的密码(如信用卡、数字等)。这是以空间换时间的典型实践,比暴力破解(Brute force)使用的时间更少,空间更多
- 但与储存密码空间中的每一个密码及其对应的哈希值(Hash)实现的查找表相比,其花费的时间更多,空间更少
- 使用加盐的密钥派生函数可以使这种攻击难以实现
- IaaS:基础设施服务,Infrastructure-as-a-service
- IaaS 是云服务的最底层,主要提供一些基础资源。它与 PaaS 的区别是,用户需要自己控制底层,实现基础设施的使用逻辑
- 案例:Amazon EC2、RackSpace Cloud 等
- PaaS:平台服务,Platform-as-a-service
- PaaS 提供软件部署平台(runtime),抽象掉了硬件和操作系统细节,可以无缝地扩展(scaling)。开发者只需要关注自己的业务逻辑,不需要关注底层
- 案例:Google App Engine、OpenShift 等
- SaaS:软件服务,Software-as-a-service
- SaaS 是软件的开发、管理、部署都交给第三方,不需要关心技术问题,可以拿来即用
- 案例:Google Apps、Facebook / Twitter / Instagram 等
- SaaS 模式下用户没有任何自主权,只能使用给定的应用程序
- PaaS 模式下可以自己安装应用程序,但是不能定制操作系统
- IaaS 模式下则是云服务商提供(虚拟的)硬件,从操作系统开始都可以自己选择和定制