面试相关问题整理
Spring、SpringMVC、SpringBoot、SpringCloud的区别与联系
Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。Spring使你能够编写更干净、更可管理、并且更易于测试的代码。
Spring MVC是Spring的一个模块,一个web框架。通过Dispatcher Servlet, ModelAndView 和 View Resolver,开发web应用变得很容易。主要针对的是网站应用程序或者服务开发——URL路由、Session、模板引擎、静态Web资源等等
Spring配置复杂,繁琐,所以推出了Spring boot,约定优于配置,简化了spring的配置流程。
Spring Cloud构建于Spring Boot之上,是一个关注全局的服务治理框架。
总结
Spring是核心,提供了基础功能;
Spring MVC 是基于Spring的一个 MVC 框架;
Spring Boot 是为简化Spring配置的快速开发整合包;
Spring Cloud是构建在Spring Boot之上的服务治理框架
线程有哪些状态
- 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
- 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。 - 阻塞(BLOCKED):表示线程阻塞于锁。
- 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
- 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
- 终止(TERMINATED):表示该线程已经执行完毕。
jvm调优
涉及到的设计模式:
适配器模式:不同平台不同的编译结果;
控制反转、依赖倒置:内存、锁由jvm控制
java、kotlin、grorvy、scala
class文件通过class Loader加载到 runtimeData areas 运行区内,通过执行引擎(jit complier、GC)执行,由natice methode interface提供硬件支撑(cpu 内存)
flink旁路输出后的数据怎么处理
这个问题没啥营养可能问的是出现问题后怎么处理
首先查看延迟有多大如果延迟不大的就调整下watermark
如果延迟很大,要找原因 看是不是数据倾斜了导致单点负载太大等问题
flink重启策略处理
flink如何保证 Exactly-Once
通过checkpoint确保 Exactly-Once
两阶段提交协议保证端到端 Exactly-Once 语义
checkpoint 如何保证 Exactly-Once
Checkpoint Barrier 对齐机制(Asynchronous barrier snapshots 基于 Chandy-Lamport 算法)
当 ExecutionGraph 物理执行图中的 subtask 算子实例接收到 Barrier 的时候,subtask 会记录它的状态数据。如果 subtask 有2个上游(例如 KeyedProcessFunction、CoProcessFunction等),subtask 会收齐上游的2个 Barrier 后再触发 Checkpoint(即 Barrier 对齐)。
- 运行任务
- JobManager 发起CheckPoint
JobManager 向任务流中发送 barrier (栅栏) - source上报CheckPoint
source收到barrier 向JobManager上报完成CheckPoint 将source的数据存储(保存位置由设置的StateBackend确定)。并将barrier 通过广播方式发送到下个task - 数据处理
在barrier到达task之前的数据按业务继续处理。收到barrier后的数据需要缓存
这里有精确一次处理(数据缓存) 和 至少一次处理(不缓存继续发送给下个task)的区别 - barrier对齐
在所有的barrier到达后,对task的状态进行checkpoint并将barrier发送到下个task
这里如何判断所有的barrier都到了? - 缓存数据处理
在所有的barrier到达最后的Sink后,上报JobManager完成checkPoint. 通知存储checkpoint结束
两阶段提交协议
checkpoint 保证作业出现fail-over后可以从最新的快照进行恢复,即分布式快照机制可以保证flink系统内部的”精确一次“处理
一旦Flink作业出现失败,作业会重新消费旧数据,这个时候就会出现重新消费的情况,也就是重复消费。
在Flink中两阶段提交的实现方式被封装到TwoPhaseCommitSinkFunction这个抽象类中,我们只需要实现其中的beginTransaction,preCommit,commit,abort四个方法就可实现”精确一次“的处理语义。
beginTransaction,在开启事务之前,我们在目标文件系统的临时目录中创捷一个临时文件,后面在处理数据时将数据写入此文件。
preCommit,在预提交阶段,刷写(flush)文件,然后关闭文件,之后就不能再写入文件了。我们还将为属于下一个检查点的任何后续写入启动新事务。
commit,在提交阶段,我们将预提交的文件原子性的移动到真正的目标目录中,这里会增加输出数据可见性的延迟
abort,在中止阶段,删除临时文件。
kafka分区计算出来的
分区
Kafka使用分区将topic的消息打散到多个分区分布保存在不同的broker上,实现了producer和consumer消息处理的高吞吐量。Kafka的producer和consumer都可以多线程地并行操作,而每个线程处理的是一个分区的数据。因此分区实际上是调优Kafka并行度的最小单元。对于producer而言,它实际上是用多个线程并发地向不同分区所在的broker发起Socket连接同时给这些分区发送消息;而consumer,同一个消费组内的所有consumer线程都被指定topic的某一个分区进行消费。
创建一个只有1个分区的topic,然后测试这个topic的producer吞吐量和consumer吞吐量。假设它们的值分别是Tp和Tc,单位可以是MB/s。然后假设总的目标吞吐量是Tt,那么分区数 = Tt / max(Tp, Tc)
机子几核设定多少个分区
有做什么自定义分区的策略吗?为什么
默认分区策略 hash(key) % partition;
例如:订单数据有外卖、堂食、外带。其中订单量比例 外卖:堂食:外带 = 1:3:1。 按正常的订单类型分区的话会导致数据倾斜。所以我们将堂食做了拆分通过
kafka 备份
ISR参数
min.insync.relicas
默认值1, 用于表明限定在ISR 列表里面 至少有几个副本, 如果设定为2,如果ISR中只有一个副本的情况下,往该分区插入数据就会报错。
kafka 采用多服务端冗余副本
副本关系:
leader partition:
客户端写数据 消费者读数据操作的都是lead partition
会维护一个ISR in-sync-replica 副本列表 写数据的时候会往副本列表中的所有副本写入数据 所有都成功了才会认为写入成功,如果有个副本写入不成功可能会将副本移出ISR中
follwer partition:
定期去lead partition同步数据
数据是怎么同步的
kafka副本策略
hbase底层数据结构
mysql底层数据结构是B+tree
hbase底层数据结构是LSMtree
hdfs写入流程
- 客户端(通过Distributed FileSystem模块)向NameNode发出写文件请求。
- 检查是否已存在文件、检查权限。若通过检查,直接先将操作写入EditLog,并返回输出流对象。
(注:WAL,write ahead log,先写Log,再写内存,因为EditLog记录的是最新的HDFS客户端执行所有的写操作。如果后续真实写操作失败了,由于在真实写操作之前,操作就被写入EditLog中了,故EditLog中仍会有记录,我们不用担心后续client读不到相应的数据块,因为在第5步中DataNode收到块后会有一返回确认信息,若没写成功,发送端没收到确认信息,会一直重试,直到成功) - client端按128MB的块切分文件。
- client将NameNode返回的分配的可写的DataNode列表和Data数据一同发送给最近的第一个DataNode节点,此后client端和NameNode分配的多个DataNode构成pipeline管道,client端向输出流对象中写数据。client每向第一个DataNode写入一个packet,这个packet便会直接在pipeline里传给第二个、第三个…DataNode。
(注:并不是写好一个块或一整个文件后才向后分发)
ps:这里被问到一个问题- client怎么知道哪个是第一个DataNode的
NameNode返回的DataNode地址,会按照集群拓扑结构得出DataNode与客户端的距离,然后进行排序。排序有两个规则:
网络拓扑结构中距离客户端近的则靠前;心跳机制中超时汇报的DataNode状态为无效的,则排靠后。NetworkTopology将整个集群中的DN存储成了一个树状网络拓扑图, - 每个DataNode写完一个块后,会返回确认信息。
(注:并不是每写完一个packet后就返回确认信息,个人觉得因为packet中的每个chunk都携带校验信息,没必要每写一个就汇报一下,这样效率太慢。正确的做法是写完一个block块后,对校验信息进行汇总分析,就能得出是否有块写错的情况发生) - 写完数据,关闭输输出流。
- 发送完成信号给NameNode。
(注:发送完成信号的时机取决于集群是强一致性还是最终一致性,强一致性则需要所有DataNode写完后才向NameNode汇报。最终一致性则其中任意一个DataNode写完后就能单独向NameNode汇报,HDFS一般情况下都是强调强一致性)
flink加盐
问道flink 数据倾斜的时候 我回答了从source地方解决。 然后反问我有没有通过flink加盐的方式处理过 表示没有。。。
数据倾斜
- 单点问题
数据集中在某些分区上(Subtask),导致数据严重不平衡。 - GC 频繁
过多的数据集中在某些 JVM(TaskManager),使得JVM 的内存资源短缺,导致频繁 GC。 - 吞吐下降、延迟增大
数据单点和频繁 GC 导致吞吐下降、延迟增大。 - 系统崩溃
严重情况下,过长的 GC 导致 TaskManager 失联,系统崩溃
解决
- 并发度
并发度设置的比分区数要低时,就会造成上面所说的消费不均匀的情况 - key 分布不均匀 (上游 源头)
通过添加随机前缀打散它们的分布,使得数据不会集中在几个 Task 中 - key 分布不均匀 (transformation阶段)
聚合统计前,先进行预聚合,例如两阶段聚合(加盐局部聚合+去盐全局聚合)
具体措施:
① 预聚合:加盐局部聚合,在原来的 key 上加随机的前缀或者后缀。
② 聚合:去盐全局聚合,删除预聚合添加的前缀或者后缀,然后进行聚合统计。
java
jvm区
public static String aaa = “aa”;
这个是在哪个内存区里面的?
第一种,static的,作为类信息在类被加载时被存在静态的方法区。
第二种,非static的,作为对象属性,在对象创建的时候被初始化,存在堆里。
第三种,在方法里的。我们知道在方法被调用时会被加载到栈中进行执行,所以写在方法里的变量存在栈中,也没毛病。