大数据开发面试问题总结(很多都是问的chatgpt,望指正)

SQL调优有哪些?

  1. 通过建立索引对查询进行优化
  2. 对查询进行优化,应尽量避免全表扫描
    • 应尽量避免在 where 子句中使用!=或<>操作符
    • 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
    • 应尽量避免在 where 子句中对字段进行 null值判断,否则将导致引擎放弃使用索引而进行全表扫描
    • 尽量避免在 where 子句中使用 or 来连接条件
    • in 和 not in 也要慎用,否则会导致全表扫描

读写分离,分库建表 explain sql分析 sql 索引的使用和优化等方面

TailDir为什么可以断点重传?

tail-dir 使用flume内置json文件记录读取位置,实现了断点续传,避免了flume宕机后重启的脏数据问题。

Linux什么指令可以监听文件?

tail命令可以输出文件的尾部内容linux监视文件命令,默认情况下它显示文件的最后十行。它常用来动态监视文件的尾部内容的增长情况,比如用来监视日志文件的变化。

Kafka 都有哪些特点?

  1. 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition, consumer group 对partition进行consume操作。
  2. 可扩展性:kafka集群支持热扩展
  3. 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失
  4. 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)
  5. 高并发:支持数千个客户端同时读写。

请简述下你在哪些场景下会选择 Kafka?

  1. 日志收集:一个公司可以用Kafka可以收集各种服务的log,通过kafka以统一接口服务的方式开放给各种consumer,例如hadoop、HBase、Solr等。
  2. 消息系统:解耦和生产者和消费者、缓存消息等。
  3. 用户活动跟踪:Kafka经常被用来记录web用户或者app用户的各种活动,如浏览网页、搜索、点击等活动,这些活动信息被各个服务器发布到kafka的topic中,然后订阅者通过订阅这些topic来做实时的监控分析,或者装载到hadoop、数据仓库中做离线分析和挖掘。
  4. 运营指标:Kafka也经常用来记录运营监控数据。包括收集各种分布式应用的数据,生产各种操作的集中反馈,比如报警和报告。
  5. 流式处理:比如spark streaming和 Flink

Kafka 的设计架构?

Kafka 架构分为以下几个部分:

  1. Producer :消息生产者,就是向 kafka broker 发消息的客户端。
  2. Consumer :消息消费者,向 kafka broker 取消息的客户端。
  3. Topic :可以理解为一个队列,一个 Topic 又分为一个或多个分区,
  4. Consumer Group:这是 kafka 用来实现一个 topic 消息的广播(发给所有的 consumer)和单播(发给任意一个 consumer)的手段。一个 topic 可以有多个 Consumer Group。
  5. Broker :一台 kafka 服务器就是一个 broker。一个集群由多个 broker 组成。一个 broker 可以容纳多个 topic。
  6. Partition:为了实现扩展性,一个非常大的 topic 可以分布到多个 broker上,每个 partition 是一个有序的队列。partition 中的每条消息都会被分配一个有序的id(offset)。将消息发给 consumer,kafka 只保证按一个 partition 中的消息的顺序,不保证一个 topic 的整体(多个 partition 间)的顺序。
  7. Offset:kafka 的存储文件都是按照 offset.kafka 来命名,用 offset 做名字的好处是方便查找。例如你想找位于 2049 的位置,只要找到 2048.kafka 的文件即可。当然 the first offset 就是 00000000000.kafka。

Kafka 分区的目的?

分区对于 Kafka 集群的好处是:实现负载均衡。分区对于消费者来说,可以提高并发度,提高效率。

Kafka 是如何做到消息的有序性?

kafka 中的每个 partition 中的消息在写入时都是有序的,而且单独一个 partition 只能由一个消费者去消费,可以在里面保证消息的顺序性。但是分区之间的消息是不保证有序的。

Kafka Producer 的执行过程?

1,Producer生产消息 --> 2,从Zookeeper找到Partition的Leader --> 3,推送消息 --> 4,通过ISR列表通知给Follower --> 5, Follower从Leader拉取消息,并发送ack --> 6,Leader收到所有副本的ack,更新Offset,并向Producer发送ack,表示消息写入成功。

首先,Kafka会在ZooKeeper上查找该分区的所有副本中的Log End Offset(LEO)最大的那个Broker,也就是说,该Broker的副本中保存的数据最新。然后,将该Broker选举为该分区的新Leader节点。 如果有多个副本的LEO相等,则Kafka会优先选择在ISR(In-Sync Replicas)中的副本,ISR中的副本与Leader节点保持同步,因此可以保证数据的一致性。如果没有ISR中的副本,则选择所有副本中的第一个在线的Broker作为新的Leader节点。 总之,Kafka在重新选举新的Leader节点时,会优先选择最新的数据副本,并尽可能地保证数据的一致性。

kafka如何保证数据的一致性?

Kafka保证数据一致性的方式有很多,其中一个是通过使用分布式副本集。分布式副本集是一组Kafka服务器,它们在同一个集群中,共同维护一个副本。当消息被写入Kafka时,它会被复制到多个副本中,从而保证数据的完整性。如果其中一个副本失效,另一个副本可以接管它的工作。这样,Kafka就可以保证数据的一致性。

MySQL的存储引擎有哪些?

  1. InnoDB存储引擎
  2. MyISAM存储引擎
  3. Memory存储引擎

Innodb的索引是怎么实现的?

  • InnoDB使用的是聚簇索引,将主键组织到一棵B+树中,而行数据就储存在叶子节点上,若使用"where id = 14"这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。若对Name列进行条件搜索,则需要两个步骤:第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键。第二步使用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据。
  • MyISM使用的是非聚簇索引,非聚簇索引的两棵B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树。

