大数据技术原理与应用 期末复习 知识点全总结(林子雨版

发布时间:2024年01月13日

目录

1.第一章 大数据概述:

(一)三次信息化浪潮

信息化浪潮发生时间标志解决的问题代表企业
第一次浪潮1980年前后个人计算机信息处理Intel、AMD、IBM、苹果、微软、联想、戴尔、惠普等
第二次浪潮1995年前后互联网信息传输雅虎、谷歌、阿里巴巴、百度、腾讯等
第三次浪潮2010年前后物联网、云计算和大数据信息爆炸亚马逊、谷歌、IBM、VMWare、Palantir、Hortonworks、Cloudera、阿里云等

(二)人类社会数据产生方式的3个阶段

运营式系统阶段用户原创内容阶段感知式系统阶段
a.数据库的出现使数据管理的复杂度大大降低,数据往往伴随着一定的运营活动而产生并记录在数据库中,数据的产生方式是被动的a.数据爆发产生于Web2.0时代,而Wed2.0时代的最重要标志就是用户原创内容 b.智能手机等移动设备加速内容产生c.数据产生方式是主动的a.感知式系统的广泛使用b.人类社会数据量第三次大的飞升最终导致了大数据的产生

(三)大数据的3个发展阶段

  1. 第一阶段:萌芽期
    时间:20世纪90年代至21世纪初
    内容:随着数据挖掘理论和数据库技术的逐步成熟,一批商业智能工具和知识管理技术开始被应用,如数据仓库、专家系统、知识管理系统等
  2. 第二阶段:成熟期
    时间:21世纪前10年
    内容:Web2.0应用迅猛发展,非结构化数据大量产生,传统处理方法难以应对,带动了大数据技术的快速突破,大数据解决方案逐渐走向成熟,形成了并行计算与分布式系统两大核心技术,谷歌的GFS和MapReduce等大数据技术受到追捧,Hadoop平台开始大行其道
  3. 第三阶段:大规模应用期
    时间:2010年以后
    内容:大数据应用渗透各行各业,数据驱动决策,信息社会智能化程度大幅度提高

(四)大数据4V概念

①数据量大 ②数据类型繁多 ③处理速度快 ④价值密度低

(五)数据存储单位之间的换算关系

单位换算关系
Byte1 Byte = 8 bit
KB1 KB = 1024 Byte
MB1 MB = 1024 KB
GB1 GB = 1024 MB
TB1 TB = 1024 GB
PB1 PB = 1024 TB
EB1 EB = 1024 PB
ZB1 ZB = 1024 EB

(六)大数据对科学研究的影响

1.第一种范式:实验科学
2.第二种范式:理论科学
3.第三种范式:计算科学
4.第四种范式:数据密集型科学

(七)大数据对思维方式的影响

1.全样而非抽样
2.效率而非精准
3.相关而非因果

(八)大数据技术的不同层面及其功能

1.数据采集与预处理层面
功能:利用ETL工具将分布的、异构数据源中的数据,如关系数据、平面数据文件等,抽取到临时中间层后进行清洗、转换、集成,最后加载到数据仓库或数据集市中,成为联机分析处理、数据挖掘的基础;也可以利用日志采集工具(如Flume、Kafka 等)把实时采集的数据作流计算系统的输入,进行实时处理分析
0
2.数据存储和管理层面
功能:利用分布式文件系统、数据仓库、关系数据库、NoSQL 数据库、云数据库等,实现对结构化、半结构化和非结构化海量数据的存储和管理

3.数据处理与分析层面
功能:利用分布或并行编程模型和计算框架,结合机器学习和数据挖掘算法,实现对海量数据的处理和分析;对分析结果进行可视化呈现,帮助人们更好地理解数据、分析数据

4.数据安全和隐私保护层面
功能:在从大数据中挖掘潜在的巨大商业价值和学术价值的同时,构建隐私数据保护体系和数据安全体系,有效保护个人隐私和数据安全

(九)大数据计算模式及其代表产品

在这里插入图片描述

(十)大数据产业的6个层次

①IT基础设施层 ②数据源层 ③数据管理层 ④数据分析层 ⑤数据平台层 ⑥数据应用层

(十一)大数据与云计算、物联网

1.云计算3种典型服务模型:
①IaaS(基础设施即服务) ②PaaS(平台即服务) ③SaaS(软件即服务)
2.云计算3种方式:
①公有云 ②私有云 ③混合云
3.云计算的关键技术
①虚拟化 ②分布式存储 ③分布式计算 ④多租户

(十二)物联网体系架构

在这里插入图片描述

(十三)大数据与云计算、物联网的关系

在这里插入图片描述

第二章 大数据处理架构Hadoop

(一)Hadoop的特性

高可靠性
高效性
高可扩展性
高容错性
成本低
运行在 Linux 平台上
支持多种编程语言

(二)Hadoop两个版本区别

Apache Hadoop版本分为两代,第一代 Hadoop 称为Hadoop 1.0,第二代 Hadoop 称为Hadoop2.0。第一代 Hadoop 包含 0.20.x、0.21.x和0.22.x三大版本,其中,0.20.x 最后演化成1.0.x,变成了稳定版,而0.21.x 和0.22.x则增加了HDFS HA 等重要的新特性。第二代 Hadoop 包含 0.23.x和2.x两大版本,它们完全不同于 Hadoop 1.0,是一套全新的架构,均包含 HDFS Federation 和YARN(Yet Another Resource Negotiator)两个系统。

(三)Hadoop 生态系统

在这里插入图片描述

第三章 分布式文件系统HDFS

3.1 分布式文件系统

3.1.2 分布式文件系统的结构

1、分布式文件系统在物理结构上是由计算机集群中的多个节点构成。一类叫“主节点”,或者也被称为“名称节点”(NameNode);另一类叫“从节点”,或者也被称为“数据节点”(DataNode)。名称节点负责文件和目录的创建、删除和重命名等,同时管理着数据节点和文件块的映射关系,因此客户端只有访问名称节点才能找到请求的文件块所在的位置,进而到相应位置读取所需文件块。数据节点负责数据的存储和读取,在存储时,由名称节点分配存储位置,然后由客户端把数据直接写人相应数据节点;在读取时,客户端从名称节点获得数据节点和文件块的映射关系,然后就可以到相应位置访问文件块。数据节点也要根据名称节点的命令创建、删除数据块和冗余复制。

3.2 HDFS简介

1、HDFS要实现的目标:
(1)兼容廉价的硬件设备
(2)流数据读写
(3)大数据集
(4)简单的文件模型
(5)强大的跨平台兼容性
(6)不适合低延迟数据访问
(7)无法高效存储大量小文件
(8)不支持多用户写入及任意修改文件

3.3 HDFS的相关概念

3.3.1 块

1、默认块的大小:64MB
2、HDFS采用抽象的块概念的好处:
(1)支持大规模文件存储
(2)简化系统设计
(3)适合数据备份

3.3.2 名称节点和数据节点

1、名称节点负责管理分布式文件系统的命名空间,保存了两个核心的数据结构,即FsImage和EditLog
2、数据节点是分布式文件系统HDFS的工作节点,负责数据的存储和读取,会根据客户端或者名称节点的调度来进行数据的存储和检索,并向名称节点定期发送自己所存储的块的列表。

3.3.3 第二名称节点

1、两方面功能:
(1)可以完成EditLog与FsImage的合并操作,减少EditLog文件的大小,缩短名称节点的重启时间
(2)可以作为名称节点的“检查点”,保持名称节点中的元数据信息

3.4 HDFS体系结构

3.4.1 概述

HDFS采用的是主从(Master/Slave)结构模型,一个HDFS集群包括一个名称节点和若干个数据节点。(

3.4.5 HDFS体系结构的局限性

局限性:(1)命名空间的限制;(2)性能的瓶颈;(3)隔离问题;(4)集群的可用性;

3.5 HDFS的存储原理

3.5.1 数据的冗余存储

HDFS的存储方式:多副本方式对数据进行冗余存储,默认的冗余复制因子是3。

3.5.3 数据错误与恢复

3种错误情形出现会有相应的机制检测数据错误和进行自动恢复:
(1)名称节点出错;(2)数据节点出错;(3)数据出错

3.6 HDFS的数据读写过程

3.6.1 读数据的过程

P53 图3-8
在这里插入图片描述

3.6.2 写数据的过程

在这里插入图片描述

第四章 分布式数据库HBase

4.1概述

(一)BigTable具备以下特性:

支持大规模海量数据、分布式并发数据处理效率极高、易于扩展且支持动态伸缩、适用于廉价设备、适用于读操作不适合写操作。

(二)HBase和BigTable的底层技术对应关系(表4-1)

项目文件存储系统海量数据处理协同服务管理
BigTableGFSMapReduceChubby
HBaseHDFSHadoopMapReduceZooKeeper

(三)HBase与传统数据库的对比分析

HBase与传统数据库的区别主要体现在以下几个方面:
①数据类型:关系数据库采用关系模型,具有丰富的数据类型和存储方式。HBase则采用了更加简单的数据模型,它把数据存储为未经解释的字符串,用户可以把不同格式的结构化数据和非结构化数据都序列化成字符串保存到HBase中,用户需要自己编写程序把字符申解析成不同的数据类型。
②数据操作。关系数据库中包含了丰富的操作,如插入、删除、更新、查询等,其中会涉及复杂的多表连接,通常是借助于多个表之间的主外键关联来实现的。HBase操作则不存在复杂的表与表之间的关系,只有简单的插入、查询、删除、清空等,因为HBase在设计上就避免了复杂的表与表之间的关系,通常只采用单表的主键查询,所以它无法实现像关系数据库中那样的表与表之间的连接操作。
③存储模式。关系数据是基于行模式存储的,元组或行会被连续地存储在磁盘页中。在读取数据时,需要顺序扫描每个元组,然后从中筛选出查询所需要的属性。如果每个元组只有少量属性的值对于查询是有用的,那么基于行模式存储就会浪费许多磁盘空间和内存带宽。HBase是基于列存储的,每个列族都由几个文件保存,不同列族的文件是分离的,它的优点是:可以降低 I/O开销,支持大量并发用户查询,因为仅需要处理可以回答这些查询的列,而不需要处理与查询无关的大量数据行;同一个列族中的数据会被一起进行压缩,由于同一列族内的数据相似度较高,因此可以获得较高的数据压缩比。
④数据索引。关系数据库通常可以针对不同列构建复杂的多个索引,以提高数据访问性能。与关系数据库不同的是,HBase只有一个索引–行键,通过巧妙的设计,HBase 中的所有访问方法,或者通过行键访问,或者通过行键扫描,从而使得整个系统不会慢下来。由于HBase位于 Hadoop框架之上,因此可以使用HadoopMapReduce来快速、高效地生成索引表。
⑤数据维护。在关系数据库中,更新操作会用最新的当前值去替换记录中原来的旧值,旧值被覆盖后就不会存在。而在HBase中执行更新操作时,并不会删除数据旧的版本,而是生成一个新的版本,旧有的版本仍然保留。
⑥可伸缩性。关系数据库很难实现横向扩展,纵向扩展的空间也比较有限。相反,HBase和BigTable这些分布式数据库就是为了实现灵活的水平扩展而开发的,因此能够轻易地通过在集群中增加或者减少硬件数量来实现性能的伸缩。
但是,相对于关系数据库来说,HBase也有自身的局限性,如HBase不支持事务,因此无法实现跨行的原子性。

4.3HBase数据模型

(一)HBase列族数据模型包括:

列族、列限定符、单元格、时间戳等概念
①表
一HBase采用表来组织数据、表由行和列组成,列划分为若干个列族。
②行
每个HBase表都由若干行组成,每个行由行键(Row Key)来标识。访问表中的行只有3种方式:通过单个行键访问;通过一个行键的区间来访问;全表扫描。行键可以是任意字符串(最大长度是64KB,实际应用中长度一般为10~100字节),在HBase内部,行键保存为字节数组。存储时,数据按照行键的字典序排序存储。在设计行键时,要充分考虑这个特性,将经常一起读取的行存储在一起。
③列族
一个HBase表被分组成许多“列族”的集合,它是基本的访问控制单元。列族需要在表创建时就定义好,数量不能太多(HBase的一些缺陷使得列族数量只限于几十个),而且不要频繁修改。存储在一个列族当中的所有数据,通常都属于同一种数据类型,这通常意味着具有更高的压缩率。表中的每个列都归属于某个列族,数据可以被存放到列族的某个列下面,但是在把数据存放到这个列族的某个列下面之前,必须首先创建这个列族。在创建完成一个列族以后,就可以使用同一
个列族当中的列。列名都以列族作为前缀。例如,courses:history和courses:math这两个都属于courses 这个列族。在HBase中,访问控制、磁盘和内存的使用统计都是在列族层面进行的,实际应用中,我们可以借助列族上的控制权限帮助实现特定的目的。比如,我们可以允许一些应用能够向表中添加新的数据,而另一些应用则只允许浏览数据。HBase列族还可以被配置成支持不同类型的访问模式。比如,一个列族也可以被设置成放入内存当中,以消耗内存为代价,从面换取更好的响应性能。
④列限定符
族、列限定符和
列族里的数据通过列限定符(或列)来定位。列限定符不用事先定义,也不需要在不同行之间保持一致。列限定符没有数据类型,总被视为字节数组byte[]。
⑤单元格
在HBase表中,通过行、列族和列限定符确定一个“单元格”(Cell)。单元格中存储的数据没有数据类型,总被视为字节数组byte[]。每个单元格中可以保存一个数据的多个版本,每个版本对应一个不同的时间戳。
⑥时间戳
每个单元格都保存着同一份数据的多个版本,这些版本采用时间戳进行索引。每次对一个单元格执行操作(新建、修改、删除)时,HBase
都会隐式地自动生成并存储一个时间戳。时间戳一般是64位整型,可以由用户自己赋值(自己生成唯一时间戳可以避免应用程序中出现数据版本冲突),也可以由HBase在数据写入时自动赋值。一个单元格的不同版本是根据时间截降序的顺序进行存储的,这样,最新的版本可以被最先读取。
在这里插入图片描述
图4-2HBase数据模型的一个实例

(二)数据坐标:

HBase视为一个四维坐标,即[行键,列族,列限定符,时间戳]。

(三)面向列的储存:

简单地说,行式数据库使用NSM(N-aryStorageModel)存储模型,一个元组(或行)会被连续地存储在磁盘页中,如图4-3所示,也就是说,数据是一行一行被存储的,第一行写入磁盘页后,再继续写入第二行,依此类推。在从磁盘中读取数据时,需要从磁盘中顺序扫描每个元组的完整内容,然后从每个元组中筛选出查询所需要的属性。如果每个元组只有少量属性的值对于查询是有用的,那么NSM就会浪费许多磁盘空间和内存带宽。
在这里插入图片描述
图4-3行式数据库和列式数据库示意

(四)行数据库和列数据库的优缺点:

行式数据库主要适用于小批量的数据处理,如联机事务性数据处理,我们平时熟悉的Oracle和MySQL等关系数据库都属于行式数据库。列数据库主要适用于批量数据处理和即席查询。它的优点是可以降低I/O开销,支持大量并发用户查询,其数据处理速度比传统方法快100倍,具有较高的数据压缩比,较传统的行式数据库更加有效,甚至能达到五倍的效果。列式数据库主要用于数据挖掘、决策支持和地理信息系统等查询密集型系统中, 因为一次查询就可以得出结果而不是每次都要遍历所有的数据库。

4.4HBase实现原理

(一)HBase的实现主要包括三个组件:

库函数,链接到每个客户端、master主服务器、多个Region服务器

(二)(重点)Region的定位HBase的三层结构

在这里插入图片描述

(三)HBase的系统架构

包括客户端、Zookeeper服务器、Master主服务器、Region服务器。
①客户端
客户端包含访问HBase的接口,同时在缓存中维护着已经访问过的Region位置信息,用来加快后续数据访问过程。HBase客户端使用HBase的RPC机制与Master和Region服务器进行通信。其中,对于管理类操作,客户端与Master进行RPC;而对于数据读写类操作,客户端则会与 Region服务器进行 RPC。
②Zookeeper 服务器
Zookeeper服务并非一台单一的机器,可能是由多台机器构成的集群来提供稳定可靠的协同服务。Zookeeper能够很容易地实现集群管理的功能,如果有多台服务器组成一个服务器集群那么必须有一个“总管”知道当前集群中每台机器的服务状态,一旦某台机器不能提供服务,集群中其他机器必须知道,从而做出调整重新分配服务策略。同样,当增加集群的服务能力时,就会增加一台或多台服务器,同样也必须让“总管”知道。
在HBase服务集群中,包含了一个Master和多个Region服务器,Master就是这个HBase集群的“总管”,它必须知道Region服务器的状态。Zookeeper就可以轻松做到这一点,每个 Region服务器都需要到Zookeeper中进行注册,Zookeeper会实时监控每个Region服务器的状态并通知给Master,这样,Master就可以通过Zookeeper随时感知到各个Region 服务器的工作状态。
Zookeeper不仅能够帮助维护当前的集群中机器的服务状态,而且能够帮助选出一个“总管”,让这个总管来管理集群。HBase中可以启动多个Master,但是Zookeeper可以帮助选举出一个 Master 作为集群的总管,并保证在任何时刻总有唯一一个Master在运行,这就避免了 Master的“单点失效”问题。
Zookeeper 中保存了-ROOT-表的地址和Master的地址,客户端可以通过访问Zookeeper获得 -ROOT-表的地址,并最终通过“三级寻址”找到所需的数据。Zookeeper中还存储了 HBase的模式,包括有哪些表,每个表有哪些列族。
③Master
? 主服务器Master主要负责表和Region的管理工作。
? 管理用户对表的增加、删除、修改、查询等操作。
? 实现不同Region服务器之间的负载均衡。
? 在Region 分裂或合并后,负责重新调整Region 的分布。
? 对发生故障失效的Region服务器上的Region 进行迁移。
客户端访问HBase上数据的过程并不需要Master的参与,客户端可以访问Zookeeper 获取-ROOT表的地址,并最终到达相应的Region服务写,Master仅仅维护着表和 Region的元数据信息,因此负载很低。
任何时刻,一个Region只能分配给一个Region服务器。Master维护了当前可用的Region服务器列表,以及当前哪些Region分配给了哪些Region服务器,哪些Region还未被分配。当存在未被分配的 Region,并且有一个Region服务器上有可用空间时,Master就给这个Region服务器发送一个请求,把该Region 分配给它。Region服务器接受请求并完成数据加载后,就开始负责管理该Region对象,并外提供服务。
④Region服务器
Region 服务器是HBase中最核心的模块,负责维护分配给自己的Region,并响应用户的读写请求。HBase一般采用HDFS作为底层存储文件系统(见图4-9),因此Region服务器需要向 HDFS文件系统中读写数据。采用HDFS作为底层存储,可以为HBase提供可靠稳定的数据存储,HBase自身并不具备数据复制和维护数据副本的功能,而HDFS 可以为 HBase 提供这些支持。当然,HBase也可以不采用HDFS,而是使用其他任何支持Hadoop接口的文件系统作为底层存储,比如本地文件系统或云计算环境中的Amazon S3 (Simple
Storage Service )。

(四)Region基本原理

Region 服务器是HBase中最核心的模块,图4-10描述读写数据的基本原理,从图中可以看出,Region服务器内部管理了一系列Region对象和一个HLog Region服务器向 HDFS文件系统中文件,其中HLog是磁盘上面的记录文件,它记录着所有的更新操作。每个Region对象又是由多个 Store组成的,每个Store对应了表中的一个列族的存储。每个Store又包含了一个MemStore和若干个StoreFile,其中,MemStore是在内存中的缓存,保存最近更新的数据;StoreFile是磁盘中的文件,这些文件都是B树结构的,方便快速读取。StoreFile在底层的实现方式是HDFS文件系统的HFile,HFile的数据块通常采用压缩方式存储,压缩之后可以大大减少网络I/O和磁盘I/O。
在这里插入图片描述

第五章NoSQL数据库

一、NoSQL的含义(没划,习题里的)

是一种不同于关系数据库的数据库管理系统设计方式,是对非关系型数据库的统称,它所采用的数据模型并非传统关系数据库的关系模型,而是类似键/值、列族、文档等非关系模型。

二、NoSQL数据库的三个特点?

1、灵活的可扩展性
2、灵活的数据模型
3、与云计算紧密融合

三、关系数据库无法满足Web2.0的需求主要表现在哪三个方面?(关系数据库的局限性)

1、无法满足海量数据的管理需求
2、无法满足数据高并发的需求
3、无法满足高可扩展性和高可用性的需求

四、关系数据库的突出优势?

以完善的关系代数理论作为基础,有严格的标准,支持事务ACID四性,借助索引机制可以实现高效的查询,技术成熟,有专业公司的技术支持。

五、关系数据库的劣势?

可扩展性差,无法较好地支持海量数据存储,数据模型过于死板,无法较好地支持Web2.0应用,事务机制影响了系统整体性能。

六、NoSQL数据库的明显优势?

可以支持超大规模数据存储,灵活的数据模型可以很好地支持Web2.0应用,具有强大的横向扩展能力。

七、NoSQL数据库的劣势?

缺乏数学理论基础,复杂查询性能不高,一般都不能实现事务强一致性,很难实现数据完整性,技术尚不成熟,缺乏专业团队的技术支持,维护较困难。

八、NoSQL的四大类型?(重点)(P99-P101的小标题,了解标题下的内容)

键值数据库、列族数据库、文档数据库、图数据库

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

九、NoSQL的三大基石?(重点)(P101-P104的小标题,了解标题下的内容)

CAP(一致性、可用性、分区容忍性)
BASE(基本可用、软状态、最终一致性)
最终一致性(因果一致性、“读己之所写”、会话一致性、单调读一致性、单调写一致性)

十、大数据引发数据处理架构变革

在这里插入图片描述
变革前,一种架构支持多类应用,包括事务型应用(OLTP系统)、分析型应用(OLAP、数据仓库)和互联网应用(Web 2.0)。

第六章 云数据库

1. 云计算和云数据库的概念

云计算是分布式计算、并行计算、效用计算、网络存储、虚拟化、负载均衡等计算机和网络技术发展融合的产物。云数据库是部署和虚拟化在云计算环境中的数据库。云数据库是在云计算的大背景下发展起来的一种新兴的共享基础架构的方法,它极大地增强了数据库的存储能力,消除了人员、硬件、软件的重复配置,让软、硬件升级变得更加容易,同时也虚拟化了许多后端功能。

2. UMP系统概述

UMP系统是低成本和高性能的 MySQL云数据库方案,关键模块采用 Erlang 语言实现。开发者通过网络从平台上申请 MySQL 实例资源,由平台提供的单一入口来访问数据。UMP系统把各种服务器资源划分为资源池,并以资源池为单位把资源分配给 MySQL 实例。系统中包含了一系列组件,这些组件协同工作,以对用户透明的形式提供主从热备、数据备份、迁移、容灾、读写分离、分库分表等一系列服务。

3. UMP采用的两种资源隔离方式

在这里插入图片描述

第七章 MapReduce

1、MapReduce的两个设计理念:

“计算向数据靠拢”(P133)、“分而治之”(P144)

2、MapReduce的工作流程

在这里插入图片描述

3、MapReduce算法的执行过程

(1)MapReduce框架使用InputFormat模块做Map前的预处理,比如验证输入的格式是否符合输入定义;然后,将输入文件切分为逻辑上的多个InputSplit,InputSplit是MapReduce对文件进行处理和运算的输入单位,只是一个逻辑概念,每个InputSplit并没有对文件进行实际切割,只是记录了要处理的数据的位置和长度。
(2)因为InputSplit是逻辑切分而非物理切分,所以还需要通过RecordReader根据 InputSplit中的信息来处理InputSplit中的具体记录,加载数据并转换为适合Map任务读取的键值对,输入给 Map任务。
(3)Map任务会根据用户自定义的映射规则,输出一系列的<key,value>作为中间结果。
(4)为了让 Reduce可以并行处理Map的结果,需要对Map的输出进行一定的分区、排序、合并、归并等操作,得到<key,value-list>形式的中间结果,再交给对应的Reduce进行处理,这个过程称为Shuffle。从无序的<key,value>到有序的<key,value-list>,这个过程用 Shuffle来称呼是非常形象的。
(5)Reduce以一系列<key,value-list>中间结果作为输入,执行用户定义的逻辑,输出结果给 OutputFormat 模块。
(6)OutputFormat模块会验证输出目录是否已经存在以及输出结果类型是否符合配置文件中的配置类型,如果都满足,就输出Reduce的结果到分布式文件系统。
在这里插入图片描述

4、Shuffle过程详解(P136)

所谓 Shuffle,是指对Map输出结果进行分区、序、合并等处理并交给Reduce的过程。因此,Shuffle过程分为Map端的操作和Reduce端的操作。
在这里插入图片描述
在Map端的Shuffle过程:
Map的输出结果首先被写入缓存,当缓存满时,就启动溢写操作,把缓存中的数据写人磁文件,并清空缓存。当启动溢写操作时,首先需要把缓存中的数据进行分区,然后对每个分区的数据进行排序(Sort)和合并(Combine),之后再写入磁盘文件。每次溢写操作会生成一个新的磁盘文件,随着Map任务的执行,磁盘中就会生成多个溢写文件。在Map任务全部结束之前,这些溢写文件会被归并(Merge)成一个大的磁盘文件,然后通知相应的Reduce任务来领取属于自己处理的数据。
在这里插入图片描述
4个步骤:
(1) 输入数据和执行Map任务
(2) 写入缓存
(3) 溢出(分区、排序和合并)
(4) 文件归并
在Reduce 端的 Shuffle 过程
Reduce任务从Map端的不同Map机器领回属于自己处理的那部分数据,然后对数据进行归并后交给 Reduce处理。
在这里插入图片描述
3个步骤:
(1) “领取”数据
(2) 归并数据
(3) 把数据输入给Reduce任务

5、用MapReduce来处理的数据集需要满足一个前提条件(P140):

待处理的数据集可以分解成许多小的数据集,而且每一个小数据集都可以完全并行地进行处理。
在WordCount程序任务中,不同单词之间的频数不存在相关性,彼此独立,可以把不同的单词分发给不同的机器进行并行处理,因此可以采用MapReduce来实现词频统计任务。

6、MapReduce程序的设计思路(P139)。

把文件内容解析成许多个单词,然后把所有相同的单词聚集到一起,最后计算出每个单词出现的次数进行输出。

7、WordCount的具体执行过程(P140、理解)。

对于WordCount程序任务,整个MapReduce过程实际的执行顺序如下。
(1)执行WordCount的用户程序(采用MapReduc编写),会被系统分发部署到集群中的多台机器上,其中一个机器作为Master,负责协调调度作业的执行,其余机器作为Worker,可以执行Map 或 Reduce任务。
(2)系统分配一部分Worker执行Map任务,一部分Worker执行 Reduce任务;MapReduce将输入文件切分成M个分片,Master将M个分片分给处于空闲状态的N个Worker来处理。
(3)执行Map任务的Worker读取输人数据,执行Map操作,生成一系列<key,value>形式的中间结果,并将中间结果保存在内存的缓冲区中。
(4)缓冲区中的中间结果会被定期刷写到本地磁盘上,并被划分为R个分区,这R个分区会被分发给R个执行Reduce任务的Worker进行处理;Master会记录这R个分区在磁盘上的存储位置,并通知R个执行Reduce任务的Worker来“领取”属于自己处理的那些分区的数据。
(5)执行Reduce任务的 Worker 收到Master的通知后,就到相应的Map机器上“领回”属于自己处理的分区。需要注意的是,正如之前在Shuffle过程阐述的那样,可能会有多个 Map机器通知某个Reduce机器来领取数据,因此一个执行Reduce任务的Worker,可能会从多个Map机器上领取数据。当位于所有Map机器上的、属于自己处理的数据都已经领取回来以后,这个执行Reduce任务的Worker会对领取到的键值对进行排序(如果内存中放不下需要用到外部排序),使得具有相同key的键值对聚集在一起,然后就可以开始执行具体的Reduce操作了。
(6)执行Reduce 任务的Worker遍历中间数据,对每一个唯一key执行Reduce函数,结果写入到输出文件中;执行完毕后,唤醒用户程序,返回结果。
在这里插入图片描述

第八章 Hadoop再讨论

(一)Hadoop 框架自身的改进:从1.0到2.0

在这里插入图片描述

(二)不断完善的 Hadoop 生态系统

在这里插入图片描述

(三)HDFS的两个新特性

HDFS HA和HDFS 联邦

(四)HDFS HA

由于第二名称节点无法提供“热备份”功能,即在名称节点发生故障的时候,系统无法实时切换到第二名称节点立即对外提供服务,仍然需要进行停机恢复,因此 HDFS 1.0的设计是存在单点故障问题的。为了解决单点故障问题,HDFS 2.0采用了 HA(High Availability)架构。在一个典型的HA 集群中,一般设置两个名称节点,其中一个名称节点处于“活跃(Active)”状态,另一个处于“待命 (Standby)”状态。处于活跃状态的名称节点负责对外处理所有客户端的请求,而处于待命状态的名称节点则作为备用节点,保存了足够多的系统元数据,当名称节点出现故障时提供快速恢复能力。也就是说,在 HDFS HA 中,处于待命状态的名称节点提供了“热备份”一旦活跃名称节点出现故障,就可以立即切换到待命名称节点,不会影响到系统的正常对外服务。

(五)HDFS 联邦

HDFS 联邦可以很好地解决可扩展性、系统性能和隔离性三个方面的问题。在HDFS 联邦中,设计了多个相互独立的名称节点,使得 HDFS 的命名服务能够水平扩展,这些名称节点分别进行各自命名空间和块的管理,相互之间是联邦关系,不需要彼此协调。HDFS 联邦并不是真正的分布式设计,但是采用这种简单的“联合”设计方式,在实现和管理复杂性方面,都要远低于真正的分布式设计而且可以快速满足需求。在兼容性方面,HDFS 联邦具有良好的向后兼容性,可以无缝地支持单名称节点架构中的配置。所以,原有针对单名称节点的部署配置,不需要做任何修改就可以继续工作。

(六)YARN设计思路

基本思路就是“放权”即不让JobTracker 这一个组件承担过多的功能,把原 JobTracker 三大功能(资源管理、任务调度和任务监控)进行拆分,分别交给不同的新组性去处理。重新设计后得到的 YARN 包括 ResourceManager、ApplicationMaster 和NodeManager,其中,由 ResourceManager 负责资源管理,由ApplicationMaster 负责任务调度和监控,由 NodeManager 负责执行原 TaskTracker 的任务。
在这里插入图片描述

(七) YARN 名个组件的功能

在这里插入图片描述

(八) YARN工作流程

(九) 163页的所有文字,比较多

在这里插入图片描述

(十)YARN的发展目标

YARN的目标就是实现“一个集群多个框架”,即在一个集群上部署一个统一的资源调度管理框架 YARN,在YARN之上可以部署其他各种计算框架(见图 8-9)比如MapReduce Tez、HBase、Storm、Giraph、Spark、OpenMPI 等,由 YARN 为这些计算框架提供统一的资源调度管理服务,并且能够根据各种计算框架的负载需求,调整各自占用的资源,实现集群资源共享和资源弹性收缩。通过这种方式,可以实现一个集群上的不同应用负载混搭,有效提高了集群的利用率;同时,不同计算框架可以共享底层存储,在一个集群上集成多个数据集,使用多个计算框架来访问这些数据集,从而避免了数据集跨集群移动,最后,这种部署方式也大大降低了企业运维成本。

第九章 Spark

9.1.1spark概述

Spark的4个特点:
① 运行速度快。Spark使用先进的DAG执行引擎,以支持循环数据流与内存计算,基于内存的执行速度可比Hadoop MapReduce快上百倍,基于磁盘的执行速度也能快上十倍。
② 容易使用。Spark支持使用Scala、Java、Python和R语言进行编程,见解的API设计有助于用户轻松构建并行程序,并且可以通过Spark Shell进行交互式编程。
③ 通用性。Spark提供了完整而强大的技术栈,包括SQL查询、流式计算、机器学习和图算法组件,这些组件可以误封整合在同一个应用中,足以应对复杂的计算。
④ 运行模式多样。Spark可运行与独立的集群模式中,或者运行在Hadoop中,也可以运行于Amazon EC2等云环境中,并且可以访问HDFS、Cassandra、Hbase、Hive等多种数据源

9.1.2Scala简介Scala的特点:

① Scala具备强大的并发性,支持函数式编程,可以更好地支持分布式系统
② Scala语法简介,能提供优雅的API
③ Scala兼容Java,运行速度快,且能融入到Hadoop生态环境中。
Scala是Spark的主要编程语言,但Spark还支持Java、Python、R作为编程语言。因此若仅仅只是编写Spark程序,并非一定要Scala。

9.1.3Spark与Hadoop的对比

①回顾Haddop的工作流程,可以发现Hadoop存在的缺点

  1. 表达能力有限。计算都必须要转化成Map和Reduce两个操作,但这并不适合所有的情况,难以描述复杂的数据处理过程。
  2. 磁盘IO开销大。每次执行时都需要从磁盘读取数据,并且在计算完成后需要将中间结果写入到磁盘中,IO开销较大。
  3. 延迟高。依次计算可能需要分解成一系列按顺序执行的MapRedecu人物,人物之间的衔接由于涉及到IO开销,会产生较高延迟。而且,在前一个任务执行完成之前,其他任务无法开始,因此难以胜任复杂、多阶段的任务
    ②Spark相比Hadoop的优点如下
  4. Spark的计算模式也属于MapReduce,但不局限于Map和Reduce操作,还提供了多种数据集操作类型,编程模型比MapReduce更灵活。
  5. Spark提供了内存计算,中间结果直接放到内存中,带来了更高的迭代运算效率。
  6. Spark基于DAG的任务调度执行机制,要优于MapReduce的迭代执行机制。
    虽然Spark相比Hadoop拥有较大的优势,但是Spark仍然不能完全替代Hadoop,主要用于替代Hadoop中的MapReduce计算模型。Hadoop可以使用廉价的异构的机器来做分布式存储与计算,而Spark对硬件的要求稍微高一些,对内存与CPU有一定的要求。

9.2Spark生态系统

①大数据处理主要包括以下三个类型:

  1. 复杂的批量数据处理:时间跨度通常在数十分钟到数小时之间。
  2. 基于历史数据的交互式查询:时间跨度通常在数十秒到数分钟之间。
  3. 基于实时数据流的数据处理:时间跨度通常在数百毫秒到数秒之间。
    ②Spark的设计遵循“一个软件栈满足不同应用场景”的理念。逐渐形成了一套完整的生态系统,既能够提供内存计算框架,也可以支持SQL即席查询、实时流式计算、机器学习和图计算等。
    ③Spark生态系统主要包含了SparkCore、Spark SQL、Spark Streaming、 MLlib和GraphX等组件,各个组件的具体功能如下
  4. SparkCore
    SparkCore包含Spark的基本功能,如内存计算、任务调度、部署模式、故障恢复、存储管理等,主要面向批数据处理。Spark建立在统一的抽象RDD智商,使其可以以基本一致的方式应对不同的大数据处理场景。
  5. Spark SQL
    SparkSQL允许开发人员直接处理RDD,同时也可查询Hive、HBase等外部数据源。他的一个重要特点是能够统一处理关系表和RDD,使得开发人员不需要自己编写Spark应用程序,使用更简单轻松的SQL命令进行查询。
  6. Spark Streaming
    它支持高吞吐量,可容错处理的实时流数据处理,其核心思路是将流数据分解成一系列短小的批处理作业,每一个短小的批处理作业都可以使用Spark Core进行快速处理。Spark streaming支持多种数据输入源,如kafka、flume和TCP套接字等
  7. MLlib(机器学习)
    MLlib提供了常用机器学习算法的实现,包括聚类、分类、回归、协同过滤等,降低了机器学习的门槛,开发人员只要具备一定的理论知识就能进行机器学习的工作。
  8. GraphX(图处理)
    它是Spark中用于图计算的API,可认为是Pregel在Spark上的重写及优化,GraphX性能良好拥有丰富的功能和运算符,能在海量数据上自如地运行复杂的图算法。
    需要注意的是,Spark SQL,Spark Streaming MLlib和GraphX都可以使用Spark Core的API 处理问题,他们的方法几乎是通用的,处理的数据也可以共享。

9.3Spark运行架构

9.3.1基本概念

RDD:是弹性分布式数据集的英文缩写,是分布式内存的一个抽象概念,提供了一种高度受限的共享内存模型
DAG:是有向无环图的英文缩写,反应RDD之间的依赖关系。
Executor:是运行在工作结点上的一个进程,负责运行任务,并为应用程序存储数据。
应用:用户编写的Spark应用程序。
任务:运行在Executor上的工作单元。
作业:一个作业包含多个RDD及作用于相应RDD上的各种操作。
阶段:是作业的基本调度单位,一个作业会分为多组任务,每组任务被称作“阶段”,或者也被称为“任务集”。

9.3.2架构设计

Spark所采用的Executor的优点

  1. 利用多线程来执行具体的人物(Hadoop MapReduce采用的是进程模型),减少人物的启动开销。
  2. Executor中有一个BlockManager存储模块,会将内存和磁盘共同作为储存设备,当需要多轮迭代计算时,可将中间结果存储到这个存储模块里。有效的减少了IO开销提升了读写IO性能。

9.3.3 Spark运行基本流程

Spark运行流程

  1. 当一个Spark应用被提交时,首先需要为这个应用构建起基本的运行环境,即由人物控制结点创建一个SoarkConext,有SparkContext负责和资源管理器的通信以及进行资源的申请、任务的分配和监控。
  2. 资源管理器为Executor分配资源,并启动Executor进程,Executor运行情况将随着“心跳”发送到资源管理器上。
  3. SparkContext根据RDD的依赖关系构建DAG图,DAG图提交给DAG调度器进行解析,将DAG图分解成多个阶段,并且计算出各个阶段之间的依赖关系,然后把一个个“任务集”提交给底层的任务调度器进行处理。Executor向SparkContext申请任务,任务调度器将任务分发给Executor运行,同时SaparkContext将应用程序代码发放给Executor。
  4. 任务在Executor上运行,把执行结果反馈给任务调度器,然后反馈给DAG调度器,运行完毕后写入数据兵释放所有资源
    Spark架构运行特点:
  5. 每个应用都有自己的专属Executor进程,并且在应用运行期间一直驻留。Executor以多线程运行任务,减少了减少了多进程任务频繁的启动开销。
  6. Spark运行过程与资源管理器无关,只要能获取Executor进程并保持通信即可。
  7. Executor上有一个BlockManager存储模块,类似于键值存储系统(把内存和磁盘共同作为存储设备),在处理迭代计算任务时,不需要把中间结果写入HDFS中,而是直接存入BlockManager中,减少IO开销,提高读写IO性能。
  8. 任务采用了数据本地行和推测执行等优化机制。数据本地性是尽量将计算移到数据所在的节点上进行,即“计算向数据靠拢”因为移动计算比移动数据所占的网络资源要少得多。而且,Spark采用了延时调度的机制,可以更大程度上实现执行过程优化。

9.4 Spark的部署和应用方式

9.4.1Spark三种部署方式

  1. standalone模式
    与MapReduce1.0框架类似,spark框架本身也自带了完整的资源调度管理服务,可以独立部署到一个集群中,而不需要依赖其他系统来为其提供资源管理调度服务。在架构的设计上,Spark与MapReduce1.0完全一致,都是由一个master和若干个slave构成,并且以槽(slot)作为资源分配单位。不同的是,spark的槽不再像MapReduce1.0那样分为map槽和reduce槽,而是只设计了一个统一的槽提供给各种任务来使用。
    2.Spark on Mesos模式
    Mesos是一种资源调度管理框架,可以为运行在它上面的Spark提供服务。由于Mesos和Spark存在一定的学院关系,因此Spark这个框架在进行设计开发的时候就充分考虑到了对Mesos的充分支持。相对而言Spark在Mesos上运行要比在YARN上更灵活和自然。
    3.Spark on YARN模式
    Spark可运行在YARN智商,与Hadoop进行统一部署,即“Spark on YARN”,其架构图如下图所示。资源管理和调度依赖YARN,分布式存储则依赖HDFS。

9.4.2 spark架构相比于hadoop+storm的优点

1.实现了一件安装和配置,线程级别的任务监控和告警。
2.降低硬件集群、软件维护、任务监控和应用开发的难度。
3.便于做成统一的硬件、计算平台资源池。
需要说明的是,sparkstreaming的原理是将流数据分解成一系列短小的批处理作业,每个短小的作业使用面向批处理的spark Core进行处理,通过这种方式变相实现流计算,而不是真正的实时流计算,因而无法实现毫秒级响应。

9.4.3 Hadoop和Spark的统一部署

统一部署的原因

  1. hadoop生态环境中的一些组件所实现的功能,spark还无法实现,比如毫秒级响应。
  2. 企业中已经有许多现有应用是基于hadoop组件开发的,完全转移到spark上需要一定的成本。
    Hadoop MapReduce、HBase、Storm、Spark等都可以运行在资源管理框架YARN上,将这些不同的计算框架同意运行在YARN之中带来的好处有:
  3. 计算资源按需伸缩。
  4. 不用负载营运混搭,集群利用率高。
  5. 更像底层存储,避免数据跨集群迁移.。

第十章 流数据

(一) 静态数据:

是指在运行过程中主要作为控制或参考用的数据,它们在很长的一段时间内不会变化,一般不随运行而变。

(二) 流数据:

是指在时间分布和数量上无线的一系列动态数据集合体。

(三) 流数据的特征:

  1. 数据快速持续到达,潜在大小也许时无穷无尽的
  2. 数据来源众多,格式复杂
  3. 数据量大,但是不十分关注存储,一旦流数据中的某个元素经过处理,要么被丢弃,要么被归档存储。
  4. 注重数据的整体价值,不过分关注个别数据。
  5. 数据顺序颠倒,或者不完整,系统无法控制将要处理的新到达的数据元素的顺序

(四) 流计算系统应达到如下需求:

高性能、海量式、实时性、分布式、易用性、可靠性

(五) 流计算框架

目前业内已涌现出许多的流计算框架与平台,在此做一个小小的汇总。
第一类是商业级的流计算平台,代表如下。
① IBM InfoSphere Streams。商业级高级计算平台,可以帮助用户开发应用程序来快速摄取、分析和关联来自数千个实时源的信息。
②IBM StreamBase。IBM开发的另一款商业流计算系统,在金融部门和政府部门使用。第二类是开源流计算框架,代表如下。
Twitter Storm。免费、开源的分布式实时计算系统,可简单、高效、可靠地处理大量的流数据,阿里巴巴公司的JStorm,是参考Twitter Storm开发的实时流式计算框架,可以看成是Storm的 Java 增强版本,在网络I0、线程模型、资源度、可用性及稳定性上做了持续改进,已被越来越多的企业使用。
②Yahoo! S4( Simple Scalable Streaming System )。开源流计算平台,是通用的、分布式的、可扩展的、分区容错的、可插拔的流式系统。
第三类是公司为支持自身业务开发的流计算框架,虽然未开源,但有不少的学习资料可供了解、学习,主要如下。
① Facebook Puma。Facebook 使用Puma和HBase相结合来处理实时数据。②DStream。百度开发的通用实时流数据计算系统。
③银河流数据处理平台。淘宝开发的通用流数据实时计算系统。
④ Super Mario。基于Erlang语言和Zookeeper模块开发的高性能流数据处理框架。此外,业界也涌现出了像SQLStream 这样专门致力于实时大数据流处理服务的公司。

(六) 流计算的处理流程包含3个阶段:

数据实时采集、数据实时计算、实时查询服务
在这里插入图片描述

(七) 数据采集系统的基本架构:

  1. Agent:主动采集数据,并把数据推送到Collector部分
  2. Collector:接收多个Agent的数据,并实现有序、可靠、高性能的转发
  3. Store:存储Collector转发过来的数据
    在这里插入图片描述

(八) 流处理系统与传统的数据处理不同之处:

  1. 流处理系统处理的是实时的数据,而传统的数据处理系统处理的是预先存储好的静态数据
  2. 用户通过流处理系统获取的是实时结果,而通过传统的数据处理系统获取的是过去某一时刻的结果。并且,流处理系统无需用户主动发出查询,实时查询服务可以将实时结果推送给用户。

(九) SM框架处理流程

在这里插入图片描述

(十) Twitter Storm是一个免费、开源的分布式实时计算系统,Storm可以简单、高效、可靠的处理流数据,并支持多种编程语言。Twitter是全球访问量最大的社交网站之一,采用了由实时系统和批处理系统组成的分层数据处理架构。

在这里插入图片描述

(十一) Storm的设计思想:

主要包括Streams、Spouts、Bolts、Topology、Stream Grooupings

(十二) Storm集群采用”Master-Worker”的节点方式

(十三) Spark Streaming最主要的抽象是Dstream,表示连续不断的数据流,在内部实现上,Spark Streaming的输入数据按照时间片分成一段一段的Dstream,每一段数据转换为Spark中的RDD,并且对Dstream的操作都最终转变为对相应的RDD的操作。

(十四) Spark Streaming和Strom最大的区别在于,Spark Streaming无法实现毫秒级的流计算,而Storm则可以实现毫秒级的响应

第十一章 图计算

一、传统的图计算算法存在的几个典型问题?

1.常常表现出比较差的内存访问局部性
2.针对单个顶点的处理工作过少
3.计算过程中伴随着并行度的改变

二、针对大型图(社交网络和网络图)的计算问题,可能解决方案及其不足之处具体如下:

1.为特定的图应用定制相应的分布式实现。不足之处是通用性不好,在面对新的图算法或者图表示方式时,就需要做大量的重复开发。
2.基于现有的分布式计算平台进行图计算。比如,MapReduce作为一个优秀的大规模数据处理框架,有时也能够用来对大规模图对象进行挖掘,不过在性能和易用性方面往往无法达到最优。
3.使用单机的图算法库,比如BGL、LEAD、NetworkX、JDSL、Standford GraphBase和FGL等。但是,这种单机方式在可以解决的问题的规模方面具有很大的局限性。
4.使用已有的并行图计算系统。Parallel BGL和CGM Graph这些库实现了很多并行图算法,但是对大规模分布式系统非常重要的一些方面(如容错),无法提供较好的支持。

三、目前通用的图处理软件主要包括?(两种)

1.第一种主要是基于遍历算法的、实时的图数据库,如Neo4j、OrientDB、DEX和InfiniteGraph。
2.以图顶点为中心的、基于消息传递批处理的并行引擎(注意:图处理软件主要是基于BSP模型实现的并行图处理系统),如Hama、GoldenOrb、Giraph和Pregel。

四、BSP(“大同步模型”)计算过程包括一系列全局超步(超步指计算中的一次迭代),每个超步主要包括三个组件:

1.局部计算(每个参与的处理器都有自身的计算任务,它们只读取存储在本地内存中的值,不同处理器的计算任务都是异步并且独立的。)
2.通信(处理器群相互交换数据,交换的形式是,由一方发起推起(put)和获取(get)操作。)
3.栅栏同步(当一个处理器遇到“路障”(或栅栏),会等其他所有处理器完成它们的计算步骤,每一次同步也是一个超步的完成和下一个超步的开始。)

五、Hadoop时代的新“三驾马车”

答:Caffeine、Dremel和Pregel

六、Pregel计算模型中的有向图和顶点

在这里插入图片描述
顶点之间采用纯消息传递模型的主要原因(2点)
1.消息传递具有足够的表达能力,没有必要使用远程读取或共享内存的方式。
2.有助于提升系统整体性能。(大型图计算通常是由一个集群完成的,集群环境中执行远程数据读取会有较高的时间延迟;Pregel的消息模式采用异步和批量的方式传递消息,因此可以缓解远程读取的延迟。)

八、状态机的活跃状态和非活跃状态之间(配合课本214理解)

在这里插入图片描述

九、Combiner的默认情况

答:Pregel计算框架并不会开启Combiner功能,因为通常很难找到一种对所有顶点的Compute()函数都合适的Combiner。当用户打算开启Combiner功能时,可以继承Combiner类并覆写虚函数Combine()

十、Combiner应用例子

在这里插入图片描述

十一、Pregel采用两种机制解决多顶点操作请求存在冲突问题:

1.局部有序:拓扑改变的请求是通过消息发送的,在执行一个超步时,所有拓扑改变会在调用Compute()函数之前完成。
2.Handler:局部有序机制无法解决的问题,借助于用户自定义的Handler来解决,包括解决由于多个顶点删除请求或多个边增加请求(或删除请求)而造成的冲突。

十三、Worker中,它所管辖的分区的状态信息是保存在内存之中的。分区中的顶点的状态信息如下:

1.顶点的当前值。
2.以该顶点为起点的出射边列表,每条出射边包含了目标顶点ID和边的值。
3.消息队列,包含了所有接收到的、发送给该顶点的消息。
4.标志位,用来标记顶点是否处于活跃状态。

十四、Master负责协调各个worker执行任务的主要内容

Master会为每个worker分配一个唯一的ID。Master维护着关于当前处于“有效“状态的所有Worker的各种信息,包括每个Worker的ID和地址信息,以及每个Worker被分配到的分区信息。

十五、十一章的了解内容

  1. p222以及p218——Aggregator
  2. p220——容错性
  3. p219——Pregel的执行过程
  4. p217——消息传递机制
  5. p214——Pregel求解最大值过程

小结:

关注我给大家分享更多有趣的知识,以下是个人公众号,提供 ||代码兼职|| ||代码问题求解||
由于本号流量还不足以发表推广,搜我的公众号即可:
在这里插入图片描述

文章来源:https://blog.csdn.net/m0_72249799/article/details/135564040
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。