2024年重庆甘肃安徽等省职业院校技能大赛_大数据应用开发样题解析-模块F:综合分析

  • 任务一:请描述HBase 的rowkey 设计原则。

  • 任务二:ClickHouse 有哪些表引擎?列举四种并简要描述。

  • 任务三:对于分组排序的理解。

  • 任务四:Kafka 中的数据如何保证不丢失?

  • 任务五:Spark 的数据本地性有哪几种,分别表示什么?

  • 任务六:请简述Spark 中共享变量的基本原理和用途。

  • 任务七:请简述Flink 资源管理中Task Slot 的概念。

 

任务一:请描述HBase 的rowkey 设计原则。

任务描述

请简要描述HBase 的rowkey 的重要性并说明在设计rowkey 时应遵循哪些原则,将内容编写至客户端桌面【Release\模块F 提交结果.docx】中对应的任务序号下。

参考答案:

  1. Rowkey的唯一原则

必须在设计上保证其唯一性。由于在HBase中数据存储是Key-Value形式,若HBase中同一表插入相同Rowkey,则原先的数据会被覆盖掉(如果表的version设置为1的话),所以务必保证Rowkey的唯一性。

  1. Rowkey的排序原则

HBase的Rowkey是按照ASCII有序设计的,我们在设计Rowkey时要充分利用这点。比如视频网站上对影片《泰坦尼克号》的弹幕信息,这个弹幕是按照时间倒排序展示视频里,这个时候我们设计的Rowkey要和时间顺序相关。可以使用”Long.MAX_VALUE – 弹幕发表时间”的 long 值作为 Rowkey 的前缀。

  1. Rowkey的散列原则

我们设计的Rowkey应均匀的分布在各个HBase节点上。拿常见的时间戳举例,假如Rowkey是按系统时间戳的方式递增,Rowkey的第一部分如果是时间戳信息的话将造成所有新数据都在一个RegionServer上堆积的热点现象,也就是通常说的Region热点问题, 热点发生在大量的client直接访问集中在个别RegionServer上(访问可能是读,写或者其他操作),导致单个RegionServer机器自身负载过高,引起性能下降甚至Region不可用,常见的是发生jvm full gc或者显示region too busy异常情况,当然这也会影响同一个RegionServer上的其他Region。

为了防止数据热点,可在设计Rowkey时采用如下几种有效措施:

(1)加盐。这里所说的加盐不是密码学中的加盐,而是在rowkey的前面增加随机数,具体就是给rowkey分配一个随机前缀以使得它和之前的rowkey的开头不同。分配的前缀种类数量应该和你想使用数据分散到不同的region的数量一致。加盐之后的rowkey就会根据随机生成的前缀分散到各个region上,以避免热点。

(2)哈希。哈希会使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是可以预测的。使用确定的哈希可以让客户端重构完整的rowkey,可以使用get操作准确获取某一个行数据。

(3)反转。第三种防止热点的方法时反转固定长度或者数字格式的rowkey。这样可以使得rowkey中经常改变的部分(最没有意义的部分)放在前面。这样可以有效的随机rowkey,但是牺牲了rowkey的有序性。反转rowkey的例子以手机号为rowkey,可以将手机号反转后的字符串作为rowkey,这样的就避免了以手机号那样比较固定开头导致热点问题。

(4)时间戳反转。一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为rowkey的一部分对这个问题十分有用,可以用 Long.Max_Value – timestamp 追加到key的末尾,例如 [key][reverse_timestamp] , [key] 的最新值可以通过scan [key]获得[key]的第一条记录,因为HBase中rowkey是有序的,第一条记录是最后录入的数据。比如需要保存一个用户的操作记录,按照操作时间倒序排序,在设计rowkey的时候,可以这样设计:[userId反转][Long.Max_Value – timestamp],在查询用户的所有操作记录数据的时候,直接指定反转后的userId,startRow是[userId反转][000000000000],stopRow是[userId反转][Long.Max_Value – timestamp]。如果需要查询某段时间的操作记录,startRow是[user反转][Long.Max_Value – 起始时间],stopRow是[userId反转][Long.Max_Value – 结束时间]。

  1. Rowkey的长度原则