HDFS的架构是怎样的?

  1. NameNode(nn):就是Master,它是一个主管、管理者。
    1. 管理HDFS的名称空间;
    2. 配置副本策略;
    3. 管理数据块(Block)映射信息;
    4. 处理客户端读写请求。
  2. DataNode:就是Slave。NameNode下达命令,DataNode执行实际的操作。
    1. 存储实际的数据块;
    2. 执行数据块的读/写操作。
  3. Client:就是客户端。
    1. 文件切分。文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传;
    2. 与NameNode交互,获取文件的位置信息;
    3. 与DataNode交互,读取或者写入数据;
    4. Client提供一些命令来管理HDFS,比如NameNode格式化;
    5. Client可以通过一些命令来访问HDFS,比如对HDFS增删查改操作;
  4. Secondary NameNode:并非NameNode的热备。当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务。
    1. 辅助NameNode,分担其工作量,比如定期合并Fsimage和Edits,并推送给NameNode ;
    2. 在紧急情况下,可辅助恢复NameNode。

NN和2NN有什么区别?

2NN与NN的区别只缺少了一个正在编辑的日志文件

HDFS的HA怎么实现?

HDFS的NameNode为单一节点,为HDFS提供对外统一服务,这说明如果NameNode因为某些原因掉线了,那整个HDFS集群就会瘫痪。为了防止这种情况在生产环境中出现,就引入了高可用(HA)模式。 在HA模式中,一般由两个NameNode组成,一个是处于激活(Active)状态,另一个就处于待命(Standby)状态,处于激活状态的NameNode对外提供统一服务,而待命状态的NameNode则不对外提供服务,同时及时同步激活状态的NameNode。当激活的NameNode掉线了,待命的NameNode就马上切换状态,变成Active。

HDFS 的读和写?

如何读 流程图 图片上传失败,请重新上传

  1. 当HDFS客户端需要读取一个数据文件的时候,首先会调用FileSystem的open()方法获取一个dfs对象(DistributedFileSystem)。
  2. DFS通过RPC从NameNode中获取文件第一批块的位置信息后,会返回一个FsDataInputStream对象。
  3. 返回的FsDataInputStream会被封装成DFSInputStream(分布式文件系统输入流),里面提供了管理NameNode和DataNode输入流的方法。当客户端调用read()方法的时候,DFSInputStream就会找出离客户端最近的DataNode并连接。
  4. 找出DataNode后就会开始读取对应的数据块,数据开始流向客户端。
  5. 当第一个块读取完成后,就会关闭第一个块指向的DataNode连接,然后接着读下一个块。
  6. 当第一批块读取完成后,就会向NameNode获取下一批块的位置信息,然后继续读取。
  7. 当所有块都读取完成后,就会关闭所有的流。

当然,在实际情况下,想一直那么顺利的传输数据是不可能的,如果在读取数据的时候,DataNode和DFSInputStream发生异常的时候,那么DFSInputStream会尝试获取当前读取块第二近的DataNode节点,并会记录哪个DataNode发生错误,后面涉及到该出事DataNode读取的时候,就会自动跳过。 如果读取的块已经坏了,那么就会将这种情况汇报给NameNode,并且从其他DataNode读取该块数据。

如何写 看下面流程图: 图片上传失败,请重新上传

  1. 和读操作一样,首先通过FileSystem获取一个DFS对象,并通过DFS对象来的create()方法来创建一个新的文件。
  2. DFS通过RPC调用NameNode去创建一个新文件,NameNode在创建前会做一些额外的校验,如文件是否已经存在、客户端是否有权限创建文件等等。
  3. 前面的操作完成后,DFS会返回一个FsDataOutputStream对象,同样,FsDataOutputStream会被封装成DFSOutputStream(分布式文件系统输入流),同样,DFSOutputStream也提供了协调DataNode和NodeNode的方法。
  4. 当客户端开始写数据的时候,就会将数据块切分成一个个数据包,然后将这些数据包排成一条数据队列。
  5. 多个DataNode组成一条数据管道,当开始传输的时候,首先第一个数据包会传到数据管道的第一个DataNode,当第一个DataNode收到后会将这个数据包传给下一个DataNode。
  6. DFSOutputStream除了数据管道外,还维护着另一个队列:响应队列,这个队列也是由数据包组成的,当DataNode收到数据块的数据包后,就会返回一个响应数据包,当管道中所有的DataNode都收到响应数据包的时候,响应队列才把对应的数据包移除。
  7. 客户端在写操作完成后,就会调用close()关闭输出流。
  8. 同时,客户端会通知NameNode把文件标记为已完成,然后NameNode会把文件写入成功的结果返回给客户端。这时整个写操作才完成。

当然,凡是涉及到节点之前的通信,都大概率会出现一些奇怪的问题,例如网络不可用啊、通信节点掉线啊等等,对于这种情况,写操作要比读操作要复杂一点,如果在写操作过程中其中一个DataNode发生错误,那么就有下面几个步骤来处理:

  1. 管道关闭。
  2. 正常的DataNode正在写的块会由一个新的ID,并且这个ID会汇报给NameNode,而失败的DataNode上发生错误的块就会在下次上报心跳的时候删掉。
  3. 失败的DataNode会被从管道中移除,而块中剩下的数据包会继续写入到管道里其他的DataNode上。
  4. NameNode同时会标记这个块的副本数量少于指定值,那么会在后面将这个块的副本在其他DataNode上创建。

