快手视频面一面
一个戴帽子的小姐姐, 一副高冷的样子, 很有范
写了一道sql题
一个表 里面两个字段 关注人, 被关注人 求出表中所有互关的人
手撕一道题
树的遍历, 非递归写法
mysql的查询如何优化, 我问: 是不是从大方面来讲那, 小姐姐让我尽情发挥
我就开始扯了
先从多表模式来看, 做范式和非范式的权衡,
然后的单表的优化, 选择合适的存储引擎, 合适的索引类型, 给合适的列加合适的索引,
然后是具体的sql优化, 查询服务器上的具体慢sql 定位性能瓶颈,排查具体的sql性能问题 , 比如索引的利用问题, 子查询和表连接权衡问题, 多表连接顺序问题
剩下的不记得了 都是常规问题 小姐姐比较好说话 让过了
第二面 视频面 十多分钟后
手写一道题: n个m长的排序数组, 返回一个nm长的新数组 写完后问复杂度 是说O(n^2) 他说不对是 O(nn*m) , 我说有道理
然后让优化下, 我就给优化了下 加了一个FinishSet 记录下哪个数组已经遍历到头了, 能少几次比较, 但是整体性能还是这样 木有空间了,
然后就是问hive sql的执行原理, 我拓展了一下, 说hive/spark sql/ mysql/ calcite 其实都有着共性, 就是分为了 sql语法词法解析 -> 逻辑计划生成和优化 -> 物理计划生成和优化
前面的两部都是类似的, 比如sql语法词法解析 calcite用了javaCC catalyst用了anltr4 ,巴拉巴拉 然后是逻辑计划的生成, 然后是逻辑计划的优化, 属于基于关系型代数来对sql语法进行同义替换的过程, 然后到了具体的物理执行计划的时候 才有各自的区别, 比如hive是把相关的逻辑计划翻译成map reduce等操作, spark sql是把他翻译成rdd直接的操作 其实整体来看 殊途同归
后面问了超级多的流计算相关的 , 我这块比较薄弱
flink savepoint checkpoint区别
功能的原理是一样的, 只是目的不同, 一个是自动的备份, 另一个是手动的保持状态, 用做版本升级/服务重启等
flink checkpoint原理
意义: 被checkpoint保存的每个subtask的状态只有raw state和managed state两种。raw state是用户自己进行序列化,而managed state是在operator生命周期初始化时就被注册到backend storage对象中了,在进行checkpoint时,会直接拿到注册的state进行保存(中间会调用回调函数,在UDF中对state进行赋值)。所以checkpoint的state不是很大的数据。
如何做到:
理想情况下, checkpoint是最好可以把输入流停掉, 然后保持这一时刻 所有分区的快照
但是这样在工程上不合理, 所以用了Chandy-Lamport算法 做一个分布式的快照

  1. 在checkpoint触发时刻,Job Manager会往所有Source的流中放入一个barrier。barrier包含当前checkpoint的ID
  2. 当barrier经过一个subtask时,即表示当前这个subtask处于checkpoint触发的“时刻”,他就会立即将barrier法往下游,并执行checkpoint方法将当前的state存入backend storage

exactly once小结: kafka, spark streaming receiverAPI 和directAPI, flink 都是如何保证exactly once的那?
kafka: 包括三部分, 首先是写入时的exactly once, 通过幂等性和事务来保证,Producer ID(即PID)和Sequence Number来保证幂等性, 事务不清楚用法了
第二部分是: kafka写入数据时候的可靠性, 通过多个副本来保证数据的有效性
第三部分就是消费时候的exactly, 例如spark streaming 使用高级消费者api, 会造成多次消费, 低级API自己管理offset, 就可以保证
然后是spark 如何保证exactly once,
使用高级消费者API其实也是可以保证的, 就是使用WAL 额外再管理一次offset相关的信息, 只是这样性能较差
使用directAPI更加合适, 这两者主要区别就是offset的管理, 除此之外体现在RDD执行计划的生成上还有一个不同之处,
receiverAPI会直接拉取数据到内存中, 然后把内存中数据来生成DGraph计划, 而directAPI不是, 他生成的RDD执行计划, 持有的应该只是我这个RDD对应需要拉取数据的offset, 在DStream这个层面并没有拉取数据, 而是InputRDD这里真正的去拉取了数据, 配合上SparkStreaming的checkpoint机制, 保持相关的offset和state信息
这样加上Spark core对RDD的容错机制 才保证了性能和exactly的兼顾

flink如何保证exactly once的, 主要有以下两点
https://blog.csdn.net/rlnLo2pNEfx9c/article/details/81369878

  1. 两阶段提交 预提交+实际提交 这是分布式事务的一种实现方式
  2. checkpoint机制, 两次checkpoint之间为一次事务, 用checkpoint保证exactly once

加上分布式事务的checkpoint实现:
a.pre-commit阶段
Flink checkpointing开始时便进入到pre-commit阶段。具体来说,一旦checkpoint开始,Flink的JobManager向输入流中写入一个checkpoint barrier将流中所有消息分割成属于本次checkpoint的消息以及属于下次checkpoint的。barrier也会在操作算子间流转。对于每个operator来说,该barrier会触发operator状态后端为该operator状态打快照。例如flink kafka source保存Kafka消费offset, 当checkpoint barrier在所有operator都传递了一遍且对应的快照也都成功完成之后,pre-commit阶段才算完成。该过程中所有创建的快照都被视为是checkpoint的一部分
b.commit阶段
下一步就是通知所有的operator,告诉它们checkpoint已成功完成。这便是两阶段提交协议的第二个阶段:commit阶段。该阶段中JobManager会为应用中每个operator发起checkpoint已完成的回调逻辑。

什么时候会被降级到at least once
快照发生时,flink会在某些有状态的operator上对data record进行对齐操作(alignment),目的是避免失败恢复时重复消费数据。这个过程也是exactly once的保证。通常对齐操作的时间仅是毫秒级的。但是对于某些极端的应用,在每个operator上产生的毫秒级延迟也不能允许的话,则可以选择降级到at least once,即跳过对齐操作,当失败恢复时可能发生重复消费数据的情况