Rowkey是一个二进制,Rowkey的长度被很多开发者建议说设计在10~100个字节,建议是越短越好。原因有两点:

  • 其一是HBase的持久化文件HFile是按照KeyValue存储的,如果Rowkey过长比如500个字节,1000万列数据仅Rowkey就要占用500*1000万=50亿个字节,将近1G数据,这会极大影响HFile的存储效率;

  • 其二是MemStore缓存部分数据到内存,如果Rowkey字段过长内存的有效利用率会降低,系统无法缓存更多的数据,这会降低检索效率;

需要指出的是不仅Rowkey的长度是越短越好,而且列族名、列名等尽量使用短名字,因为HBase属于列式数据库,这些名字都是会写入到HBase的持久化文件HFile中去,过长的Rowkey、列族、列名都会导致整体的存储量成倍增加。

任务二:ClickHouse 有哪些表引擎?列举四种并简要描述。

任务描述

ClickHouse 有哪些表引擎?列举四种并简要描述。将内容编写至客户端桌面【Release\模块F 提交结果.docx】中对应的任务序号下。

参考答案:

表引擎是ClickHouse设计实现中的一大特色。表引擎决定了:

  • 数据存储和读取的位置

  • 支持哪些查询方式

  • 能否并发式访问数据

  • 能不能使用索引

  • 是否可以执行多线程请求

  • 数据复制使用的参数

ClickHouse拥有庞大的表引擎体系,包括MergeTree系列引擎、日志(Log)引擎、集成(Integrations)表引擎和特殊(Special)表引擎共4大类20多种。

我这里列举其中四种表引擎,并进行简要描述。

1)MergeTree

MergeTree表引擎用于插入极大量的数据到一张表中,数据以数据片段的形式一个接着一个的快速写入,数据片段按照一定的规则进行合并。

它适用于高负载任务,支持大数据量的快速写入并进行后续的数据处理,通用程度高且功能强大。它的特点是支持数据副本、分区、数据采样等特性。

2)Log

Log表引擎支持并发读取数据文件,每个列会单独存储在一个独立文件中,查询性能比较好。

它适用于快速写入小表(1百万行左右的表)并读取全部数据的场景。它的特点包括:数据被追加写入磁盘中;不支持delete、update; 不支持索引;不支持原子性写;insert会阻塞select操作。

3)Kafka

Kafka表引擎属于集成表引擎,用于将Kafka Topic中的数据直接导入到数据库ClickHouse。

它适用于将外部数据导入到数据库ClickHouse中,或者在数据库ClickHouse中直接使用外部数据源。

4)Memory

Memory表引擎将数据存储在内存中,重启后会导致数据丢失。查询性能极好,适合于对于数据持久性没有要求的1亿以下的小表。在云数据库ClickHouse中,通常用来做临时表。

它适用于特定的功能场景。

任务三:对于分组排序的理解。

任务描述

请问Hive SQL 有哪三种分组排序,他们各自的特点是什么?将内容编写至对应报告中将内容编写至客户端桌面【Release\模块F 提交结果.docx】中对应的任务序号下。

参考答案:

hive中可用于分组排序的函数主要有:row_number,rank,dense_rank,它们分别有不同的特点。

  • (1) row_number:排序时给每一行分配唯一的顺序,相同行顺序也不同。

  • (2) rank:相同行会分配相同的顺序,但是接下来会跳跃排序。

  • (3) dense_rank:为相同行分配同样的顺序,但是接下来的顺序也是连续的,不是跳跃的。

任务四:Kafka 中的数据如何保证不丢失?

任务描述

在任务D 中使用到了Kafka,将内容编写至客户端桌面【Release\模块F 提交结果.docx】中对应的任务序号下。

参考答案:

Kafka 的整个架构非常简洁,是分布式的架构,主要由 Producer、Broker、Consumer 三部分组成。一条消息从产生,到发送到kafka保存,到被取出消费,会有多个场景和流程阶段,因此剖析丢失场景会从 Producer、Broker、Consumer 这三部分入手来剖析。