HBase是列式存储吗?行式存储和列式存储有什么区别?

  1. 在数据写入上的对比
    1. 行存储的写入是一次完成。如果这种写入建立在操作系统的文件系统上,可以保证写入过程的成功或者失败,数据的完整性因此可以确定。
    2. 列存储由于需要把一行记录拆分成单列保存,写入次数明显比行存储多(意味着磁头调度次数多,而磁头调度是需要时间的,一般在1ms~10ms),再加上磁头需要在盘片上移动和定位花费的时间,实际时间消耗会更大。所以,行存储在写入上占有很大的优势。
    3. 还有数据修改,这实际也是一次写入过程。不同的是,数据修改是对磁盘上的记录做删除标记。行存储是在指定位置写入一次,列存储是将磁盘定位到多个列上分别写入,这个过程仍是行存储的列数倍。所以,数据修改也是以行存储占优。
  2. 在数据读取上的对比
    1. 数据读取时,行存储通常将一行数据完全读出,如果只需要其中几列数据的情况,就会存在冗余列,出于缩短处理时间的考量,消除冗余列的过程通常是在内存中进行的。
    2. 列存储每次读取的数据是集合的一段或者全部,不存在冗余性问题。
    3. 两种存储的数据分布。由于列存储的每一列数据类型是同质的,不存在二义性问题。比如说某列数据类型为整型(int),那么它的数据集合一定是整型数据。这种情况使数据解析变得十分容易。相比之下,行存储则要复杂得多,因为在一行记录中保存了多种类型的数据,数据解析需要在多种数据类型之间频繁转换,这个操作很消耗CPU,增加了解析的时间。所以,列存储的解析过程更有利于分析大数据

显而易见,两种存储格式都有各自的优缺点:

  • 行存储的写入是一次性完成,消耗的时间比列存储少,并且能够保证数据的完整性,缺点是数据读取过程中会产生冗余数据,如果只有少量数据,此影响可以忽略;数量大可能会影响到数据的处理效率。
  • 列存储在写入效率、保证数据完整性上都不如行存储,它的优势是在读取过程,不会产生冗余数据,这对数据完整性要求不高的大数据处理领域,比如互联网,犹为重要。

NN和2NN有什么区别?

NN和2NN的区别在于2NN是一个辅助节点,用于帮助NN进行元数据的备份和恢复。在传统的HDFS架构中,NN是单点故障,如果NN发生故障,整个文件系统将不可用。通过引入2NN并将元数据的备份放在2NN上,可以提供高可用性和容错能力。

HDFS的HA怎么实现?

HDFS的高可用性(HA)是通过在集群中启用多个NN来实现的。在这种配置下,会有一个Active NN和多个Standby NN运行,Active NN处理客户端请求并维护元数据,Standby NN则跟踪Active NN的操作并保持与其同步。如果Active NN失效,Standby NN可以快速接管并继续提供服务,以实现无缝的故障切换和高可用性。

HBase是列式存储吗?行式存储和列式存储有什么区别?

HBase是一种列式存储数据库。传统的行式存储数据库以行为单位存储数据,而列式存储数据库将数据以列为单位进行存储。这种存储方式在分析和聚合大量数据时表现出色,因为可以只读取需要的列数据,而不需要读取整行数据。此外,列式存储数据库还支持更高的压缩比和更快的查询速度。

介绍一下HBase的HA?

HBase的高可用性(HA)是通过在集群中启用多个RegionServer来实现的。每个RegionServer负责管理一个或多个Region(数据表的分片),而Master节点负责协调和监控整个集群。如果Master节点发生故障,可以通过选举新的Master节点来继续提供服务。同时,HBase还支持ZooKeeper来进行故障检测和集群协调。

项目里Hive用的是内部表还是外部表?它们的区别是什么?并说明为什么用外部表?

在项目中,使用的是Hive的内部表。内部表是Hive自己管理的表,其元数据和数据都存储在Hive的默认存储路径中。而外部表是在Hive中引用外部HDFS或本地文件系统上的数据,其元数据存储在Hive的默认存储路径,而数据存储在外部数据路径中。外部表可以使数据与Hive解耦,可以方便地在不同Hive实例之间共享数据,也可以方便地与其他数据处理工具集成。

介绍一下Hive数据倾斜?

Hive数据倾斜指在数据处理过程中,某些数据分布不均匀,导致部分计算任务消耗的时间远远超过其他任务的现象。这会导致整个任务的执行时间延长。针对此问题,可以采取一些优化措施,如使用MapJoin代替常规Join,增加数据的分区等。

介绍一下Hive的UDF函数?

Hive的UDF(User-Defined Function)函数是用户自定义的函数,用于在Hive中进行数据处理和计算。用户可以使用Java或其他编程语言编写UDF函数,并将其注册到Hive中,然后通过Hive的查询语句调用这些函数。UDF函数可以扩展Hive的功能,以满足特定的数据处理需求。

有没了解过开窗函数?介绍一下

开窗函数(Window Function)是一种在关系型数据库中进行分析函数计算的功能。它可以对查询结果的某个窗口进行聚合、排序、筛选等操作,并生成与原始查询结果相匹配的结果集。开窗函数通常与OVER子句一起使用,以指定窗口的范围和排序方式。

MySQL的存储引擎有哪些?Innodb的索引是怎么实现的?为什么用B+树?

MySQL的存储引擎有多种,常见的包括InnoDB、MyISAM等。其中InnoDB是一种事务安全的存储引擎,支持行级锁和MVCC,并提供了更好的并发性能和数据完整性。InnoDB的索引是通过B+树来实现的,B+树是一种多叉树结构,可以实现快速的查找和范围查询,并且对数据的插入和删除操作有较好的性能。

索引的作用

索引的作用是提高数据库的查询性能。通过在数据库表中创建索引,可以将数据按照特定的列或多列进行排序和组织,从而加快数据的查找速度。索引可以减少磁盘I/O和减少查询的数据扫描量,提高查询效率。

