面试吹牛之前先打个草稿!
各位面试官好!
1.我叫 xxx,毕业于 xxx,之前在 xxx 公司待了 1 年多,期间⼀直从事的是 IT 行业,刚开始的时候做的是 Java 开发后来转岗到大数据方向做大数据开发; 刚转行到大数据开发的时候开始比较困难的,大数据并不像 Java 那样⼀套框架基本可以搞定所有的问题,而是不同的业务对于同⼀个问题有多种解决方案。
2.我叫 xxx,毕业至今就职于 xx 公司,职位是数仓开发。
参加工作以来,我先后参与筹备大数据服务器购买以及从 0 到 1 的搭建,离线数仓项目组,实时数仓项目组。这三个项目都得到了老板们的一致好评,大大增加了业务方需要客户数据的效率,能更快的做出实时决策。
我对大数据各框架有浓厚的兴趣,工作之余经常钻研技术,例如 flink 的水位线,双流 join 等,对业务需求分析的比较透彻。
工作三年,我已经连续两年被评为优秀员工,我觉得这足以说明我技术扎实,对待工作严谨,好学,当然也离不开原公司帮助过我的师傅们。
3.我叫 xxx,毕业于 xxx,自己大学期间学了 C++就喜欢上了编程,然后大学期间利用业余时间学习了 JAVA。大四的时候又接触到了大数据,又对大数据产生兴趣,学校也开了大数据相关的专业,于是就在晚上找各种相关资料,在 B 站上搜一些比较好的大数据视频,把相关视频学习钻研了一遍。20 年毕业的时候,也从事的大数据行业的工作,参与了大数据架构的搭建,以及数仓的建模等相关的工作。又利用业余时间,进行补充知识,不断的提高自己。至于以后,还是会不断的学习来提高自己对大数据的开发能力,提高自己的业务水准。
4.我叫 xxx,毕业于 xxx。之前 2 年多的时间里一直从事大数据开发工作。
刚开始是在平台岗,主要负责数据平台的搭建以及维持整个框架的正常运行,从购买服务器,包括框架版本选型,以及服务器台数定制,这些都是从 0 到 1 搭建的;在平台岗工作了差不多半年时间,由于这段期间表现比较突出,公司想成立数仓组,就让我负责筹建搭建数仓的工作,我从数仓建模开始逐渐搭建元数据管理,数据质量监控,权限管理,指标分析,之后就一直数仓岗的工作;直到一年前,公司老大决定要做实时这块,要统计一个大屏的可视化展示,可能觉得我的攻坚能力比较强,第一时间又想到了我,我就把这个活接过来了,我开始组建实时团队,也比较好的完成了任务。
我离职前主要是做平台的搭建以及各种指标的分析: 实现和离线的都做;
我最近做的⼀个项目是商城平台,我们这个项目主要包含三个方⾯ :
- 数据仓库的搭建;
- 实时计算系统;
- 离线计算系统;
刚开始主要是负责做平台相关的工作,后来做了⼀段时间的实时指标,离职前主要负责离线 指标这块的内容以及⼀些维护优化的⼯作;
公司大数据部门这边刚开始有 5 个人,随后因为业务的增加又招了⼀些人离职前有 8 个人;
一、简要介绍项目
接下来我先介绍⼀下这个项目:
项目是⼀个高度定制化的商城平台,最近主要做的是数仓和离线指标计算这⼀块;
数仓初期
数仓搭建初期,由于公司数据量少,经验不足,数仓没有层级概念,过来的数据直接进行解析,每次计算一个指标的时候,都需要进行 ETL 操作,每次都需要进行 join,造成了大量的重复操作,效率十分低下,浪费大量人力。
数仓后期
数仓在搭建一段时间后,重复的计算操作困恼了我很久,后来我参考了阿里的离线数仓架构,我们对数仓进行了重新的架构搭建,对数仓进行了分层规划。
主要分为:
- ods 层 : 数据缓冲层;
- dwd 层 : 基础数据层;
- dws 层 : 数据汇总层;
- app 层 : 应用层;
分四层的原因主要是为了隔离数据然后还能复用上⼀层计算出来的数据,另一方面也是为了数据的备份;
二、介绍熟悉的框架
数据采集我们主要是采集业务系统的数据及日志数据两部分,业务系统数据存储在 Mysql 中,使用 Sqoop 将数据导入大数据平台。
Sqoop:
Sqoop 是在 Hadoop 生态体系和 RDBMS 体系之间传送数据的一种工具。它的工作机制是将导入或导出命令翻译成 mapreduce 程序来实现。在翻译出的 mapreduce 中主要是对 inputformat 和 outputformat 进行定制。
我们在使用 Sqoop 导入导出时出现了 Null 的存储一致性问题,Hive 中的 Null 在底层是以“\N”来存储,而 MySQL 中的 Null 在底层就是 Null。为了保证数据两端的一致性,在导出数据时采用--input-null-string 和--input-null-non-string 两个参数。导入数据时采用--null-string 和--null-non-string。
Flume:
对于日志采集我们当时选用的是 Flume,采集日志框架也有很多,之所以选择 Flume 主要是因为它采集数据的效果比较好,其次是对于 HDFS 和 Kafka ⽀持的也比较好;
Flume 主要包含三大组件:
Source、Channel、Sink
- Flume 在 1.7 以后提供了⼀个 TailDirSource 用来⽀持多目录和断点续传功能;
- 断点续传主要保证在服务器挂掉的情况下,再次启动服务数据不会丢失的问题;其原理就是在底层维护了⼀个 offset 偏移量(也就是每次读取文件的偏移量)Flume 会通过这个偏移量来找到上次文件读取的位置从⽽实现了断点续传的功能;
- 在 1.6 以前这个实现断点续传是需要手工维护这个偏移量的会比较麻烦;
- Channel 的种类比较多主要有:
- MemoryChannel : 数据放在内存中,会在 Flume 宕机的时候丢失数据,可以用在对数据安全性要求没有那么高的场景中比如日志数据;
- FileChannel : 不会丢失数据,因为数据是放在磁盘上边的⽽且⽀持多目录配置可以提高写入的性能,同时因为有落盘的操作所以效率比较低,适合用在对数据安全性要求比较高的场景比如⾦融类的数据;
- KafkaChannel : 主要是为了对接 Kafka,使用这个可以节省 Sink 组件也可以提升效率的,我们项目中使用的就是这个 Channel,因为下⼀层是使用 Kafka 来传递消息的;
- 在 Flume 这⼀层我们还做了⼀个拦截器,主要是对收集到的日志做了⼀层过滤,因为有的日志没有 id 或一些关键字段,这些数据对我们数据分析来说是没有任何用的,所以在拦截器里边对这些数据进行了简单清洗;
- 还做了⼀个分类型的拦截器,在这个拦截器里边我们对数据进行类型的区分,主要是做了⼀个打标签的功能对不同的日志数据打上不同的标签,然后通过后续的选择器 Multiplexing 将不同标签的数据放到不同的 topic 里边,⽅便下游对数据进行处理;
Kafka:
下游数据传输使用的是 Kafka 作为消息队列来传输消息,使用 Kafka 的主要原因是因为 Kafka 的高吞吐量以及可以对数据进行分类也就是不同的 topic,⽅便下⼀层的使用,整体的架构是采用 Lamda 架构设计的,实时和离线都会从 Kafka 中获取数据来进行处理,⽽且还有其他的业务线也是从 Kafka 中获取数据的,这样做以后可以有效的提高数据的复用减少数据的冗余,离线这块我们是在 Kafka 之后⼜做了⼀层 Flume 来作为消费者处理 Kafka 中的数据的, 将消费到的数据直接放入 HDFS 中,实时这块使用的是 SparkStreaming 来消费 Kafka 中的数据;
为什么选择 Kafka 作为消息队列来处理数据
当时在做技术选型的时候我们也是做了大量的调研,因为消息队列的产品有很多比如 : ReactMQ Kafka 等;
我们当时调研考虑的主要指标就是吞吐量这⼀块,因为大数据流式处理对数据的吞吐量要求是⾮常高的,在这⼀块 ReactMQ 是比较厉害的,吞吐量可以达到 1 万多每秒;通过后来的调研以后发现 Kafka 的吞吐量比 ReactMQ 更高,如果使用恰当的话吞吐量甚⾄可以达到 10 万+每秒;
kafka 支持消息持久化,消费端是主动拉取数据,消费状态和订阅关系由客户端负责维护,消息消费完后,不会立即删除,会保留历史消息。因此支持多订阅时,消息只会存储一份就可以。
- broker:kafka 集群中包含一个或者多个服务实例(节点),这种服务实例被称为 broker(一个 broker 就是一个节点/一个服务器);
- topic:每条发布到 kafka 集群的消息都属于某个类别,这个类别就叫做 topic;
- partition:partition 是一个物理上的概念,每个 topic 包含一个或者多个 partition;
- producer:消息的生产者,负责发布消息到 kafka 的 broker 中;
- consumer:消息的消费者,向 kafka 的 broker 中读取消息的客户端;
- consumer group:消费者组,每一个 consumer 属于一个特定的 consumer group(可以为每个 consumer 指定 groupName);
Kafka 为什么可以这么快?
- 首先从生产者说起,生产者发送数据是按照批进行发送的并不是⼀条⼀条发送的,从这里就已经可以保证 Kafka ⼀个比较高的吞吐量了;
- 生产者来⼀条消息以后会进入⼀个拦截器,在拦截器里边可以对数据进行⼀个整体的 修改操作⼀般这里是不做特殊的处理的,数据从拦截器出来以后就会进入到序列化器, 在序列化器里边将数据转换成⼀个⼆进制流的形式放入 Broker 里边;
- 经过序列化器以后数据就会⾛到分区器,Kafka 使用的分区器是⼀个叫做 Hash 的分区器,Hasf 分区器我们可以对其进行重写;
- 生产者将消息发送到 Broker 的过程可能会出现消息的重复或者丢失的情况,这个主要是靠 ACK 的配置来决定的,ack 的响应有三个状态值 0,1,-1
- 0:生产者只负责发送数据,不关心数据是否丢失,丢失的数据,需要再次发送
- 1:partition 的 leader 收到数据,不管 follow 是否同步完数据,响应的状态码为 1
- -1:所有的从节点都收到数据,响应的状态码为-1
- 这里还有⼀个很重要的概念就是 ISR 副本同步队列,在这个队列里边包含了 Leader 和 Follower,主要解决的问题就是 Leader 挂了以后谁来做 Leader 的问题:
- 选举机制就是通过这个 ISR 来进行的,默认是有⼀个排序排序的⼀般都是选取第⼀ 个,因为每⼀批的数据只有最快的那个才能达到第⼀个接收消息,其中 ISR 队列以及 Leader 的选举是由 Controller 来控制的,Zookeeper 来进行存储,关于 Controller 在 Kafka 中也是⾮常重要的 Controller 也有⼀个专门的选举机制,它是相当于是用 Zookeeper 来做了⼀个分布式锁,具体原理就是利用 Zookeeper 生成的临时节点生成⼀个分布式锁,谁先抢占到谁就是 Leader;
三、介绍项目采用的架构
上面也说到,我们整体的架构是采用 Lamda 架构设计的。
数据从底层的数据源开始,经过 Kafka、Flume 等数据组件进行收集,然后分成两条线进行计算:
- 一条线是进入流式计算平台(例如 Storm、Flink 或者 SparkStreaming),去计算实时的一些指标;
- 另一条线进入批量数据处理离线计算平台(例如 Mapreduce、Hive,Spark SQL),去计算 T+1 的相关业务指标,这些指标需要隔日才能看见。