1)生产者数据的不丢失

Kafka的ack机制:在Kafka发送数据的时候,每次发送消息都会有一个确认反馈机制,确保消息正常的能够被收到,其中状态有0、1、-1。

如果是同步模式:ack机制能够保证数据的不丢失,如果ack设置为0,风险很大,一般不建议设置为0。即使设置为1,也会随着leader宕机丢失数据。

producer.type=sync 
request.required.acks=1

如果是异步模式:也会考虑ack的状态,除此之外,异步模式下的有个buffer,通过buffer来进行控制数据的发送。有两个值来进行控制:时间阈值与消息的数量阈值。如果buffer满了数据还没有发送出去,有个选项是配置是否立即清空buffer。可以设置为-1,永久阻塞,也就数据不再生产。异步模式下,即使设置为-1。也可能因为程序员的不科学操作,操作数据丢失,比如kill -9,但这是特别的例外情况。

producer.type=async
request.required.acks=1
queue.buffering.max.ms=5000
queue.buffering.max.messages=10000
queue.enqueue.timeout.ms=-1
batch.num.messages=200

结论:producer有丢数据的可能,但是可以通过配置保证消息的不丢失。

2)消费者数据的不丢失

通过offset commit 来保证数据的不丢失,Kafka自己记录了每次消费的offset数值,下次继续消费的时候,会接着上次的offset进行消费。

而offset的信息在Kafka0.8版本之前保存在Zookeeper中,在0.8版本之后保存到topic中,即使消费者在运行过程中挂掉了,再次启动的时候会找到offset的值,找到之前消费消息的位置,接着消费,由于 offset的信息写入的时候并不是每条消息消费完成后都写入的,所以这种情况有可能会造成重复消费,但是不会丢失消息。

唯一例外的情况是,我们在程序中给原本做不同功能的两个consumer组设置KafkaSpoutConfig.bulider.setGroupid的时候设置成了一样的groupid,这种情况会导致这两个组共享同一份数据,就会产生组A消费partition1、partition2中的消息,组B消费partition3的消息,这样每个组消费的消息都会丢失,都是不完整的。 为了保证每个组都独享一份消息数据,groupid一定不要重复才行。

3)Kafka集群中的broker的数据不丢失

每个broker中的partition我们一般都会设置有replication(副本)的个数,生产者写入的时候首先根据分发策略(有partition按partition,有key按key,都没有轮询)写入到leader中,follower(副本)再跟leader同步数据,这样有了备份,也可以保证消息数据的不丢失。

任务五:Spark 的数据本地性有哪几种,分别表示什么?

任务描述

在任务B 与任务C 中使用到了Spark,其中有些JOB 运行较慢,有些较快,一部分原因与数据位置和计算位置相关,其数据本地性可以在SparkUI 中查看到。请问Spark 的数据本地性有哪几种(英文)?分别表示的含义是什么(中文)?将内容编写至客户端桌面【Release\模块F 提交结果.docx】中对应的任务序号下。

参考答案:

大数据中有一个很有名的概念就是“移动数据不如移动计算”,之所以有数据本地性就是因为数据在网络中传输会有不小的I/O消耗,如果能够想办法尽量减少这个I/O消耗就能够提升效率。那么如何减少I/O消耗呢,当然是尽量不让数据在网络上传输,即使无法避免数据在网络上传输,也要尽量缩短传输距离,这个数据需要传输多远的距离(实际意味着数据传输的代价)就是数据本地性,数据本地性根据传输距离分为几个级别,不在网络上传输肯定是最好的级别,其它级别划分依据传输距离越远级别越低,Spark在分配任务的时候会考虑到数据本地性,优先将任务分配给数据本地性最好的Executor执行。