内连接是什么?

内连接(Inner Join)是一种数据库查询操作,用于获取两个表中共有的数据记录。内连接根据两个表中的连接条件,将满足条件的记录合并成一条记录,并返回结果。只有在连接条件满足的情况下,内连接才会返回结果。

有了解MVCC吗?介绍一下

MVCC(Multi-Version Concurrency Control)是一种并发控制机制,用于在并发读写场景中保证数据库的一致性和隔离性。MVCC通过给每个事务分配唯一的事务ID,并为每个修改操作创建一个新版本的数据,从而实现并发访问的数据可见性和一致性。在读操作中,可以根据事务ID和版本号来选择合适的数据版本,从而保证不会读取到由其他事务修改但未提交的数据。

SQL调优有哪些?

SQL调优主要包括以下几个方面:优化查询语句、适当创建索引、合理设计数据库表结构、适时进行表分区、优化数据库配置参数、适当缓存查询结果、使用批量操作等。

项目里的Flume是怎么用的?

项目中的Flume可以用来实时收集、聚合和传输大量的日志数据,并将其传输到其他的数据存储系统(如Hadoop、HBase等)。可以通过配置Flume的source(源)和sink(目标)来定义数据的输入和输出。

TailDir为什么可以断点重传?

TailDir可以监听指定文件夹中的文件变化情况,并将新增的文件或者文件中新增的数据传输到指定的目标。它实现断点重传的方式是通过记录每个文件的文件偏移量,当发生中断时,可以根据文件偏移量继续读取文件,从而实现断点重传。

Linux什么指令可以监听文件?

在Linux中,可以使用tail -f命令来监听文件的变化,并实时输出新增的内容。

Kafka的基本架构?

Kafka的基本架构由多个组件组成,包括Producer、Broker、ZooKeeper、Consumer等。Producer负责将数据发送到Kafka集群,Broker负责存储消息并处理消息的分发,ZooKeeper用于协调和管理Kafka集群的状态,Consumer负责从Kafka中读取数据。

Kafka的partition副本写数据是怎么写的?

Kafka的partition副本写数据是采用领导者-追随者模式。每个partition都有一个leader和多个follower,当Producer发送消息时,会将消息发送给对应partition的leader,leader将消息写入自己的日志,并同步给所有follower。一旦leader确认消息已写入多数follower的日志,就返回成功给Producer。follower会周期性地从leader拉取新的数据,并将其写入自己的日志。

Kafka副本的leader是怎么选出来的?

Kafka的副本的leader是通过选举机制选出来的。当leader出现故障或下线时,Kafka会从副本中选择一个新的leader,选举方式通常基于副本的优先级和可用性等因素进行选择。

有没有了解Kafka的架构设计?

Kafka的架构设计是基于分布式、高可用、高吞吐量和容错性。它采用发布-订阅消息模型,通过分区和副本机制实现高吞吐量和可靠性,同时借助ZooKeeper实现集群的管理和协调。

Java的有哪些集合?详细介绍一下实现过程?

Java中常见的集合包括List、Set和Map等。其中,List实现有ArrayList和LinkedList,Set实现有HashSet和TreeSet,Map实现有HashMap和TreeMap等。不同的集合实现方式有所不同,可以根据具体的场景和需求选择适合的集合。

ArrayList是怎么实现的?LinkedList是怎么实现的?ArrayList与LinkedList有什么区别?

ArrayList是通过数组实现的,它在内存中是一块连续的空间。LinkedList则是通过链表实现的,每个节点保存了当前元素的值以及指向前一个节点和后一个节点的引用。ArrayList适合随机访问和获取元素,而LinkedList适合插入、删除和遍历元素。

怎么声明字符串(String)?字符串new出来保存到哪里?如果是字符串常量保存在哪?

字符串可以通过直接赋值给变量来声明,例如String str = "Hello";。字符串常量保存在字符串常量池中,而通过new操作创建的字符串对象保存在堆内存中。

StringBuffer和StringBuilder有什么区别?

StringBuffer和StringBuilder都是用来处理可变的字符串,但是StringBuffer是线程安全的,而StringBuilder是非线程安全的。在多线程环境下,如果需要对字符串进行修改操作,推荐使用StringBuffer,而在单线程环境下,使用StringBuilder可以获得更好的性能。

Java里除了Synconized,还有什么加锁方式?

除了synchronized关键字,Java中还有其他的加锁方式,如ReentrantLock、Lock接口、Atomic类等。这些机制可以更灵活地控制锁的获取和释放,并提供更多的功能。

介绍一下垃圾回收机制。

Java的垃圾回收机制是通过垃圾收集器来回收废弃对象所占用的内存空间。垃圾收集器会定期进行垃圾回收,找出不再被引用的对象,将它们所占用的内存空间释放出来,以供其他对象使用。

具体的垃圾回收器有哪些?

具体的垃圾回收器有很多种,例如串行垃圾回收器(Serial)、并行垃圾回收器(Parallel)、并发标记垃圾回收器(CMS)、G1垃圾回收器等。不同的垃圾回收器具有不同的特点和适用场景,可以根据具体的需求选择合适的垃圾回收器。

Flume的事务是怎样的?

Flume的事务是通过事务性存储器(TransactionChannel)实现的。当Flume接收到数据时,会将数据写入到事务内存中,并标记该事务为“正在进行中”,然后等待事务完成。一旦事务完成,数据会被提交到目标系统,如果事务失败,则数据会被回滚。

如何实现UDF?

UDF(User-Defined Function)是自定义函数,用于在SQL查询中扩展功能。可以通过继承现有的UDF类或实现UDF接口来实现UDF。实现UDF时,需要定义函数的输入和输出类型,然后实现对应的evaluate方法进行具体的逻辑处理。

