大数据基础复习
大数据复习
第一章、大数据概述
1.1 大数据时代
背景:2010年前后,大数据、云计算、物联网的快速发展,拉开了第三次信息化浪潮的大幕。
大数据时代的技术支撑:
- 存储设备容量不断增加,读写速度提升,价格下降
- CPU处理能力大幅提高,促进数据量的增加,“摩尔定律”
- 网络带宽不断增加,网络覆盖范围和速度都增加
数据产生方式的变革促成了大数据时代的来临:
- 阶段一:运营式系统阶段
- 自数据库诞生开始
- 数据库总保存了大量结构化的企业关键信息
- 数据的产生方式是被动的,依赖于实际业务的发生
- 阶段二:用户原创内容阶段
- 互联网的出现
- 数据传播不需要借助于磁盘、磁带
- Web 2.0
- 阶段三:感知式系统阶段
- 物联网的发展
- 诸多传感器自动采集数据
大数据的发展历程:
- 萌芽期:21世纪初
- 数据挖掘理论提出
- 数据库技术成熟
- 成熟期:21世纪前 10年
- Web 2.0迅猛发展
- 形成了并行计算和分布式系统两大核心技术
- 谷歌的 GFS和 MapReduce
- Hadoop
- 大规模:2010年后
- 数据驱动决策
1.2 大数据的概念
大数据有 “4V”的说法,分别表示:数据量大(Volume)、数据类型繁多(Variety)、处理速度快(Velocity)和价值密度低(Value)
数据量大:
- 人类进入信息社会初期,数据以自然方式增长
- Web 2.0后,产生第一次 数据爆炸
- 物联网技术的提出,产生了第二次 数据爆炸
- “大数据摩尔定律”:数据以每年 50%的速度增长
- 量变引起质变
数据种类繁多:
- 数据来源繁多,科学研究、企业应用、Web应用都产生大量数据
- 类型多样:
- 消费者大数据
- 金融大数据
- 医疗大数据
- 城市大数据
- 工业大数据
- 既有 结构化数据(10%),又有 非结构化数据(90%)
处理速度快:
- 数据产生速度快
- 需要基于快速生成的数据给出 实时分析 结果
价值密度低:
- 价值密度远远低于传统关系数据库中的数据
- 有价值的数据分布于海量数据中
1.3 大数据的影响
大数据对科学研究、思维方式、社会发展、就业市场和人才培养都有影响。
大数据对 科学研究 的影响:
- 第 1 种范式:实验科学
- 人类采用实验来解决一些科学问题
- 第 2 种范式:理论科学
- 采用数学、几何、物理等理论,构建问题模型和寻找解决方案
- 第 3 种范式:计算科学
- 以 “计算”为中心
- 借助计算机,通过编写算法,来实现高速运算
- 先提出理论,再搜集数据,然后通过计算来验证
- 第 4 种范式:数据密集型科学
- 以“数据”为中心
- 先有了大量数据,再通过计算发现未知的理论
大数据对 思维方式 的影响:
- 全样而非抽样
- 过去由于存储和处理能力有限,通常采用抽样的方式来推断全集数据的总体特征
- 有了大数据技术的支持,可以直接对全集数据进行处理操作
- 效率而非精准
- 在抽样分析中,必须追求方法的精确性,否则在应用到全集后,误差会被放大
- 由于采用 全样而非抽样的思想,“快速响应”成了新的要求,因此数据分析强调效率
- 相关而非因果
- 过去数据分析的目标为:解释事物背后的发展机理 和 预测未来可能发生的事
- 在大数据时代,“因果性”不再重要,相反“相关性”才是人们追求的
大数据对 社会发展 的影响:
- 大数据决策成为一种新的决策方式
- 根据数据制定决策
- 面向多类型、非结构化的海量数据进行决策分析
- 大数据应用促进 信息技术 与 各行业 的深度融合
- 大数据开发推动 新技术 和 新应用 的不断涌现
大数据对 就业市场 的影响:
- 数据科学家炙手可热
大数据对 人才培养 的影响
- 高校培养
- 企业培养
1.4 大数据的应用
可用于:制造、金融、汽车、互联网、餐饮、电信、能源、物流、城市管理、生物医学、体育娱乐、安全领域、个人生活等。
1.5 大数据的关键技术
所谓的大数据技术,是指伴随着大数据的采集、存储、分析和结果呈现的相关技术
大数据技术层面 | 功能 |
---|---|
数据采集和预处理 | ETL工具,进行数据转换、清洗、集成、加载; 日志采集工具,把实时采集的数据作为流计算系统的输入 |
数据存储和管理 | 利用 分布式文件系统、数仓、RDB、NoSQL、云数据库等进行存储 |
数据处理与分析 | 利用 分布式并行编程模型和计算框架; 对分析结果进行可视化呈现 |
数据安全和隐私保护 | 构建数据安全体系和隐私数据保护体系 |
1.6 大数据计算模式
大数据的计算模式包括:批处理计算、流计算、图计算、查询分析计算等
计算模式 | 解决的问题 | 代表产品 |
---|---|---|
批处理计算 | 大规模数据的批量处理 | MapReduce、Spark |
流计算 | 流数据的实时计算 | Flume、Storm、S4、Flink |
图计算 | 大规模图结构数据的处理 | Pregel、GraphX、Giraph、Hama |
查询分析计算 | 大规模数据的存储管理和查询分析 | Hive、Cassandra |
批处理计算:
- MapReduce 用于大规模数据集(大于 1TB)的并行运算
- 它将复杂的并行运算抽象为两个函数—— Map 和 Reduce
- Spark是一个低延迟的集群分布式计算系统,启用了内存分布数据集
- 提供交互式查询、优化迭代工作负载
- 使用内存作为中间结果的存储媒介
流计算:
- 流数据是指在时间分布和数量上无限的动态数据集合体,数据价值随时间流逝而降低
- 必须采用实时计算给出秒级响应
图计算:
- MapReduce作为单输入、两阶段、粗粒度数据并行的分布式计算框架,在表达多迭代、稀疏结构和细粒度数据时,力不从心
1.7 大数据产业
大数据产业指一切与支撑大数据组织管理和价值发现相关的企业经济活动的集合
1.8 大数据与云计算、物联网
大数据、云计算和物联网代表了 IT领域最新的技术发展趋势,三者相辅相成。
云计算:
- 云计算实现了通过网络提供可伸缩的、廉价的分布式计算能力
- 包括 3种典型的 服务模式:基础设施即服务(IaaS)、平台即服务(PaaS)、软件即服务(SaaS)
- 云计算包括:公有云、私有云和混合云 3种类型
- 云计算的关键技术:
- 虚拟化,将一台计算机虚拟为多台逻辑计算机,被虚拟的对象可以是硬件也可以是软件,容器技术
- 分布式存储,HDFS,GFS,HBase,BigTable
- 分布式计算,MapReduce,把一个大数据集切分成多个小数据的批量处理工作
- 多租户
- 云计算产业:
- IaaS,将基础设施(计算和存储等资源)作为服务出租,IBM、微软
- PaaS,把平台作为服务出租,谷歌、阿里、新浪
- SaaS,把软件作为服务出租,谷歌、Salesforce
物联网:
- 物联网是物物相联的互联网,是互联网的延伸
- 技术架构上可以分为四层:感知层、网络层、处理层、应用层
- 关键技术:
- 识别和感知技术
- 网络和通信技术
- 数据挖掘和融合技术
大数据与云计算、物联网的关系:
- 大数据侧重与对海量数据的存储、处理和分析
- 云计算旨在整合和优化各种 IT资源
- 物联网的发展目标是实现“物物相连”
第二章、大数据处理架构 Hadoop
Hadoop是一个开源的、可运行于大规模集群上的分布式计算平台,它实现了 MapReduce计算模型和分布式文件系统 HDFS等功能
2.1 概述
Hadoop是基于 Java语言开发的,核心是 MapReduce和 HDFS;
Hadoop的特性:
- 高可靠性,有多个数据副本
- 高效性,分布式存储和分布式处理
- 高可扩展性,可以高效稳定的运行在廉价的计算机集群上
- 高容错性,自动保存数据的多个副本,自动将失败的任务重新分配
- 成本低,采用廉价的计算机集群
- 运行在 Linux操作系统上
- 支持多种编程语言
Hadoop的应用现状:
- 国内采用 Hadoop的公司主要有:百度、淘宝、网易、华为、移动;其中淘宝的 Hadoop集群较大
- 华为是 Hadoop的使用者,同时也是该技术的重要推动者,贡献榜上排名前列
2.2 Hadoop生态系统
除了核心的 HDFS和 MapReduce之外,还包括 ZK、HBase、Hive等
Hadoop2.0中新增了一些重要的组件,即 HDFS HA和 Yarn
HDFS:
- 针对 GFS的开源实现
- 具有处理超大数据、流式处理、运行在廉价商用服务器上等特点
HBase:
- 是一个提供高可靠、高性能、可伸缩、实时读写、分布式的列式数据库
- 一般采用 HDFS作为其底层数据存储系统
- 是对 BigTable的开源实现
- 具有良好的横向扩展能力
MapReduce:
- 是对 MapReduce的开源实现
- 将复杂的、运行与大规模集群上的并行计算抽象为两个函数 Map和 Reduce
- 核心思想是 “分而治之”
- 把输入的数据集切分为若干个数据块,分发给各个分结点共同并行完成;最后再通过中间节点得到最终结果
Hive:
- 基于 Hadoop的数据仓库工具
- 可以对 Hadoop文件中的数据集进行数据整理、特殊查询和分析存储
- 可以通过 HiveQL语句快速简单地实现 MapReduce任务,试用与统计分析
Pig:
- 是一种数据流语言和运行环境
- 在 MapReduce的基础上创造力更简单抽象的过程语言
- 可以编写 Pig脚本实现集群中自动并行处理和分发
ZooKeeper:
- 对 Chubby的开源实现
- 提供了分布式锁、统一命名、状态同步、集群管理、应用配置等服务
- 减轻了分布式应用程序所承担的协调任务
Flume:
- 用于日志采集、聚合和传输
Sqoop:
- Sql-to-Hadoop的缩写
- 用于 Hadoop和 RDB之间的数据交互
- 使用 JDBC连接
- 支持增量更新
第三章、分布式文件系统 HDFS
大数据时代必须解决海量数据的高效存储问题,HDFS是针对 GFS的实现,是 Hadoop两大核心组成部分之一,具有在廉价服务器集群中进行大规模分布式文件存储的能力,且具有良好的容错能力
3.1 分布式文件系统
分布式文件系统是一种通过网络实现文件在多台主机上进行分布式存储的文件系统
计算机集群结构:
- 分布式文件系统把文件分布存储到多个计算机节点上,成千上万的计算机节点构成计算机集群
- 集群中的计算机节点存放在机架上,每个机架可以存放 8~64个节点
- 同一机架上的不同节点之间通过网络互联;不同机架之间采用另一级网络或交换机互联
分布式文件系统结构:
-
操作系统中,如 Linux,文件系统一般会把磁盘空间划分为每 512Byte一组,称为“磁盘块”,
- 它是文件系统进行读写操作的最小单位
- 文件系统的块通常是磁盘块的整数倍,即每次读写的数据量必须是磁盘块大小的整数倍
-
分布式文件系统中也采用了 块 的概念
- 文件被分成若干个块进行存储,块是数据读写的基本单元
- HDFS默认的一个块大小是 64MB
- 注意:如果一个文件小于一个数据块的大小,它并不占用整个数据库的存储空间
-
分布式文件系统在物理结构上由集群中多个节点构成,分为:主节点(名称节点)和 从节点(数据节点)
- 名称节点 负责文件和目录的创建、删除和重命名等
- 同时管理着数据节点和文件块之间的映射关系
- 数据节点 负责数据的存储和读取
- 存储时,由名称节点分配存储位置,然后有客户端把数据写入相应的数据节点
- 读取时,客户端从名称节点获得数据节点和文件块的映射关系,然后放问道对应的文件块
- 数据节点也要根据名称节点的命令创建、删除和复制数据块
- 名称节点 负责文件和目录的创建、删除和重命名等
-
集群中的节点可能发生故障,为了保证数据的完整性,采用多副本存储
- 存储同一文件块的不同副本的各个节点会分布在不同的机架上
-
HDFS是针对大规模数据存储而设计的,在 TB量级以上,规模过小会影响系统的扩展和性能
分布式文件系统的设计需求:
设计需求 | 具体含义 | HDFS的实现情况 |
---|---|---|
透明性 | 1. 具有访问透明性、位置透明性、性能和伸缩透明性 2. 用户能够通过相同的操作来访问本地文件和远程文件资源 |
只能支持一定程度的访问透明性 完全支持位置透明、性能和伸缩透明 |
并发控制 | 一个客户端对文件的读写不影响其他客户端对同一个文件的读写 | 任何时间都只允许有一个程序写文件 |
文件复制 | 一个文件可以拥有不同位置的多个副本 | 多副本 |
硬件和操作系统的异构性 | 在不同的操作系统和计算机上实现同样的客户端和服务器端程序 | 基于 Java,跨平台 |
可伸缩性 | 支持节点的动态加入和退出 | 可建立集群,伸缩性好 |
容错 | 保证文件服务在和客户端或者服务端出现问题的时候能正常使用 | 具有多副本机制和故障自动检测、恢复机制 |
安全 | 保证系统的安全性 | 安全性较弱 |
3.2 HDFS简介
HDFS在设计上采取了多种机制保证在硬件出错的环境下实现数据的完整性
HDFS要实现以下目标:
- 兼容廉价的硬件设备
- HDFS设计了快速检测硬件故障和进行自动恢复的机制,实现持续监视、错误检查、容错处理和自动恢复
- 可以在硬件出错的情况下实现数据的完整性
- 流数据的读写
- HDFS放松了一些 POSIX的要求,从而能够以流式方式访问文件系统数据
- 大数据集
- 文件单个通常可达 GB、TB级别
- 简单的文件模型
- 采用“一次写入,多次读取”的简单文件模型
- 强大的平台兼容性
- 采用 Java编写,基于 JVM,有良好的平台兼容性
HDFS的局限性:
- 不适合低延迟访问数据
- 无法高效存储大量 小文件
- 小文件是指文件大小小于一个块的文件
- HDFS采用名称节点存储文件的 元数据,保存在内存中,便于快速获取存储位置
- 通常,每个文件基本信息、目录和块占 150Byte,大量的文件数量会导致元数据检索效率的降低
- 且 当元数据增加时,内存空间的占用也会增多
- 且 用 MapReduce处理大量小文件时,会产生过多的 Map任务,进程管理开销巨大
- 且 访问大量小文件的速度远小于访问等容量的大文件,需要不断的进行数据节点的读取切换
- 不支持多用户写入及任意修改文件
- HDFS只支持一个文件有一个写入者
- 且 仅支持追加操作,不能进行随机写操作
3.3 HDFS的相关概念
块、名称节点、数据节点、第二名称节点
块:
- 在传统的文件系统中,为了提高磁盘读写效率,一般以数据块为单位,而不是以字节为单位
- HDFS同样采用了块的概念,默认的块大小为 64MB
- HDFS中的文件会被拆分成多个块,每个块作为独立的单元进行存储
- 之所以设计较大的块大小,是为了减小文件寻址的开销
- 客户端读取文件的流程:
- 从名称节点获得组成这个文件的数据块的位置列表
- 根据位置列表获取实际存储各个数据库的数据节点的位置
- 数据节点根据数据块信息在本地 Linux文件系统上找到对应的文件
- 返回给客户端
- 块的大小也不宜过大
- 通常 MapReduce中的 Map任务一次处理一个块中的数据,如果 块太大,启动的任务太少,会影响并行处理速度
- 采用抽象块概念的好处:
- 支持大规模文件的存储
- 一个文件的大小不会受到单个节点的存储容量的限制
- 简化系统设计
- 容易计算一个结点可以存储多少个块
- 方便元数据的管理,元数据不需要和文件块存储在一起,可以由其他系统负责管理元数据
- 适合数据备份
- 每个文件块都可以冗余存储到多个节点上,提高了容错性和可用性
- 支持大规模文件的存储
名称节点:
-
名称节点负责管理分布式文件系统的命名空间(Namespace),保存了两个核心数据结构 FsImage 和 EditLog
-
FsImage 用于维护文件系统树,以及文件树中所有的文件和文件夹的元数据
-
EditLog 记录了所有针对文件的创建、删除、重命名等操作
-
名称节点记录了每个文件中各个块所在的数据节点的位置信息
- 并不持久化地存储这些信息,而是会在系统每次启动时扫描所有数据节点,进行重构
-
名称节点的启动:
- 将 FsImage的内容加载到内存中
- 执行 EditLog文件中的各种操作,使内存中的元数据保持最新
- 创建一个新的 FsImage文件和一个空的 EditLog文件
- 名称节点启动成功并进入正常运行状态,之后的所有更新操作都会被写入 EditLog中,而不是直接到 FsImage
- 因为 FsImage文件通常都很大,如果所有的更新操作都在 FsImage中,系统的运行速度会变慢
- 而 EditLog通常远小于 FsImage,更新操作高效
-
名称节点启动过程中处于“安全模式”,HDFS只能读不能写
数据节点:
- 是分布式文件系统 HDFS的工作节点
- 会根据 客户端 或者 名称节点 的调度来进行数据的存储和检索
- 向 名称节点 定期发送自己所存储的 文件块的列表
- 每个数据节点中的数据会被保存在各自的本地 Linux文件系统中
第二名称节点:
-
在名称节点运行期间,HDFS不断产生更新操作,写入 EditLog中,因此 EditLog文件会逐渐变大
-
当名称节点重启时,需要将 FsImage加载到内存中,并执行 EditLog中的记录
- 此时如果 EditLog很大,就会导致整个过程变得非常缓慢,使得名称节点长期处于“安全模式”中
-
第二名称节点(Secondary NameNode)有两方面功能:
- 完成 EditLog和 FsImage的合并操作,减小 EditLog文件的大小
- 每个一段时间,同名称节点通信,请求其停止使用 EditLog文件,暂时将新到达的写操作添加到 EditLog.new文件中
- 把名称节点中的 FsImage和 EditLog 拉取到本地,进行合并,使得 FsImage保持最新
- 将合并后得到的最新的 FsImage.ckpt发送到名称节点,名称节点收到后用 FsImage.ckpt替换原有的 FsImage,并用 EditL.new替换 EditLog
- 作为名称节点的“检查节点”,保存名称节点中的元数据信息
- 周期性地备份名称节点中的元数据信息,当名称节点发送故障时,可以用它的元数据信息进行恢复
- 但是恢复的信息仅是上一次合并时的数据,相比于最新的,会有一段缺失
- 故,2NN不能起到“热备份”的作用,只能是作为“检查点”
- 完成 EditLog和 FsImage的合并操作,减小 EditLog文件的大小
3.4 HDFS体系结构
HDFS采用主从(Master/Slave)结构模型,一个 HDFS集群包括一个名称节点和若干个数据节点;
名称节点作为中心服务器,负责管理文件系统的命名空间和客户端对文件的访问;
数据节点一般是一个结点对应一个进程,负责处理文件系统客户端的读写请求,在 NN的调度下进行数据块的创建、删除和复制等;
每个数据节点会周期性地向名称节点发送 “心跳”信息,报告自己的状态,没有发送的被标记为 “死机”,不再分配 IO请求
文件访问:
-
可以像普通文件系统一样,使用文件名存储和访问文件
-
在系统内部,一个文件被切分成多个数据块,分别存储到若干个 DN上
-
客户端访问一个文件,发送给 NN,NN根据文件名找到对应的 数据块和 DN的映射
-
根据数据块信息找到 DN,把 DN位置发送给客户端
-
最后客户端直接访问这些 DN获取数据
-
注意:在整个访问过程中,NN并不参与数据的传输,这样可以实现一个文件的数据在不同数据节点上并发访问
名称节点:
-
HDFS集群中只有唯一一个名称节点,负责所有元数据的管理,
-
简化了分布式文件系统的结构
-
保证数据不会脱离 NN的控制
-
同时用户数据不会经过 NN,减轻了中心服务器的负担
-
HDFS命名空间管理:
- HDFS的命名空间包涵目录、文件和块
- 命名空间支持对 HDFS中的目录和块进行类似文件系统的创建、修改等基本操作
- HDFS使用的是传统的分级文件体系
- HDFS没有实现磁盘配额和文件访问权限等功能,也不支持软硬连接
通信协议:
- HDFS部署在集群上,很多数据通过网络进行传输
- 所有的 HDFS通信协议都是构建在 TCP/IP基础之上的
- 客户端通过一个可配置的端口向 NN主动发起 TCP连接,并使用 客户端协议与 NN进行交互
- NN和 DN之间使用 **数据节点协议 **进行交互
- 客户端和 DN之间的交互通过 远程过程调用(RPC)来实现
- NN并不会主动发起 RPC,而是响应来自客户端和 DN的 RPC请求
客户端:
- 客户端是操作 HDFS最常用的方式
- 客户端提供了类似 Shell的命令行方式访问 HDFS中的数据
- 也支持 JavaAPI,作为应用程序访问文件系统
HDFS体系结构的局限性:
- HDFS只能设置一个 NN
- 命名空间的限制
- NN保存在内存中,因此可容纳的对象数量有限
- 性能的瓶颈
- 整个集群的吞吐量受限于单个 NN的吞吐量
- 隔离问题
- 由于只有一个 NN,无法对不同应用程序进行隔离
- 集群的可用性
- 一旦 NN坏了,整个集群都会不可用
3.5 HDFS的存储原理
数据的冗余存储、数据存取策略、数据错误与恢复
数据的冗余存储:
-
HDFS采用多副本方式对数据进行冗余存储
- 通常一个数据块的多个副本会被分布到不同的 DN上
-
这种存储方式的优点:
- 加快数据传输速度,多个客户端访问同一个文件时,分别从不同的数据块副本中获取数据,加快传输
- 容易检查数据错误,容易判断数据传输是否错误
- 保证数据的可靠性,即使某个数据节点出现故障失效
数据存取策略:
- 数据存放
- HDFS采用了以机架(Rack)为基础的数据存放策略
- HDFS默认每个数据节点都在不同的机架上
- 缺点:写入数据的时候不能充分利用同一机架内部机器之间的带宽
- 优点:获得很高的数据可靠性,可以在多个机架上并行读取数据,更容易实现系统内部负载均衡和错误处理
- HDFS默认的冗余复制因子是 3,每个文件块会同时保存到 3个地方,其中两个在同一机架上,另一个在不同机架上
- 好处:既保证机架发送异常时的数据恢复,也可以提高数据读写性能
- HDFS的副本放置策略:
- 如果是在集群内发起的写操作请求,则把第 1个副本放置在发起写操作请求的数据节点上,实现就近写入
- 如果是在集群外发起的写操作,则挑选空间充足、CPU空闲的数据节点作为第 1个副本的存放地点
- 第 2个副本放在与第 1个副本不同的机架的数据节点上
- 第 3个副本放在与第 1个副本相同的机架的数据节点上
- 如果还有更多的副本,则随机选择数据节点存放
- 数据读取
- 当客户端读取数据时,从名称节点获得数据块的不同副本的存放位置列表,列表中包涵了副本所在的数据节点
- 可以调用 API或 Shell命令确定这些数据节点所属的机架 ID
- 如果某个机架 ID和当前客户端的机架 ID相同,则优先选择该副本
- 否则随机选择一个副本读取数据
- 数据复制
- HDFS的数据复制采用流水线复制的策略
- 具体的流程:
- 客户端发出请求向 HDFS写入一个文件,这个文件首先会被写入本地,切分成多个块
- 每个块都向 HDFS集群中的 NN发起写请求,NN会根据 系统中DN的情况,选择一个 DN列表返回给客户端
- 客户端会把数据首先写入列表中的第 1个 DN,同时把列表传递给第 1个 DN
- 当第 1个 DN接收到 4KB数据的时候,写入本地,并且向列表中的第 2个DN发起连接请求,把该 4KB数据和列表传递给第 2个 DN
- 第 2及之后的 DN执行同样的操作,列表中的多个 DN形成一条数据复制的流水线
- 最后,当文件写完的时候,数据复制也结束了
数据错误与恢复:
- NN出错
- NN保存了所有的元数据,其中最核心的文件是 FsImage和 EditLog,如果 NN损坏,整个 HDFS都会失效
- Hadoop采用两种机制保护 NN:
- 把 NN上的元数据信息同步存储到其他文件系统,比如挂载到远程的网络文件系统中
- 当 NN宕机后,运行 2NN,并利用 2NN中的元数据信息进行系统恢复,但该方法仍会丢失部分数据
- DN出错
- 每个 DN会定期向 NN发送“心跳”信息,如果 NN无法接收,就会标识该 DN为“死机”,其上的所有数据不可读,不发送所有 IO请求
- 此时可能出现如下情景:由于某个 DN的宕机,导致一些数据块的副本数量小于冗余因子
- NN会定期检查上述情况,发现后会启动数据冗余复制,为它生成新的副本
- HDFS与其他分布式文件系统最大的区别就是它可以调整冗余数据的位置
- 数据出错
- 网络传输和磁盘错误都会导致数据错误
- 文件 上传时 的措施:
- 在文件被创建时,客户端就会对每个文件块进行消息摘录,并写入同一个路径的隐藏文件中
- 文件 下载时 的措施:
- 当客户端读取文件时,会先读取该隐藏文件
- 然后会采用 MD5和 SHA-1校验逐块校验
- 如果校验出错,就会向另一个 DN读取该文件块,并向 NN报告错误
- NN会定期检查并重新复制该块
3.6 HDFS的数据读写过程
FileSystem介绍:
FileSystem
是一个通用文件系统的抽象基类,可以被分布式文件系统继承- Hadoop为其提供了诸多实现,
DistributedFileSystem
就是在 HDFS中的实现 - FileSystem的
open()
方法返回一个输入流FSDataInputStream
,在 HDFS中具体的就是DFSInputStream
- FileSystem的
create()
方法返回一个输出流FSDataOutputStream
,在 HDFS中具体的输出流就是DFSOutputStream
读数据的过程:
-
客户端通过
FileSystem.open()
打开文件- HDFS返回输入流
DFSInputStream
- HDFS返回输入流
-
在
DFSInputStream
的构造函数中,输入流通过ClientProtocal.getBlockLocations()
RPC调用 DN,获取文件开始部分数据块的保存位置;- DN返回保存该数据块的所有数据节点的地址,同时根据距离客户端远近对 DN排序
-
然后
FileSystem
利用DFSInputStream
来实例化FSDataInputStream
并返回给客户端同时返回数据块的 DN地址 -
获取
FSInputStream
之后,客户端调用read()
方法读取数据- 输入流根据前面的排序结果,选择距离客户端最近的 DN建立连接并读取数据
-
数据从该 DN读到客户端,读完后
FSDataInputStream
关闭 -
输入流通过
getBlockLocations()
方法查找下一个数据块 -
找到该数据块最佳 DN,读取数据,读完后再关闭
-
注意:如果在读取过程中,客户端和 DN之间的通信出现错误,就会尝试连接该 DN的下一个 DN
写数据的过程:
-
客户端通过
FileSystem.create()
创建文件- 创建输出流
DFSOutputStream
- 创建输出流
-
然后
FileSystem
通过 RPC远程调用 NN,在文件系统的命名空间中创建一个新的文件- NN会执行一些检查,比如文件是否已经存在,客户端是否有创建的权限
- 检查过后,NN会构造一个新文件,并添加文件信息
-
然后
FileSystem
利用DFSOutputStream
来实例化FSDataOutputStream
,并返回给客户端,客户端使用它来写数据 -
客户端调用输出流的
write()
方法向 HDFS中对应的文件写入数据 -
客户端向
FSDataOutputStream
中写入的数据会被分成一个个分包- 这些包被放入
DFSOutputStream
对象的内部队列 FSDataOutputStream
会向 NN申请保存文件和副本数据块的若干个 DN,这些 DN形成一个数据流管道- 分包最后被打成数据包,发往数据流管道的第一个 DN,第一个 DN将数据包发送给第二个 DN 。。。,这样数据包流经各个 DN
- 这些包被放入
-
为了保证所有 DN的数据都是准确的,接收到数据的 DN需要向发送者发送“ACK包”
- 该“ACK包”沿着管道逆流而上,依次进过各个 DN并最终发往客户端
- 客户端收到应答后,它将对应的分包从内部队列移除
-
客户端调用
close()
方法关闭输出流- 当
DFSOutputStream
对象内部队列的分包都收到应答以后,就可以使用ClientProtocol.complete()
方法通知 NN关闭文件
- 当
第四章、分布式数据库 HBase
HBase是对谷歌 BigTable的实现,是一个高可靠、高性能、面相列、可伸缩的分布式数据库,主要用来存储非结构化和半结构化的松散数据。
4.1 概述
从 BigTable说起:
- BigTable是一个分布式存储系统,利用谷歌提出的 MapReduce来处理海量数据
- 它具有如下特性:
- 支持大规模海量数据
- 分布式并发数据处理效率极高
- 易于扩展且支持动态伸缩
- 适用于廉价设备
- 适合读操作不适合写操作
HBase简介:
-
HBase利用 Hadoop MapReduce来处理 HBase中的海量数据,实现高性能计算
-
HBase利用 ZooKeeper作为协同服务,实现稳定服务和失败恢复
-
HBase利用 HDFS作为高可靠的底层存储,利用廉价集群提供海量数据存储能力
-
Sqoop为 HBase提供了高效、便捷的 从RDB导入数据的功能
-
Pig和 Hive为 HBase提供了高层语言支持
HBase与传统 RDB对比分析:
- 数据类型
- RDB采用关系模型,具有丰富的数据类型和存储方式
- HBase把数据存储为未经解释的字符串,可以把不同格式的数据转化为字符串保存在 HBase中
- 用户需要自己编写程序把字符串解析成不同的数据类型
- 数据操作
- RDB提供了丰富的操作,如CRUD等,可能涉及主外键多表连接
- HBase只有简单的CRUD,通常只采用单表的主键查询
- 存储模式
- RDB是基于行模式存储的,元祖或行会被连续地存储在磁盘页中,读取时需要顺序扫描
- 如果每个元祖只有少量属性的值对查询有用是,就会产生大量的内存和带宽浪费
- HBase是基于列存储的,每个列族都由几个文件保存,不同列族的文件是分离的
- 仅处理可以回答这些查询的列,可以降低 IO开销,支持大量并发用户查询
- 同一个列族的数据会被一起压缩,因为数据相似度高,所以压缩比大
- RDB是基于行模式存储的,元祖或行会被连续地存储在磁盘页中,读取时需要顺序扫描
- 数据索引
- RDB可以针对不同列构建复杂的多个索引
- HBase只有一个索引——行键
- 数据维护
- RDB中更新操作会用最新的值替换旧值,旧值被覆盖后不再存在
- HBase中执行更新操作时,不会删除旧版本的数据,而是生成一个新版本的数据,同时保留旧版本
- 可伸缩性
- RDB很难实现横向扩展,纵向扩展也比较麻烦
- HBase能轻易地通过在集群中增减硬件数量来实现性能的伸缩
- 注意:HBase也有自身的局限性,如不支持事务,无法实现跨行的原子性
4.2 HBase访问接口
HBase提供了 Native Java API,HBase Shell,Thrift Gateway,REST Gateway,Pig,Hive等多种访问方式
类型 | 特点 | 使用场合 |
---|---|---|
Native Java API | 常规和高效的访问方式 | 适合 Hadoop MapReduce作业并行批处理 HBase表数据 |
HBase Shell | HBase的命令行工具,最简单的借口 | 适合 HBase的管理 |
Thrift Gateway | 利用 Thrift序列化技术,支持 C++、PHP、Python等 | 适合其他异构系统在线访问 HBase表数据 |
REST Gateway | 解除语言限制 | 支持 REST风格的 HTTP API访问 HBase |
Pig | 使用 Pig Latin流式编程语言来处理 HBase中的数据 | 适合做数据统计 |
Hive | 简单 | 以类似 SQL的方式访问 HBase |
4.3 HBase数据模型
HBase列族数据模型,包括表、行键、列族、列限定符、单元格、时间戳等概念
数据模型概述:
- 基本概念
- HBase是一个稀疏、多维度、排序的映射表,它的索引包括行键、列族、列限定符和时间戳。
- 每个值都是一个未解释的字符串,没有数据类型
- 用户在表中存储数据时,每一行都有一个可排序的行键和任意多的列
- 表在水平方向由一个或多个列族组成,一个列族可包涵任意多个列,且无需预先定义
- 由于同一张表中,每一行的数据都可以有截然不同的列,因此对于整个映射表而言,有些列的值是空的,所以说 HBase是 稀疏 的
- 版本信息
- 在 HBase中执行更新操作时,并不会删除数据的旧版本,而是生成一个新的版本
- HBase可以对允许保留的版本数量进行设置
- 客户端可以一次获取所有版本,或者获取最近的版本
- 如果在查询时不提供时间戳,就会 返回最新的数据,因为在存储的时候,数据会按照时间戳排序
- HBase提供了两种数据版本回收方式:
- 保存数据的最后 n个版本
- 保存最近一段时间的版本(如最近 7天)
数据模型相关概念:
- HBase实际上就是一个稀疏、多维、持久化存储的映射表,采用行键(Row Key)、列族(Column Family)、列限定符(Column Qualifier)和时间戳(Timestamp)进行索引,每个值都是未经解释的字节数组 byte[]
- 表
- 表由行和列族组成,列族划分为多个列
- 行键
- 每个行由行键(Row Key)标识
- 访问表中的行只有 3种方式:
- 通过单个行键访问
- 通过一个行键的区间来访问
- 全表扫描
- 行键可以是任意字符串,最大长度为 64KB
- 数据按照行键的字典顺序排序,因此设计行键时应将经常一起读取的行存储在一起
- 列族
- HBase表被分组成多个“列族”的集合,它是基本的访问控制单元
- 列族需要在表创建时就定义好,数量不能太多,且不能频繁修改
- 存储在一个列族中的所有数据,通常都属于同一种数据类型,这样能得到较好的数据压缩率
- 列名都已列族作为前缀,如:“hdu:oliq”
- 在 HBase中,访问控制、磁盘和内存的使用统计都是在列族这一层次上进行的
- 比如,我们可以允许一些应用只能向表中添加数据,另一些只能浏览
- 此外列族可以被配置成不同类型的访问模式,可以设置成内存访问或硬盘访问
- 列限定符
- 列族内的数据通过列限定符来定位
- 列限定符不用事先定义,也不需要在不同行之间保持一致
- 单元格
- 通过 行键、列族、列限定符可以确定一个单元格
- 每个单元格中可以保存一个数据的多个版本,每个版本对应一个不同的时间戳
- 时间戳
- 每个单元格都保存着同一份数据的多个版本,这些版本采用时间戳进行索引
- 时间戳一般是 64位整数,可以由用户自己赋值
- 一个单元格的不同版本根据时间戳降序存储,这样最新的版本就可以最先被读取
数据坐标:
- HBase使用坐标来定位表中的数据
- “四维坐标”为:[‘行键’, ‘列族’,‘列限定符’,‘时间戳’]
- 如果把坐标看作键,那么 HBase可以视作键值数据库
概念视图:
- 在 HBase的概念视图中,一个表可以视为一个稀疏、多维的映射关系
- HBase按照行键的字典顺序来排序存储数据,采用反向 URL的方式可以让来自同一个网站数据内容都保存到同一个分区中
物理视图:
- 从概念视图层面,HBase中的每个表是由许多行组成的,但是在物理存储层面,它采用基于列的存储方式
- HBase表中的内容会按照列族进行分别存储,属于同一个列族的数据保存在一起,同时和每个列族一起存放的还包括行键和时间戳
- 如果某些列是空的,即这些列上面不存在值,在物理视图中,它们并不会设置成 null,而是根本不会被存储,当请求这些空白单元格时,会返回 null值
面相列的存储:
- 行式数据库使用行存储模型(N-ary Storage Model, NSM),一个元祖(或行)会被连续地存储在磁盘页中
- 在从磁盘读取数据时,需要从磁盘中顺序扫描整个元祖的完整内容,然后再进行筛选
- 如果每个元祖中只有少量属性的值有用,那么 NSM就会浪费许多磁盘空间 和内存带宽
- 列式数据库采用列存储模型(Decomposition Storage Model,DSM),目的是最小化无用的 IO
- DSM会对关系进行垂直分解,并为每个属性分配一个子关系
- 因此,一个具有 n个属性的关系会被分解成 n个子关系,每个子关系单独存储
- 子关系只有当其相应的属性被请求时才会被访问
- 也就是说,多个元祖的同一属性(或同一列值)会被存储在一起
- 而一个元祖中的不同属性会被分别存放到不同的磁盘页中
- 行式数据库主要适合小批量的数据处理,列式数据库适合批量数据查询和即席查询
- 列式数据库的优点:
- 降低 IO开销
- 支持大量并发用户查询
- 具有较高的数据压缩比
- 列式数据库的缺陷:
- 执行连接操作时需要昂贵的元祖重构代价
- 当需要一个完整的元祖时,需从多个磁盘页中读取相应字段的值来进行整合
4.4 HBase的实现原理
HBase的功能组件、表和 Region、以及 Region的定位
HBase的功能组件:
- 库函数
- 连接到每个客户端
- 一个 Master主服务器
- 管理和维护 HBase表的分区信息
- 记录每个 Region存放在哪台 Region服务器上
- 维护 Region服务器列表
- 当某个 Region服务器宕机时,Master会把该故障服务器上存储的 Region重新分配给其他 Region服务器
- 处理模式裱花,如表和列族的创建
- 许多 Region服务器
- 存储和维护分配给自己的 Region
- 处理来自客户端的读写请求
- 客户端并不是直接从 Master主服务器上读取数据,而是在获得 Region的存储位置信息后,直接从 Region服务器上获取数据
- 客户端并不依赖于 Master而是借助于 ZooKeeper来获得 Region的位置信息
- 所以大多数客户端从来不和 Master主服务器通信,这使得 Master的负载很小
表和 Region:
-
HBase表中包含的行的数量可能很大,无法存储在一台机器上
-
需要根据行键的值对表中的行进行分区
-
每个行区间构成一个分区,成为“Region”
-
Region包含了位于某个值域区间内的所有数据,是负载均衡和数据分发的基本单位
-
这些 Regionhi被分发到不同的 Region服务器上
-
-
初始时,每个表只包含一个 Region,随着数据的不断插入,Region持续增大
-
当一个 Reign中包含的行数达到一个阈值后,会自动分成两个新的 Region
-
-
每个 Region的默认大小是 100~200MB,是 HBase中负载均衡和数据分发的基本单位
-
每个 Region服务器通常放置 10~1000个 Region
-
Master会把不同的 Region分配到不同的 Region服务器上,同一个 Region不会被拆分到多个 Region服务器上
Region的定位:
-
一个 HBase的表可能非常庞大,会被分裂成很多 Region,这些 Region可被分发到不同的 Region服务器上,因此必须设计相应的 Region定位机制
-
每个 Region都有一个 RegionID来标识它的唯一性,这样一个 Region标识符就可以表示成 “表名+开始主键+RegionID”
-
为了定位每个 Region所在的位置,可以构建一张映射表,映射表中的每个条目(或每行)包含两项内容
- 一个是 Region标识符
- 另一个是 Region服务器标识
-
这个映射表包含了关于 Region的元数据(Region和 Region服务器之间的对应关系)
- 因此被称为“元数据表”,又称为“.META.表”
-
当一个 HBase表中的 Region数量非常庞大的时候,.META.表的条目就会非常多,一个服务器保存不下,也需要分区存储到不同的服务器上
- 因此 .META.表也会被分裂成多个 Region,这时为了定位这些 Region,就需要构建一个新的映射表
- 这个新的映射表就是“根数据表”,又称为 “-ROOT-表”
-
-ROOT-表不能被分割,永远只存在一个 Region用于存放 -ROOT-表
-
为了加快访问,.META.表的全部 Region都会被保存在内存中
-
客户端读取顺序:
- 首先访问 ZooKeeper,获取 -ROOT-表的位置信息
- 访问 -ROOT-表,获得 .META.表的信息
- 访问 .META.表,找到所需的 Region具体位于哪个 Region服务器
- 最后才会到该 Region服务器读取数据
-
为了加速寻址过程,一般会在客户端把查询过的位置信息缓存起来,就可以直接从客户端缓存中获取 Region的位置信息
-
但是需要注意的是 Region的信息会发生变化,位置信息失效后需要重新经历“三级寻址”的步骤
4.5 HBase运行机制
HBase系统架构、Region服务器、Store和 HLog
HBase系统架构:
-
HBase的体系架构包括:客户端、ZooKeeper服务器、Master主服务器、Region服务器;HBase一般采用 HDFS作为底层数据存储系统
-
客户端
- 包涵访问 HBase的接口,同时在缓存中维护着已经访问过的 Region位置信息,用来加快后续数据访问过程
- HBase客户端使用 HBase的 RPC机制与 Master和 Region服务器进行通信
- 管理类操作,客户端和 Master进行 RPC
- 数据读写类操作,客户端和 Region服务器进行 RPC
-
ZooKeeper服务器
- 一般 ZooKeeper服务器是由多台机器构成的集群
- 每个 Region服务器都需要到 ZK中进行注册,ZK会试试监控每个 Region服务器的状态并通知 Master
- HBase中可以启动多个 Master,但是 ZK可以帮助选举出一个 Master作为集群的总管,避免了单点故障
- ZK中保存了 -ROOT-表的地址和 Master的地址
- 客户端可以通过访问 ZK获取 -ROOT-表的地址
- 最终通过“三级寻址”找到所需数据
- ZK中还存储了 HBase的模式,包括 HBase有哪些表,哪些列族
-
Master主服务器
- 主要负责表和 Region 的管理工作
- 管理用户对表的增加、删除、修改和查询等工作
- 实现不同 Region服务器之间的负载均衡
- 在Region分裂或合并后,负责重新调整 Reign的分布
- 对发生故障失效的 Region服务器上的 Region进行迁移
- 客户端访问 HBase上的数据时并不需要 Master主服务器的参与,Master上仅维护了表盒 Region的元数据,因此负载很低
- Master维护了当前可用的 Region服务器列表,以及确定哪些 Region分配给哪些 Region服务器
- 主要负责表和 Region 的管理工作
-
Region服务器
- 是 HBase中最核心的模块
- 负责维护分配给自己的 Region
- 响应用户的读写请求
- Region服务器需要向 HDFS中读写数据
- HBase本身不具备数据复制和副本维护的功能,但是借助 HDFS可以实现
- 是 HBase中最核心的模块
Region服务器工作原理:
-
Region服务器内部管理了一系列 Region对象和一个 HLog文件
- 每个 Region对象有多个 Store组成,每个 Store对应表中的一个列族的存储。
- 每个 Store又包含一个 MemStore和若干个 StoreFile
- MemStore是在内存中的缓存,保存最近更新的数据
- StoreFile是磁盘中的文件,都是 B树结构的
- StoreFile通过 HDFS的 HFile实现,通常采用压缩方式存储
- HLog是磁盘上面的记录文件,记录着所有的更新操作
- 每个 Region对象有多个 Store组成,每个 Store对应表中的一个列族的存储。
-
用户读写数据的过程
- 写入数据时,分配到相应的 Region服务器去执行操作
- 用户数据首先被写入 MemStore和 HLog中
- 当操作写入 HLog后,
commit()
调用才会将其返回给客户端
- 读取数据时,Region服务器会首先访问 MemStore缓存,如果不在缓存中,就是去 StoreFile中寻找
- 写入数据时,分配到相应的 Region服务器去执行操作
-
缓存的刷新
- MemStore的容量有限
- 系统会周期性地调用
Region.flushcache()
把 MemStore缓存里的内容写到 StoreFile中 - 然后清空缓存,并在 HLog文件中写入一个标记,用来表示缓存中的内容已经被写入 StoreFile中了
- 系统会周期性地调用
- 每次刷新都uhi在磁盘上生成一个新的 StoreFile文件,因此每个 Store会包含多个 StoreFile文件
- 每个 Region服务器都有一个自己的 HLog文件
- 启动的时候,会查看自己的 HLog文件
- 确认最近一次执行缓存刷新操作之后是否发生新的写入操作
- 如果没有,说明所有数据都已经永久被保存到磁盘的 StoreFile中了
- 如果有,就先把这些数据写入 MemStore,然后刷新缓存写入 StoreFile
- 最后,删除旧的 HLog,并开始提供数据访问服务
- MemStore的容量有限
-
StoreFile的合并
-
每次 MemStore缓存的刷新操作都会在磁盘上生成一个新的 StoreFile
- 这样系统中就会出现很多个 StoreFile
- 当需要访问某个 Store中的值时,需要查找所有的 StoreFile,非常耗时
-
为了减少查找时间,系统会调用
Store.compact()
把多个 StoreFile文件合并成一个大文件- 由于合并操作非常耗资源,所以一般只在 StoreFile的数量达到阈值后进行
-
Store的工作原理:
- Region服务器是 HBase的核心,Store是 Region服务器的核心
- 每个 Store对应一个列族的存储
- 每个 Store包含一个 MemStore缓存和若干个 StoreFile文件
- MemStore是排序的内部缓冲区
- 当用户写入数据时,系统首先把数据放入 MemStore中
- MemStore满了之后,就会刷新到磁盘中的一个 StoreFile中
- 随着 StoreFile的不断增加,会触发文件 合并 操作,多个 StoreFile会被合并成一个大的 StoreFile文件
- 当单个 StoreFile文件大小超过一定阈值时,就会触发文件 分裂 操作,同时会触发 Region的分裂
- 父 Region分裂成两个子 Region
- 父 Region下线,子 Region被分配到 Region服务器上
HLog的工作原理:
- HBase为每个 Region服务器配置了一个 HLog文件,它是一种预写日志(Write-Ahead Log)
- 用户更新数据必须首先被记录到日志才能写入 MemStore缓存,
- 并直到 MemStore缓存内容对应的日志已经被写入磁盘后,该缓存内容才会被刷新写入磁盘
- ZK实时监测每个 Region服务器的状态,当某个 Region服务器发生故障时,ZK通知 Master
- Master会处理该 Region服务器上遗留的 HLog文件
- 该 HLog文件中包含了来自多个 Region对象的日志记录
- 系统根据每条日志记录所属的 Region对象对 HLog数据进行拆分,分别放到相应 Region对象的目录下
- 然后将失效的 Region重新分配到可用的 Region服务器中,随带该 Region相关的 HLog
- Region服务器领取到 Region后,会重新做一遍日志记录中的各种操作,将数据写入 MemStore,再刷写到 StoreFile中
- 注意:因为一个 Region服务器只有一个 HLog,但又有多个 Region存储,所以恢复的时候需要进行日志文件的拆分
第五章、NoSQL数据库
在大数据时代,数据类型繁多,包括结构化数据和非结构化数据,传统的 RDB力不从心
5.1 NoSQL简介
NoSQL是一种不同于 RDB的数据库管理系统设计方式,是对非 RDB的统称;NoSQL没有固定的表结构,通常也不存在连接操作,也没有严格的 ACID约束
NoSQL的特点:
- 灵活的可扩展性
- RDB很难实现“横向扩展”,当数据库负载大规模增加时,需要通过升级硬件来“纵向扩展”
- NoSQL在设计之初就是为了满足“横向扩展”的需求
- 灵活的数据模型
- 关系数据模型是关系数据库的基石,以 ACID为基础,保证了业务系统对数据一致性的要求
- NoSQL天生就旨在摆脱关系数据库的各种束缚,采用键值、列族等非关系模型存储数据
- 与云计算紧密融合
- 云计算具有很好的水平扩展能力,可以根据资源使用情况自由伸缩
5.2 NoSQL兴起的原因
尽管 RDB的事务和查询机制较好地满足了业务数据管理需求,但是现已力不从心
兴起的原因:
- RDB无法满足 Web2.0的需求
- 无法满足海量数据的管理需求
- 无法满足数据高并发的需求
- 无法满足高可扩展性和高可用性的需求
- ACID成为鸡肋
- Web2.0网站通常不要求严格的数据库事务
- Web2.0并要求严格的读写实时性
- Web2.0通常不包含大量复杂的 SQL查询
5.3 NoSQL与关系数据库的比较
对比指标 | NoSQL | RDB |
---|---|---|
数据库原理 | 部分支持 | 完全支持 |
数据规模 | 超大 | 大 |
数据库模式 | 灵活 | 固定 |
查询效率 | 高效的简单查询 低效的复杂查询 无法进行高度结构化的查询 |
快 |
一致性 | 弱一致性 | 强一致性 |
数据完整性 | 很难实现 | 容易实现 |
扩展性 | 好 | 一般 |
可用性 | 很好 | 好 |
标准化 | 否 | 是 |
技术支持 | 低 | 高 |
可维护 | 复杂 | 复杂 |
5.4 NoSQL的四大类型
键值数据库:
- 使用一个哈希表进行存储,有一个特定的 Key和 Value,Key用来定位 Value
- Value对数据库而言是透明不可见的,不能通过 Value进行索引和查询,只能通过 Key进行查询
- Value可以用来存储任意数据类型
- 可划分为:内存键值数据库和 持久化键值数据库
- 优点:
- 在大量写操作下,相对 RDB有更好的性能,因为 RDB需要对写入的数据建立索引
- 索引的频繁更新,导致维护代价高昂
- 具有良好的伸缩性,理论上可以实现无限扩容
- 在大量写操作下,相对 RDB有更好的性能,因为 RDB需要对写入的数据建立索引
- 缺点:
- 难以进行条件查询
- 只对部分值进行查询和更新的操作效率低下
- 无法多表关联查询
- 不支持事务,无法回滚
- 需采用双向冗余存储替代表关联,将关联查询替换为单表查询
列族数据库:
- 采用列族数据模型,数据库由多行构成
- 每行数据包含多个列族,不同的行可以具有不同的列族,统一列族的数据统一存放
- 每行数据通过行键进行定位
文档数据库:
- 文档是最小的单位,由某种标准化格式封装并加密
- 一般通过一个键来定位一个文档,但其查询效率高于键值数据库
- 文档数据库可以根据键构建索引,也可以根据文档内容构建索引
图数据库:
- 以图论为基础,用来表示一个对象的集合
- 使用图作为数据模型存储数据
- 可以高效存储不同顶点之间的关系
- 专门用于处理具有高度相互关联关系的数据
5.5 NoSQL的三大基石
CAP、BASE和最终一致性
CAP:
- C(Consistency):一致性
- 一个读操作总是能够读到之前完成的写操作的结果
- A(Availability):可用性
- 快速获取数据,且在确定的时间内返回操作结果
- P(Tolerance of Network Partition):分区容忍性
- 在当前网络分区的情况下,分离的系统也能够正常运行
- CAP理论告诉我们,一个分布式系统不可能同时满足 C、A、P这 3个特性,最多只能同时满足其中的 2个
- 当处理 CAP的问题时,可以有以下几个选择:
- CA,强调一致性和可用性,如 RDB
- CP,强调一致性和分区容忍性,如 HBase
- AP,强调可用性和分区容忍性,如 Cassandra
BASE:
- BASE的基本含义是 基本可用(Basically Available)、软状态(Soft-state)、最终一致性(Eventual consistency)
- 基本可用
- 部分系统宕机后,其他系统仍能可用
- 软状态
- 状态可以有一段时间不同步,具有一定的滞后
- 最终一致性
- 允许后续的访问操作可以暂时读不到更新后的数据
- 但是经过一段时间后,用户最终必须能够读到
最终一致性:
- 从服务端看,一致性是指更新如何分布到整个系统
- 从客户端看,一致性指后续的操作能否获取最新的数据
- 最终一致性根据更新数据后各进程访问到数据的时间和方式的不同,可以进行如下区分:
- 因果一致性
- 如果 A通知了 B,它已经更新了一个数据,那么 B一定能获取到新的值
- 但是针对未受到通知的进程,可以获取旧值
- “读己所写”一致性
- 自己总是能访问到更新过的值,绝不会看到旧值
- 会话一致性
- 将访问存储系统的进程放到会话的上下文中
- 只要会话存在,系统就保证“读己所写”一致性
- 单调读一致性
- 如果进程已经看到过数据对象的某个值,那么任何后续访问都不会返回前面的值
- 单调写一致性
- 系统保证来自同一个进程的写操作顺序
- 因果一致性
第七章、MapReduce
大数据时代除了需要解决大规模数据的高效存储问题,还需要解决大规模数据的高效处理问题。
分布式并行编程可以大幅度提高程序性能,实现高效的批量数据处理
MapReduce是一种并行编程模型,用于大规模数据集的并行运算,将复杂的、运行于大规模集群上的并行计算过程高度抽象为两个函数:Map和 Reduce
7.1 概述
分布式编程:
- 从 2005年开始摩尔定律逐渐失效,CPU性能提升速度放缓,人们开始借助于分布式并行编程来提高程序性能
- 传统的程序以单指令、单数据流的方式顺序执行,受到单台服务器的限制;分布式并行程序可以运行在由大量计算机构成的集群上
- Hadoop MapReduce是谷歌的 MapReduce的开源实现,运行在 HDFS上
MapReduce模型简介:
- MapReduce将复杂的、运行于大规模集群上的并行计算过程高度地抽象为两个函数:Map和 Reduce
- 在 MapReduce中,一个存储在 HDFS的大规模数据集会被切分成许多独立的 小数据集,被多个 Map任务并行处理
- Map任务生成的结果会继续作为 Reduce任务的输入,最终由 Reduce任务输出最后的结果,并写入 HDFS中
- 核心理念为“计算向数据靠拢”,因为数据的传输需要耗费大量的网络开销
- 只要有可能,MapReduce框架就会将 Map程序就近地在 HDFS数据所在的节点运行
Map和 Reduce函数:
-
程序员只需要关注如何实现 Map和 Reduce函数,而不需要处理并行编程中的其他问题
-
Map和 Reduce都是以 <Key, Value>作为输入,按一定的映射规则将其转换成另一个或一批 <Key, Value>进行输出
-
函数 输入 输出 说明 Map <K1, V1> List(<k2, V2>) 1. 将小数据集进一步解析成一批 <K, V>对,输入 Map函数
2. 每个输入的 <K1, V1>会输出一批 <K2, V2>,它是计算的中间结果Reduce <K2, list(V2)> <K3, V3> 输入的中间结果 <K2, list(V2)>中的 list(V2)表示一批同属于一个 K2的 Value -
Map函数的输入来自 HDFS中的文件块,格式任意;但是同一个元素不能跨文件块存储
-
Map函数将输入的元素转化为 <K, V>键值对,键和值的类型也是任意的,键没有唯一性;即使是一个输入,也可以产生多个输出
-
Reduce函数会将输入的一系列具有相同键的键值对集合以某种方式组合起来,输出处理后的键值对,输出结果会合并成一个文件
-
用户可以指定 Reduce任务的个数,Main进程通常会选择一个 Hash函数,针对键进行哈希运算
7.2 MapReduce的工作流程
MapReduce的各个执行阶段、Shuffle
工作流程概述:
-
MapReduce是核心思想可以用“分而治之”来描述
- 一个大的 MR任务,会被拆分成多个 Map任务在多台机器上并行处理
- 每个 Map任务通常会运行在数据存储的节点上,这样计算和数据可以放在一起,不需要额外的数据传输开销
-
当 Map任务结束后,会生成以 <Key, Value>形式的许多中间结果,然后分发到多个 Reduce任务在多台机器上并行执行
- 具有相同 Key的 <Key, Value>会被发送到同一个 Reduce任务
- Reduce任务会对中间结果进行汇总计算,并输出到 HDFS
-
注意:不同的 Map任务之间不会进行通信,不同的 Reduce任务之间也不会发生信息交换;用户不能显式地从一台机器向另一台机器发送信息
-
在整个 MR过程中,Map任务的输入文件,Reduce任务的输出文件都是保存在 HDFS中的,而中间结果则保存在服务器本地磁盘
-
只有当 Map任务全部结束后,才会开始 Reduce任务
-
只用 Map任务才需要考虑数据局部性,实现“计算向数据靠拢”
MapReduce的各个执行阶段:
-
MR框架使用 InputFormat模块做 Map前的预处理
- 将输入文件切分为逻辑上的多个 InputSplit
- 每个 InputSplit记录了要处理的数据的位置和长度
-
通过 RecordReader根据 InputSplit中的信息处理 InputSplit中的具体记录
- 加载数据并将其转换为适合 Map任务读取的键值对并输入给 Map任务
-
Map任务处理
-
对 Map的输出结果进行一定的 分区、排序、合并、归并操作
- 得到 <K, list(V)>形式的中间结果,交给 Reduce来处理,这个过程称为 Shuffle
-
Reduce任务处理
-
OutputFormat模块进行输出
Shuffle简介:
-
Shuffle是指对 Map任务输出结果进行分区、排序、合并、归并等处理,并交给 Reduce的过程
- 因此,Shuffle过程分为 Map端操作和 Reduce端操作
-
在 Map端的 Shuffle
- Map任务的输出结果首先被写入缓存中
- 缓存满了后,启动溢写操作,把缓存中的数据写入磁盘文件
- 随着 Map任务的执行,磁盘中会生成多个溢写文件
- 在 Map任务全部结束之前,这些溢写文件会归并成一个大文件
- 然后通知相应的 Reduce任务来“领取”自己的处理数据
-
在Reduce端的 Shuffle
- Reduce任务在 Map端的不同 Map机器上“领取”属于自己的那部分数据
- 对数据进行归并后交给 Reduce进行处理
Map端的 Shuffle过程:
-
输入数据和执行 Map任务
- 从 HDFS的文件块中获取文件内容
- Map任务接收 <K, V>作为输入后,按一定的映射规则输出多个 <K, V>
-
写入缓存
- 每个 Map任务都会被分配一个缓存文件
- Map任务的输出先写入缓存
- 当缓存中堆积了一定数量的 Map输出后,再一次性写入磁盘,能减少 IO
-
溢写
- 提供给 MR的缓存容量是有限的,默认为 100M
- 当缓存占满后,需要进行溢写操作(Spill),将缓存中的内容一次性写入磁盘,并清空缓存
- 溢写的过程通常是由另外一个单独的后台线程来完成的,不影响 Map结果向缓存内的写入
- 通常溢写的比例为 0.8,即当缓存中有 80M的数据时,就会发生溢写,剩余 20M的空间供 Map结果继续写入
- 在进行溢写前,缓存中的数据会进行分区,MR通过 Partitioner接口对 <K, V>键值对进行分区
- 默认的分区策略是先采用 Hash函数对 Key进行哈希,再对 Reduce任务的数量进行取模
- 对于每个分区内的所有键值对,后台线程会根据 Key进行内存排序
- 如果事先定义了 Combiner函数,还可以在排序后进行合并操作,减少溢写到磁盘的数据量
- “合并”是指将那些具有相同 key的 <K, V>的 value加起来,类似 Reduce
- 但是这个操作发生在 Map阶段,所以称为 合并
- Combiner的输出是 Reduce任务的输入,Combiner绝不能改变 Reduce任务最终的计算结果
- 每次溢写操作都会在磁盘中生成一个新的溢写文件
- 写入溢写文件的所有键值对都是进过分区和排序的
-
文件归并
- 每次溢写操作都会生成一个新的溢写文件
- 随着 MR的进行,溢写文件越来越多
- 在 Map任务结束前,会对所有溢写文件进行归并,生成一个大的溢写文件
- 这个大的溢写文件也是进过分区和排序的
- “归并”指:<k1, v1>, <k1, v2>, <k1, v3>, <k1, v4>归并成 <k1, <v1, v2, v3, v4>>的结果
- 当进行归并操作时,如果磁盘中已经生成的溢写文件数量超过
min.num.spills.for.combie
,就可以再次运行 Combiner进行合并
- 每次溢写操作都会生成一个新的溢写文件
-
最终生成一个被存放在本地磁盘上的大文件
- 大文件中的数据是分区的
- 不同的分区会被发送到不同的 Reduce任务进行并行处理
- JobTracker会一直监测 Map任务的执行
Reduce端的 Shuffle过程:
- “领取”数据
- Map任务完成后,Reduce任务把数据“领取”(Fetch)到本地
- 每个 Reduce任务会不断地通过 RPC向 JobTracker询问 Map任务是否已完成
- 归并数据
- 从 Map端“领取”的数据会被存放在 Reduce任务所在机器的缓存中
- 如果缓存被占满,也会被溢写到磁盘中
- 由于在 Shuffle阶段,Reduce任务还未开始,所以可以把大部分空间都分配给 Shuffle过程作为缓存
- 注意:系统中一般会存在多台 Map机器,Reduce任务会从多个 Map机器“领取”属于自己的那些分区的数据
- 缓存中的数据是来自不同的 Map机器的,一般会存在很多可以合并的键值对
- 当溢写过程启动时,具有相同 key的键值对会被归并
- 如果用户定义了 Combiner,则归并后的数据会进行合并,减少 IO
- 溢写的最后,也会把所有的溢写文件合并成一个大文件
- 归并的时候,会对键值对进行排序
- 把多个溢写文件归并成一个大文件可能需要执行多轮归并操作
- 每轮归并操作可以归并的文件数量由参数
io.sort.factor
控制
- 每轮归并操作可以归并的文件数量由参数
- 从 Map端“领取”的数据会被存放在 Reduce任务所在机器的缓存中
- 把数据输入给 Reduce任务
- 磁盘中经过多轮归并后得到的若干个大文件,不会继续归并成一个新的大文件,而是直接输入 Reduce任务
第八章、Hadoop再探讨
Hadoop的优化与发展主要体现在两个方面:一方面是 Hadoop自身两大主键 MR和 HDFS架构改进;另一方面是 Hadoop其他组件的丰富
8.1 Hadoop的优化与发展
Hadoop 1.0的局限与不足:
- 抽象层次低
- 表达能力有限
- 开发者自己管理作业之间的依赖关系
- 难以看到程序整体逻辑
- 执行迭代操作效率低
- 资源浪费
- 实时性差
针对 Hadoop的改进与提升:
- 设计了 HDFS HA,提供名称节点热备份机制
- 设计了 HDFS联邦,管理多个命名空间
- 设计了新的资源管理框架 YARN
8.2 HDFS 2.0的新特性:
HDFS HA:
- 在 HDFS中,NN是系统的核心节点,存储了各类元数据
- 在 HDFS 1.0中,只存在一个 NN,容易发送单点故障;虽然有 2NN,但它并不是适合的备用节点
- HDFS 2.0中,提供了高可用(HA)架构
- 在一个典型的 HA集群中,一般设置两个 NN,一个处于活跃状态,另一个处于待命状态
- Active状态的 NN中的数据必须实时同步到 Standby状态的 NN
- 可以借助网络文件系统、仲裁日志管理器或 ZK
- 需要给 DN配置两个 NN的地址信息
HDFS联邦:
- HDFS 1.0中单个 NN的设计还存在可扩展性、系统整体性和隔离性等方面的问题
- 整个 HDFS的性能受限于 NN的吞吐量
- HDFS联邦设计了多个互相独立的 NN,使得 HDFS的命名服务可以进行横向扩展
- 这些 NN分别管理各自的命名空间和映射
- HDFS联邦并不是真正的分布式设计,而是“联合”的设计方式
- 所有的 NN共享底层的 DN资源
- 属于同一个命名空间的块构成一个“块池”,每个 DN会为多个块池进行存储
- 块池是一个逻辑结构
- HDFS联邦采用客户端挂载表的形式进行数据共享和访问
8.3 新一代资源管理调度框架 YARN
MapReduce 1.0的缺陷:
-
MR 1.0采用 Master/Slave架构设计,包括一个 JobTracker和 若干个 TaskTracker
- JobTracker负责作业的调度和资源的管理
- TaskTracker负责执行 JT指派的具体任务
-
存在的问题:
- 存在单点故障,只有一个 JT
- JT任务过重
- 容易出现内存溢出
- 资源划分不合理
YARN的设计思路:
-
基本思路就是“放权”,不让一个 JT承担过多的功能
- 对原 JT的三大功能(资源调度、任务调度和任务监控)进行拆分
-
重新设计后的 YARN包括 ResourceManager、ApplicationManager和 NodeManager
- RM负责资源管理
- AM负责任务调度和监控
- NM负责执行原 TaskTracker的任务
-
这种放权的设计,大大降低了 JobTracker的负担,提升了系统的运行效率和稳定性
YARN的体系结构:
- ResourceManager
- 处理客户端请求
- 启动/监控 ApplicationMaster
- 监控 NodeManager
- 资源分配与调度
- ApplicationMaster
- 为应用程序申请资源,并分配给内部任务
- 任务调度、监控与容错
- NodeManager
- 单个节点上的资源管理
- 处理来自 ResourceManager的命令
- 处理来自 ApplicationMaster
- RM负责整个系统的资源管理和分配,主要包括两个组件:资源调度器(Resource Scheduler)和 应用程序管理器(Application Manager)
- 资源调度器 主要负责 资源管理和 分配
- 它接收来自 ApplicationMaster的应用程序资源请求
- 根据容量、队列等限制条件,把集群中的资源以“容器”的形式分配给提出申请的应用程序
- 调度器是一个可插拔的组件,YARN不仅自己提供了许多种直接可用的调度器,也允许用户自定义
- 在 MR 1.0中,资源分配的单位是“槽”,在 YARN中是以容器作为动态资源分配单位
- 应用程序管理器 负责系统中所有应用程序的管理工作
- 处理应用程序提交
- 与资源调度器协商资源以启动 ApplicationMaster
- 监控 ApplicationMaster运行状态并在失败时重新启动
- RM接收用户提交的 MR作业,按照作业的上下文信息以及从 NodeManager收集来的容器信息,启动调度过程,为用户作业启动一个 ApplicationMaster
- 资源调度器 主要负责 资源管理和 分配
- ApplicationMaster的主要功能:
- 当用户作业提交时,ApplicationMaster与 ResourceManager协商获取资源,资源以“容器”的形式获取
- 把获得的资源进一步分配给内部的各个任务,实现资源的“二次分配”
- 与 NodeManager保持交互通信,进行应用程序的启动、运行、监控和停止
- 定时向 ResourceManager发送“心跳”
- 作业完成后,ApplicationMaster向 ResourceManager注销容器
- NodeManager是驻留在一个 YARN集群中的每个节点上的代理
- 负责容器生命周期管理
- 监控每个容器的资源使用情况
- 跟踪节点健康情况
- 以“心跳”的方式与 ResourceManager保持通信
- 向 ResourceManager回报资源的使用情况和每个容器的运行状态
- 接收来自 ApplicationMaster的启动/停止容器的各种请求
- YARN的 RM组价和 HDFS的 NN组件部署在一起,YARN的 AM、NM组件和 HDFS的 DN组件部署在一起,容器也和 DN部署在一起
YARN工作流程:
- 用户编写客户端应用程序,向 YARN提交应用程序,包括 AM程序、启动 AM命令、用户程序
- YARN中的 RM负责接收和处理来自客户端的请求
- 接到客户端应用程序请求后,RM里的调度器为程序分配一个容器
- RM的 Application Manager与该容器的 NM进行通信,为该容器启动一个 Application Master
- AM被创建后首先向 RM注册,使得用户可以通过 RM查看应用程序的运行状态
- AM采用轮询的方式通过 RPC协议向 RM申请资源
- RM以“容器”的形式向提出申请的 AM分配资源,一旦 AM申请到了资源,就会与该容器所在的 NM进行通信,要求其启动任务
- 当 AM要求容器启动任务时,它会为任务设置好运行环境,将任务启动命令写入脚本,在容器中执行脚本
- 各个任务通过某个 RPC协议向 AM汇报自己的状态和进程,让 AM可以随时掌握各个任务的运行状态
- 应用程序完成后,AM向 RM注销并关闭自己,如果 AM宕机,RM会检测到失败情形,然后将其重新启动,直到所有的任务执行完毕
YARN框架与 MR 1.0对比:
- 客户端没有发生变化,大部分 API都保持兼容
- MR 1.0中的 JobTracker和 TaskTracker,变成了 YARN中的 RM、AM和 NM
- YARN的优势:
- 大大减少了承担中心服务功能的 RM的资源消耗
- JobTracker同时承担资源管理、任务调度、任务监控
- RM只负责资源调度,其他由 AM完成,如果有多个作业,就起多个 AM
- MR 1.0既是一个计算框架,又是一个资源管理调度框架;YARN是一个纯粹的资源管理框架,在它上面可以运行包括 MR在内的许多编程模型
- YARN中的资源管理更加高效,以容器为单位可以避免资源浪费
- 大大减少了承担中心服务功能的 RM的资源消耗
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!