数据本地性共分为五个级别:

  1. PROCESS_LOCAL:顾名思义,要处理的数据就在同一个本地进程中,即数据和Task在同一个Executor JVM中,这种情况就是RDD的数据在之前就已经被缓存过了,因为BlockManager是以Executor为单位的,所以只要Task所需要的Block在所属的Executor的BlockManager上已经被缓存,这个数据本地性就是PROCESS_LOCAL,这种是最好的locality,这种情况下数据不需要在网络中传输。

  2. NODE_LOCAL:数据在同一台节点上,但是并不不在同一个jvm中,比如数据在同一台节点上的另外一个Executor上,速度要比PROCESS_LOCAL略慢。还有一种情况是读取HDFS的块就在当前节点上,数据本地性也是NODE_LOCAL。

  3. NO_PREF:数据从哪里访问都一样,表示数据本地性无意义,看起来很奇怪,其实指的是从MySQL、MongoDB之类的数据源读取数据。

  4. RACK_LOCAL:数据在同一机架上的其它节点,需要经过网络传输,速度要比NODE_LOCAL慢。

  5. ANY:数据在其它更远的网络上,甚至都不在同一个机架上,比RACK_LOCAL更慢,一般情况下不会出现这种级别,万一出现了可能是有什么异常需要排查下原因。

任务六:请简述Spark 中共享变量的基本原理和用途。

任务描述

请简述Spark 中共享变量的基本原理和用途, 将内容编写至客户端桌面【Release\模块F 提交结果.docx】中对应的任务序号下。

参考答案:

Spark中共享变量包括广播变量和累加器。

1)累加器

累加器可以理解为一种分布式变量,其在driver端创建并赋初值,随着任务的分发在taskExecutor执行更新。

累加器只能在driver端读取,不能在executor端读取,在executor端可以通过add方法累加,不同executor的累加互不影响,executor是task级别的。

2)广播变量

用来分发较大的对象,以供一个或多个Spark操作符使用。

在多个并行操作中使用同一个变量时,Spark会为每个任务分别发送。对应闭包中某些变量,会随着task任务的分发而分发,因为闭包数据以task为单位发送,每个任务包含闭包数据。例如,如果有1000个任务,则会被分发1000次,且被缓存1000次,这将造成较多的冗余数据,过多消耗内存,影响作业运行性能。

Spark使用广播在task分发之前将变量发送到executor,将闭包的数保存到Executor的内存中(只读)。同一个executor的多个task共享这个变量,降低了任务分发时的消耗和内存消耗。Executor 即相当于一个JVM进程,启动时会自动分配内存,将任务中的闭包数据放置在Executor的内存中达到共享目的。

rdd不能被广播,如果要广播rdd,需要使用collect算子将数据汇总到driver,然后广播数据。

executor不能修改广播数据,广播数据是只读的。

3)用途

累加器可以用在诸如统计全局次数之类的场景。

广播变量用在优化shuffle、提升性能的场景。

任务七:请简述Flink 资源管理中Task Slot 的概念。

任务描述

请简述你对Task Slot 的理解,将内容编写至客户端桌面【Release\模块F 提交结果.docx】中对应的任务序号下。

参考答案:

在Flink架构中,TaskManager是实际负责执行计算的Worker。TaskManager是一个JVM进程,并会以独立的线程来执行一个task或多个subtask。

为了控制一个TaskManager能接受多少个task,Flink提出了Task Slot的概念。TaskManager中最细粒度的资源是Task slot,代表了一个固定大小的资源子集。简单的说,TaskManager会将自己节点上管理的资源分为不同的Slot(固定大小的资源子集)。这样就避免了不同Job的Task互相竞争内存资源。

通过调整task slot的数量,用户可以定义task之间是如何相互隔离的。每个TaskManager有一个slot,也就意味着每个task运行在独立的JVM中。每个TaskManager有多个slot的话,也就是说多个task运行在同一个JVM中。

而在同一个JVM进程中的task,可以共享TCP连接(基于多路复用)和心跳消息,可以减少数据的网络传输,也能共享一些数据结构,一定程度上减少了每个task的消耗。 每个slot可以接受单个task,也可以接受多个连续task组成的pipeline。

但是需要注意的是,Slot只会做内存的隔离。没有做CPU的隔离。

© 版权声明
THE END
喜欢就支持一下吧
点赞295赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

夸夸
夸夸
还有吗!没看够!
取消
昵称表情代码图片

    暂无评论内容