UDF要成为永久函数怎么做?如果不加temperory,函数下次还能用吗?

要将UDF成为永久函数,需要使用CREATE FUNCTION语句将UDF注册到数据库中。如果不加temporary关键字创建函数,默认是永久函数,可以在下次会话中继续使用。

介绍一下UDTF?

UDTF(User-Defined Table Function)是自定义表函数,可以将一行输入转换为多行输出。UDTF需要实现TableFunction接口,并重写eval方法来处理输入数据。

Hive的窗口函数有了解过吗?

Hive的窗口函数是用于在分组数据上执行聚合操作的函数,可以通过OVER子句指定窗口的范围和排序方式。

开窗函数Over()中有没有orderby有什么区别?

开窗函数Over()中可以有orderby子句,用于指定窗口中数据的排序方式。如果没有指定orderby子句,则使用默认的排序方式,通常是按照输入数据的顺序进行排序。

Flink任务的并行度和内存怎么设置的?

Flink任务的并行度可以通过设置ExecutionConfig中的setParallelism()方法来进行设置,内存的分配可以在Flink的配置文件中进行设置。

Flink的TaskManager内存模型了解吗?

Flink的TaskManager内存模型包括堆内存、以及Off-heap和On-heap内存。堆内存主要用于存储数据和运行时信息,Off-heap内存用于存储Flink的元数据,On-heap内存用于执行堆外操作。

Flink 新旧版本之间的区别包括功能的增强、bug修复、性能优化等。

有没有了解过Flink的窗口函数?

Flink提供了丰富的窗口函数,如滚动窗口、滑动窗口、会话窗口等,可以根据具体的需求选择合适的窗口函数进行数据处理。

离线数仓做了什么工作?

离线数仓的工作包括数据抽取、数据清洗、数据转换、数据加载等。通过这些工作将原始数据转化成业务数据,供分析和决策使用。

数仓为什么要分层?

数仓要分层是为了更好地组织和管理数据。分层有助于提高查询和计算的效率,便于对不同层次的数据进行灵活的处理和管理,并能支撑多种分析场景。

实时数仓也要像离线数仓那样分层吗?

实时数仓也需要进行分层,但分层原则可能会有所不同,需要根据实时计算的要求进行设计。

开发数仓的过程中有哪些注意的点?优化的点?

在开发数仓的过程中,需要注意数据的准确性和一致性,保证数据质量;同时也要关注性能优化,如合理设置分区、选择合适的数据格式、合理设置压缩等。

拉链表的分区是怎么设置的?(一级分区、二级分区?)

拉链表的分区可以通过一级分区和二级分区来实现数据的分散存储。一级分区可以根据日期、地区等维度进行划分,二级分区可以根据具体的业务维度进行划分。

有哪些压缩方式?各有什么优缺点?

常见的压缩方式有Snappy、Gzip、LZO等。不同的压缩方式有不同的优缺点,如压缩比、压缩速度、解压速度等方面的差异。在选择压缩方式时需要根据具体的场景和需求进行评估和选择。

HDFS的小文件过多会导致什么问题?怎么解决?

HDFS的小文件过多会导致存储效率低下、元数据开销大和数据读写性能下降等问题。通过合并小文件、设置合适的块大小、使用SequenceFile等方式可以解决小文件问题。

MapReduce的原理:

MapReduce是一种分布式计算模型,包含两个阶段:Map和Reduce。Map阶段将输入数据拆分为若干片段并进行并行处理,生成一系列键值对。Reduce阶段对Map输出的键值对进行归并和聚合,最终得到最终的计算结果。MapReduce采用了数据本地性原则,借助分布式文件系统将数据移动到计算节点,减少数据的网络传输。

环形缓冲区为什么要反向?

环形缓冲区反向有助于减小跨页面访问的成本,提高数据访问的效率。由于CPU缓存的局部性原理,顺序访问的数据具有更高的缓存命中率,因此将数据反向存放可以增加数据的顺序性,提高缓存的效率。

Spark的原理:

Spark是一个快速而通用的集群计算系统,基于RDD(弹性分布式数据集)模型。Spark将计算任务划分为多个阶段,每个阶段包含若干个并行的任务。通过将计算过程中的数据保留在内存中,Spark能够实现较低的计算延迟和更高的吞吐量。Spark支持多种操作,如转换和动作,同时提供丰富的API和库,支持Scala、Java、Python和R等编程语言。

Spark、Flink的部署模式:

Spark和Flink都支持以下部署模式:

  • Standalone模式:在单机上运行Spark或Flink,方便开发和测试。
  • Local模式:在分布式环境中,将Spark或Flink的所有组件都运行在同一台机器上。
  • YARN模式:通过YARN资源管理器来分配和管理计算资源,支持任务的动态调度和资源隔离。
  • Mesos模式:通过Mesos资源管理器来分配和管理计算资源,也支持任务的动态调度和资源隔离。

YARN的角色和任务:

YARN(Yet Another Resource Negotiator)由以下角色组成:

  • ResourceManager:负责集群资源的分配和管理。
  • NodeManager:负责管理节点上的资源,包括任务的启动、监控和报告等。
  • ApplicationMaster:每个应用程序都有一个对应的ApplicationMaster,负责任务的协调和监管。
  • Container:YARN中的基本单位,用于封装资源(CPU、内存)和任务的运行环境。

YARN的调度器:

YARN支持多种调度器,包括:

  • CapacityScheduler:按照预定义的容量分配资源,支持多队列和资源配额功能。
  • FairScheduler:按照公平原则分配资源,每个应用程序都能获得公平的机会。
  • DominantResourceFairnessScheduler:基于优先级和资源需求的公平调度器。

Hive和HBase的区别:

Hive是一个建立在Hadoop上的数据仓库工具,提供类似于SQL的查询和数据分析能力。HBase是一个NoSQL数据库,基于Hadoop的HDFS存储数据。主要区别包括:

  • 数据模型:Hive是基于关系型数据模型,支持复杂的查询和数据分析,HBase是基于列族的数据模型,类似于Bigtable。
  • 查询语言:Hive使用类SQL语言(HiveQL)进行查询,HBase使用API操作数据。
  • 存储方式:Hive将数据存储在HDFS上,HBase在HDFS上构建了一层支持随机读写的索引结构。

Kafka的作用:

Kafka是一个高吞吐量的分布式消息系统,用于发布和订阅流式数据。在大规模数据处理场景下,Kafka可以扮演消息中间件的角色,实现不同组件之间的解耦和连接。它支持持久化、容错、并行处理和可伸缩性等特性,适用于高吞吐量的实时数据流处理。

Kafka的架构:

Kafka的架构包括以下组件:

  • Producer:数据的发布者,将数据发送到Kafka的Topic中。
  • Consumer:数据的消费者,从Kafka的Topic中读取和处理数据。
  • Topic:数据发送和接收的通道,逻辑上相当于一个消息队列。
  • Partition:Topic的分区,用于实现数据的并行处理和存储。
  • Broker:Kafka集群中的一台服务器,负责存储和复制数据。
  • ZooKeeper:Kafka使用ZooKeeper来管理集群的配置和状态信息。

Kafka消息积压的解决方案:

处理Kafka消息积压可以从以下方面入手:

  • 增加消费者的数量和并行度,提高消费速度。
  • 调整Kafka的配置,增加分区数和副本数,提高吞吐量和容错性。
  • 优化消费者的消费逻辑,减少消费逻辑的复杂度,提高处理效率。
  • 监控Kafka集群和消费进度,及时发现问题并进行调整。

Hive数据倾斜的原因和优化:

Hive数据倾斜主要是由于数据分布不均匀导致的,可能是某个特定的键值或组合的数据量过大,导致计算任务不均衡。优化的方法包括:

  • 调整分桶和分区策略,使得数据更加均匀地分布在各个桶和分区中。
  • 使用随机前缀或哈希分区,将数据分散存储和计算。
  • 使用扩展算子(例如LATERAL VIEW EXPLODE)对数据进行分拆,以减少特定键值或组合的数据量。
  • 调整并行度,通过增加或减少Reducer数量来均衡计算任务。

小文件问题可以使用以下方法进行处理:

  1. 合并小文件:可以使用Hadoop的SequenceFile格式来合并小文件,将多个小文件写入一个SequenceFile中,减少文件数量。
  2. 使用CombineInputFormat:使用CombineInputFormat可以将多个小文件合并成一个输入切片,减少任务数量。
  3. JVM重用:可以开启JVM重用机制,重用已经初始化的JVM来处理多个小文件,减少JVM启动和销毁的时间开销。

Hive支持的存储格式包括TextFile、SequenceFile、ORC和Parquet。

ORC和Parquet是两种优化的列式存储格式,它们的区别如下:

  1. 存储方式:ORC使用行组(Row Group)存储数据,每个行组包含多行数据,而Parquet使用列组(Column Chunk)存储数据,每个列组包含一个或多个列的数据。
  2. 压缩方式:ORC和Parquet都支持多种压缩方式,但ORC压缩率更高,适合存储超大表,而Parquet压缩速度更快,适合交互式查询。
  3. 数据编码:ORC使用了可变长度编码(Variable Length Encoding)和字典编码(Dictionary Encoding)来减小存储空间,而Parquet使用了位图编码和字典编码。
  4. 兼容性:ORC是Hive特有的存储格式,Parquet是一种开放的存储格式,被多个大数据处理框架支持,如Hive、Spark、Impala等。

常见的压缩格式包括gzip、bzip、snappy和lzo。

Hive的数据倾斜可以采取以下处理方法:

  1. 数据重分区:将倾斜的数据进行分区,将数据均匀分布到不同的分区中,避免数据倾斜。
  2. 使用随机前缀:对倾斜的键添加随机前缀,使倾斜的键均匀分布在不同的分区内。
  3. 聚合优化:对倾斜的数据进行预聚合,减少需要进行聚合操作的数据量。
  4. 键值对转化:将倾斜的数据转化为键值对进行处理,如将倾斜的join操作转化为map-side join。
  5. 动态调整资源:根据实际情况动态调整资源,如增加或减少任务的并行度,提高倾斜键的处理速度。

以上是处理Hive的数据倾斜的一些常见方法,具体的处理方式可以根据场景和需求进行选择。

分区和分桶的区别?

分区(Partition)是将数据按照某个特定的列分成多个不同的目录或文件存储,以便更高效地查询和管理数据。分桶(Bucket)是将数据按照哈希算法分成几个桶,每个桶中的数据大小可以不等,便于进行随机采样和均匀分布的操作。分区是根据列的值进行数据划分,而分桶是根据哈希算法对数据进行划分。

SQL提交到Hive的过程大致分为以下几个步骤:

  • 解析器将SQL语句解析成抽象语法树(AST)。
  • 语法分析器根据AST生成逻辑执行计划(Logical Plan)。
  • 将逻辑执行计划转化为物理执行计划(Physical Plan),并进行优化。
  • 生成MapReduce作业,将物理执行计划转化为一系列的MapReduce任务。
  • 提交MapReduce作业到集群中执行,并等待作业完成。

Hive方面的调优手段有:

  • 适当增加并行度和减少任务数量,以提高查询的执行效率。
  • 使用合适的存储格式,如ORC或Parquet,以减小存储空间并提高查询性能。
  • 合理定义分区和分桶,以避免全表扫描和提高查询速度。
  • 使用合适的索引,如位图索引或Bloom过滤器,以减少数据的扫描和过滤。
  • 使用动态分区插入和多行插入语句,以提高数据的导入速度。
  • 使用Map-side Join进行连接操作,以避免大表和大表之间的内存溢出问题。
  • 合理使用Join优化参数,如自动调整mapjoin的阈值等。

避免大表和大表之间的join内存溢出可以采用以下方法:

  • 采用Map-side Join:如果其中一个表可以小到可以进入内存,可以将其作为小表进行Map-side Join,避免将所有数据加载到内存中。
  • 调整Join操作的并行度:通过调整map端、reduce端并行度或启用合适的Join优化参数,可以减少内存消耗并提高Join操作的性能。
  • 调整内存参数:增加Map和Reduce任务的内存限制,如mapreduce.map.memory.mb和mapreduce.reduce.memory.mb,可以为Join操作提供更多的内存资源。

全量数据是指每次处理时需要处理所有的数据,而增量数据是指只处理最新的变化数据。通常情况下,静态数据或周期性更新的数据可以采用全量方式处理,而实时变化的数据可以采用增量方式处理。为了实现全量和增量数据的处理,可以采取以下方法:

  • 全量数据处理:每次处理时从源端获取全部数据,并进行数据清洗、转换和加载。
  • 增量数据处理:根据数据的增量标识(如时间戳或增量ID),只获取最新的变化数据,并进行增量处理,如更新、插入等操作。

这样可以保证数据的一致性,并提高数据处理的效率。具体的处理方式可以根据需求和情况进行选择。

Flume挂了处理方式:

  • 检查Flume的日志文件,查看错误信息,尝试找出导致Flume挂掉的原因,并做相应的修复措施。
  • 重启Flume进程,如果是配置文件或参数问题,可以尝试调整配置文件并重新启动。
  • 检查Flume的资源占用情况,如内存、磁盘等,如果资源吃紧可以尝试优化配置或增加资源。
  • 如果以上方法都无法解决问题,可以考虑采取备份方案,使用备份节点继续接收和处理数据,同时对故障节点进行诊断和修复。

Flume实现精准一致性的方法:

  • 启用事务机制:Flume可以通过启用事务机制来确保数据的精确一致性。在事务中,Flume会先将数据写入到临时存储(如内存或磁盘),等待事务完成后再将数据提交到目标存储(如HDFS、HBase等)。
  • 配置可靠性机制:Flume提供了可靠性机制,可以配置数据重试、持久化和可靠性存储等功能,确保数据能够正确传输和存储。
  • 监控和故障恢复:通过监控Flume的运行状态和日志信息,及时发现和修复数据传输故障,确保数据的精确一致性。

Flume写到HDFS的分区方式:

  • 通过Flume的配置文件中的时间戳插件(TimestampInterceptor)来进行分区,可以将事件写入到不同的目录或文件中,以时间为维度进行分区。
  • 自定义分区插件:可以开发自定义的Flume插件,根据业务需求对数据进行分区,如基于数据内容、关键字等进行分区。

Hive数据同步到HBase的方法:

  • 使用HBase的Bulk Load功能:将Hive表数据导出为HFiles格式,然后使用HBase提供的Bulk Load功能将HFiles导入到HBase表中。
  • 使用Hive的HBase Storage Handler:通过在Hive中创建外部表,并指定使用HBase Storage Handler存储格式,数据写入Hive表时会同时写入HBase表。

JVM的内存模型是指JVM对内存的组织和管理方式,主要包括以下部分:

  • 栈内存(Stack):用于存储方法调用的局部变量和方法调用栈。
  • 堆内存(Heap):用于存储对象实例和数组。
  • 非堆内存(Non-Heap):包括永久代(Permanent Generation)和元数据区,用于存储类的元数据信息和常量池等。
  • 方法区(Method Area):用于存储类的结构信息、静态变量和常量池等。
  • 本地方法栈(Native Method Stack):用于存储本地方法调用的相关信息。

JVM的内存模型对依赖于Java运行环境的程序来说是透明的,但开发人员需要了解它的组成和特性,以便进行合理的内存管理和性能优化。

垃圾回收机制是指自动回收程序不再使用的内存资源的一种机制,它能够自动检测和释放不再使用的对象,以便回收内存空间。

常见的垃圾回收算法有:

  1. 标记-清除算法(Mark and Sweep)
  2. 复制算法(Copying)
  3. 标记-整理算法(Mark and Compact)
  4. 分代算法(Generational)
  5. 增量垃圾回收算法(Incremental)

内存碎片化指的是内存中存在一些零散的、不连续的空闲内存块。内存碎片化可能导致以下问题:

  1. 内存分配效率低下:在存在内存碎片的情况下,需要找到足够大的内存块进行分配,可能会浪费一些小的空闲块。
  2. 内存使用不连续:内存碎片化导致内存空闲块不连续,可能无法满足需要连续内存空间的操作。

常见的设计模式有:

  1. 单例模式(Singleton)
  2. 工厂模式(Factory)
  3. 观察者模式(Observer)
  4. 建造者模式(Builder)
  5. 适配器模式(Adapter)
  6. 策略模式(Strategy)
  7. 装饰器模式(Decorator)
  8. 模板方法模式(Template Method)

单例模式的实现方式有:

  1. 饿汉式(Eager Initialization)
    • 在类加载时就创建实例,保证只有一个实例,并提供全局访问点。
  2. 懒汉式(Lazy Initialization)
    • 在需要时才创建实例,延迟加载,并提供全局访问点。
  3. 双重检查锁(Double-Checked Locking)
    • 结合了懒汉式和同步锁的方式,保证线程安全和延迟加载。

Spark程序的执行过程如下:

  1. 创建SparkContext:初始化Spark应用程序的环境。它负责和集群资源进行交互,并且是与Spark核心引擎进行通信的入口点。
  2. 创建RDD(弹性分布式数据集):通过读取外部数据源或对其他RDD进行转换来创建初始RDD。
  3. 执行转换操作:对RDD进行转换操作,如map、filter、reduce等,形成RDD的依赖关系图(DAG)。
  4. 触发动作操作:对RDD应用动作操作,如count、collect、save等,触发Spark作业的执行。
  5. 提交作业:将作业提交到集群,由Spark的调度器进行调度和分配资源;
  6. 任务划分:Spark将作业划分为不同的任务,并将这些任务分配到集群中的不同节点上并行执行。
  7. 任务执行:各个节点上的Executor执行任务,并将结果返回给驱动程序。
  8. 结果返回:驱动程序将各个节点上的任务执行结果进行汇总和整合,形成最终结果。

Stage是Spark作业中的一个阶段,它是根据作业的DAG图进行划分的。具体划分方式如下:

  1. 宽依赖划分:将作业DAG中存在Shuffle依赖的边界作为Stage划分的依据,即根据需要进行数据洗牌(Shuffle)的边界进行划分。
  2. 窄依赖划分:在宽依赖内部存在独立的任务链时,可能会将一个Stage再细分为多个子Stage,以提高执行并行度。

Shuffle是指Spark作业中进行数据重分区操作的过程,它主要涉及到数据的重新分组和排序。在执行Shuffle操作时,Spark会将执行节点的数据按照指定的Key进行重新分区,并将相同Key的数据打包并发送给同一个节点进行计算。Shuffle的过程开销较大,涉及数据的网络传输和磁盘IO等,因此需要在Spark程序中合理使用Shuffle,尽量减少Shuffle操作的频率和数据量,以提高程序的性能。

Spark和Flink是两种常见的大数据处理框架,它们有以下区别:

  1. 数据流模型:Spark采用的是批处理模型,将数据划分为离散的批次进行处理;而Flink采用的是流处理模型,能够实时处理无限流数据。

  2. 容错机制:Spark使用的是基于RDD(弹性分布式数据集)的容错机制,将数据从磁盘读取到内存进行计算,可通过重复执行容错的RDD操作来实现容错;而Flink使用的是基于状态的容错机制,通过定期对运算符的状态进行检查点(Checkpoint)来实现容错。

  3. 运行模式:Spark支持多种运行模式,如Standalone、YARN等;而Flink主要是在分布式环境下运行,如通过集群管理器如Apache Mesos、YARN、Kubernetes等。

  4. 数据一致性:Spark的批处理作业在随机抽样等场景下,存在数据一致性问题;而Flink的流处理模型具有事件时间和处理时间的一致性。

Flink的Checkpoint机制:

Flink的Checkpoint机制是一种容错机制,用于创建作业状态的一致性检查点。在执行过程中,Flink定期将作业的状态信息存储到持久化的存储介质中,以便在发生故障时进行恢复。Checkpoint包括作业状态的快照以及相关的元数据信息,如作业配置、操作符状态等。

Flink的Checkpoint机制的流程如下:

  1. Flink生成一个Checkpoint ID,然后以该ID创建一个全局一致的快照。
  2. Flink触发任务操作符进行快照操作,将操作符的状态和数据发送到持久化存储介质中。
  3. 一旦所有操作符完成快照,Flink会将快照的元数据保存到Checkpoint存储中,以便失败时进行恢复。

水位线是Flink用于处理事件时间的一种机制。水位线用于衡量事件时间进展,是一个时间戳的度量。Flink根据水位线确定触发窗口计算的时机,确保所有事件被正确地分配到正确的窗口中。水位线的更新策略可以通过编程方式进行自定义,常见的方式是基于事件时间的周期性更新,或者基于某个事件时间的最大延迟来更新。

对于迟到很久的数据,Flink可以使用侧输出流(Side Output)进行处理。侧输出流是指从主流中分流出来的一个或多个分支流,它可以用于处理迟到事件或异常情况。当一个事件的时间戳超出了某个窗口的结束时间时,Flink可以将这个事件发送到侧输出流,以单独进行处理,比如进行延迟计算、存储到外部系统等。

对于任务执行的流程,Spark的任务执行流程如下:

  1. Spark应用程序启动并初始化相关配置和资源。
  2. Spark将应用程序中的操作转化为一个个的DAG任务。
  3. Spark将DAG任务划分为不同的Stage,根据Shuffle边界进行划分。
  4. Spark将Stage中的任务分配给集群中的Executor进行并行执行。
  5. Executor执行任务并将结果返回给Spark Driver。
  6. Spark Driver整合各个Executor的结果并生成最终结果。

对于给定的1G文件,每一行一个词,词大小不超过16字节,内存大小为1M,要找出频数最高的100个词,可以使用以下算法:

  1. 将文件分成多个小文件,每个小文件可以全部读入内存。
  2. 遍历每个小文件,使用哈希表统计每个词出现的频数。
  3. 将每个小文件的哈希表合并到一个全局的哈希表中。
  4. 在全局哈希表中取出频数最高的100个词。可以使用堆排序等算法来实现。
  5. 输出结果即为频数最高的100个词。
#我的实习求职记录#
全部评论
chat 4吗
点赞 回复 分享
发布于 2023-11-10 09:11 上海

相关推荐

评论
21
71
分享

创作者周榜

更多
牛客网
牛客企业服务