常见大数据面试题汇总带答案
Posted Direction_Wind
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常见大数据面试题汇总带答案相关的知识,希望对你有一定的参考价值。
大数据面试题汇总
redis
为什么快
首先,采用了多路复用io阻塞机制
然后,数据结构简单,操作节省时间
最后,运行在内存中,自然速度快
– 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);
– 数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
– 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
– 使用多路I/O复用模型,非阻塞IO;
– 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;
flink(大部分知识点写过的帖子里都有)
interval join不上的数据,怎么处理?怎么做数据修复?
需要匹配join不上的,用cogroup实现
(CoGroup算子:将两个数据流按照key进行group分组,并将数据流按key进行分区的处理,最终合成一个数据流(与join有区别,不管key有没有关联上,都可以合并成一个数据流),只能在window中使用)
或者用flinkSQL的左右外关联
广播变量优势劣势
– 优势:Flink支持广播。可以将一份数据广播到一个TaskManager所有的task ,数据存储到内存中。这样可以减少大量的shuffle操作,而不需要多次传递给集群节点;
– 劣势:广播变量是要把dataset广播到内存中,所以广播的数据量不能太大,否则会出现OOM;广播变量的值不可修改,这样才能确保每个节点获取到的值都是一致的;
mr,java ,集群
hashSet底层去重原理
step1–>存入元素时,先比较要存入的元素的哈希值和集合中元素的哈希值是否一样
step2–>如果要存入的元素哈希值不同直接存入集合
step3–>如果存入元素的哈希值和集合元素的哈希值相同,再调用equals比较属性值,如果属性值相同,就不存入集合,属性值不相同,就存入集合
列存优势 lsm的存储结构和优势
行式存储可以看成是一个行的集合,其中每一行都要求对齐,哪怕某个字段为空(下图中的左半部分),而列式存储则可以看成一个列的集合(下图中的右半部分)。列式存储的优点很明显,主要有以下 4 点:
– 查询时可以只读取涉及的列(选择操作),并且列可以直接作为索引,非常高效,而行式存储则必须读入整行。
– 列式存储的投影操作非常高效。
– 在数据稀疏的情况下,压缩率比行式存储高很多,甚至可以考虑将相关的表进行预先连接,来完全避免投影操作。
– 因为可以直接作用于某一列上,聚合分析非常迅速。
– 行式存储一般擅长的是插入与更新操作,而列式存储一般适用于数据为只读的场景。对于结构化数据,列式存储并不陌生。因此,列式存储技术经常用于传统数据仓库中。
– lsm树 日志追加append的方式写入,会存几个副本 hbase就是,天生适合写多读少的场景, 会先写入 后合并,所以写入效率非常高,删除也是内存里先标记,后面异步合并操作才会真正的删除数据,效率高
MR提交流程 shuffle的过程? 哪些算子会产生shuffle?
https://@note.youdao.@com/s/@PcTseRlE
java线程池的实现原理
算法题
请你找出其中不含有重复字符的 最长子串 的长度?
public static int lengthOfLongestSubstring(String s)
if (s == null || "".equals(s))
return 0;
int n = s.length();
Map<Character, Integer> map = new HashMap<>(16);
int maxLength = 0;
for (int i = 0,j = 0; j < n; j++)
if (map.containsKey(s.charAt(j)))
i = Math.max(map.get(s.charAt(j)), i);
maxLength = Math.max(maxLength, j - i + 1);
map.put(s.charAt(j), j + 1);
return maxLength;
public static int lengthOfLongestSubstring(String s)
if (s == null || "".equals(s))
return 0;
List<Character> list = new ArrayList<>();
int n = s.length();
int maxLength = 0;
for (int i = 0; i < n; i++)
int index = list.indexOf(s.charAt(i));
if (index == -1)
list.add(s.charAt(i));
maxLength = Math.max(list.size(), maxLength);
else
for (int j = index; j >= 0; j--)
list.remove(j);
list.add(s.charAt(i));
return maxLength;
微信红包
还是以10元10个红包为例,随机10个数,红包金额公式为:红包总额 * 随机数/随机数总和,假设10个随机数为[5,9,8,7,6,5,4,3,2,1],10个随机数总和为50,
第一个红包105/50,得1元。
第二个红包109/50,得1.8元。
第三个红包10*8/50,得1.6元。
以此类推。
写个快排
package Launcher;
import java.util.Arrays;
public class QuickSort
public static int partition(int[] array, int low, int high)
// 取最后一个元素作为中心元素
int pivot = array[high];
// 定义指向比中心元素大的指针,首先指向第一个元素
int pointer = low;
// 遍历数组中的所有元素,将比中心元素大的放在右边,比中心元素小的放在左边
for (int i = low; i < high; i++)
if (array[i] <= pivot)
// 将比中心元素小的元素和指针指向的元素交换位置
// 如果第一个元素比中心元素小,这里就是自己和自己交换位置,指针和索引都向下一位移动
// 如果元素比中心元素大,索引向下移动,指针指向这个较大的元素,直到找到比中心元素小的元素,并交换位置,指针向下移动
int temp = array[i];
array[i] = array[pointer];
array[pointer] = temp;
pointer++;
System.out.println(Arrays.toString(array));
// 将中心元素和指针指向的元素交换位置
int temp = array[pointer ];
array[pointer] = array[high];
array[high] = temp;
return pointer;
public static void quickSort(int[] array, int low, int high)
if (low < high)
// 获取划分子数组的位置
int position = partition(array, low, high);
// 左子数组递归调用
quickSort(array, low, position -1);
// 右子数组递归调用
quickSort(array, position + 1, high);
public static void main(String[] args)
int[] array = 6,72,113,11,23;
quickSort(array, 0, array.length -1);
System.out.println("排序后的结果");
System.out.println(Arrays.toString(array));
kafka
kafka offset在一个名为 __consumer_offsets 的Topic中
kafka的ISR机制 副本同步机制 保证数据准确性
— 首先我们知道kafka 的数据是多副本的,某个topic的replication-factor为N且N大于1时,每个Partition都会有N个副本(Replica)。kafka的replica包含leader与follower。每个topic 下的每个分区下都有一个leader 和(N-1)个follower,
—每个follower 的数据都是同步leader的 这里需要注意 是follower 主动拉取leader 的数据
---- Replica的个数小于等于Broker的个数,也就是说,对于每个Partition而言,每个Broker上最多只会有一个Replica,因此可以使用Broker id 指定Partition的Replica
http@s://www.c@nblogs.com/@zzzzrrrr/p/13197390.html
Kafka 并不支持主写从读(读写分离),这是为什么呢?
1.kafka的follower与leader会有延时,不好解决
2.kafka写多读也多,不太适合
3.之后支持读写分离,为了解决跨数据中心消费的问题(就是机器不在一个地儿,带宽不够),才搞得读写分离。
kafka保证分区内顺序
设置一个分区
生产时指定分区;生产时用相同的key
维度建模分为哪几种?
https:/@/www.csdn.net/tags/NtT@aUg2sNTYx@MzMtYmxvZwO0O0OO0O0O.html
星型 : 事实表+维度
雪花 :事实表+维度-维度
星座:事实+维度+事实+维度
SQL高频面试题
刷题网站:https://www.nowcoder.com/exam/oj?page=1&tab=SQL%E7%AF%87&topicId=268
sql面试题:求连续最大登录天数
连续签到领金币:https://www.nowcoder.com/practice/aef5adcef574468c82659e8911bb297f?tpId=268&tqId=2285347&ru=/exam/oj&qru=/ta/sql-factory-interview/question-ranking&sourceUrl=%2Fexam%2Foj%3Fpage%3D1%26tab%3DSQL%25E7%25AF%2587%26topicId%3D268
连续签到领金币 7天一周期 3天7天 多领 计算总领的金币
WITH t1 AS( -- t1表筛选出活动期间内的数据,并且为了防止一天有多次签到活动,distinct 去重
SELECT
DISTINCT uid,
DATE(in_time) dt,
DENSE_RANK() over(PARTITION BY uid ORDER BY DATE(in_time)) rn -- 编号
FROM
tb_user_log
WHERE
DATE(in_time) BETWEEN '2021-07-07' AND '2021-10-31' AND artical_id = 0 AND sign_in = 1
),
t2 AS (
SELECT
*,
DATE_SUB(dt,INTERVAL rn day) dt_tmp,
case DENSE_RANK() over(PARTITION BY DATE_SUB(dt,INTERVAL rn day),uid ORDER BY dt )%7 -- 再次编号
WHEN 3 THEN 3
WHEN 0 THEN 7
ELSE 1
END as day_coin -- 用户当天签到时应该获得的金币数
FROM
t1
)
SELECT
uid,DATE_FORMAT(dt,'%Y%m') `month`, sum(day_coin) coin -- 总金币数
FROM
t2
GROUP BY
uid,DATE_FORMAT(dt,'%Y%m')
ORDER BY
DATE_FORMAT(dt,'%Y%m'),uid;
sql:表名:test,字段(user_id1,user_id2,time)求这个表里,互相关注的用户有多少?
select
a.from_user,
a.to_user,
if( sum(1) over (partition by feature) > 1, 1, 0) as is_friend
from
(
select
a.from_user,
a.to_user,
if(from_user > to_user, concat(to_user, from_user), concat(from_user, to_user)) as feature
from table_relation
)a
hbase
写入过程
1)客户端处理阶段:客户端将用户的写入请求进行预处理,并根据集群元数据定位写入数据所在的RegionServer,将请求发送给对应的RegionServer。
2)Region写入阶段:RegionServer接收到写入请求之后将数据解析出来,首先写入WAL,再写入对应Region列簇的MemStore。
3)MemStore Flush阶段:当Region中MemStore容量超过一定阈值,系统会异步执行flush操作,将内存中的数据写入文件,形成HFile。
注意:用户写入请求在完成Region MemStore的写入之后就会返回成功。MemStore Flush是一个异步执行的过程。
RowKey设计原则
– 1.Rowkey的唯一原则
– 2.Rowkey的排序原则:HBase的Rowkey是按照ASCII有序设计的,我们在设计Rowkey时要充分利用这点。
– 3.Rowkey的散列原则 也就是热点问题,经常与2冲突。
热点问题:
– 1.Reverse反转
针对固定长度的Rowkey反转后存储,这样可以使Rowkey中经常改变的部分放在最前面,可以有效的随机Rowkey。
– 2.Salt是将每一个Rowkey加一个前缀,前缀使用一些随机字符,使得数据分散在多个不同的Region,达到Region负载均衡的目标。
– 3.rowkey做hash
高可用原理
jvm
1、JVM 主要组成部分
1、类加载器(ClassLoader)
2、运行时数据区(Runtime Data Area)
3、执行引擎(Execution Engine)
4、本地库接口(Native Interface)
2、组件的作用
首先,通过类加载器(ClassLoader)会把 Java 代码转换成字节码;
其次,运行时数据区(Runtime Data Area)再把字节码加载到内存中,而字节码文件只是 JVM 的一套指令集规范,并不能直接交给底层操作系统去执行;
于是,需要特定的命令解析器执行引擎(Execution Engine),将字节码翻译成底层系统指令,再交由 CPU 去执行;
最后,此过程中需要调用其他语言的本地库接口(Native Interface)来实现整个程序的功能
mysql
联合索引机制:
– 遵守最左前缀匹配原则,检索数据时从联合索引的最左边开始匹配,直到遇到范围查询就停止匹配。
– 本质上联合索引也是一个 B+树,和单列索引不同的是,联合索引的键值不是一个,而是大于 1 个。建立联合索引的时候,B+树只能选择一个字段构建有序的树,默认是第一个字段,即最左边的字段,只有当第一个字段的值是相同的,才会按照第二个字段的值进行排序,即先确定第一个字段有序,才会匹配第二个字段
– 对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c). 可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找
4.mysql的主从节点数据复制机制,可以开启主从双写吗?会有什么问题?
不可以,MySQL 默认采用异步复制方 双写会有重复吧,
本来读写分离,现在双写,就不分离了
sql递归
WITH CTE AS(
SELECT 部门ID,父级ID,部门名称,部门名称 AS 父级部门名称
FROM Company
WHERE 父级ID=-1
UNION ALL
SELECT c.部门ID,c.父级ID,c.部门名称,p.部门名称 AS 父级部门名称
FROM CTE P
INNER JOIN Company c ON p.部门ID=c.父级ID
)
SELECT 部门ID,父级ID,部门名称,父级部门名称
FROM CTE
hive
reduceByKey和groupByKey:
reduceByKey在分区内会进行预聚合,而后再将所有分区的数据按照关键字来分组聚合。
而groupByKey则不会先进行预聚合,它直接将所有分区的数据一起分组,如果要再进行聚合,则groupByKey还需要使用其他函数,比如sum()
大小表数据倾斜,用MAPjoin 原理 :
join本来是reduce进行关联查找,改成了map端进行关联查找
适用于大表join小表,使用DistributedCache机制将小表存储到各个Mapper进程所在机器的磁盘空间上,各个Mapper进程读取不同的大表分片,将分片中的每一条记录与小表中所有记录进行合并
合并后直接输出map结果即可得到最终结果。
注:不需要进行shuffle流程,也不需要reduce处理
distinct 和 group by有什么区别?在哪种情况下使用group by性能会更优?
--------仅仅从查询的作用角度看:
distinct 和 group by 都可以用来去重
不同之处,distinct 是针对要查询的全部字段去重,而 group by 可以针对要查询的全部字段中的部分字段去重,它的作用主要是:获取数据表中以分组字段为依据的其他统计数据。
-------- 从性能角度看:
两者执行方式不同,distinct主要是对数据两两进行比较,需要遍历整个表。group by分组类似先建立索引再查索引,当数据量较大时,group by速度要优于distinct。
hive的执行流程
客户端提交到接口 ,解析 校验 优化 执行,mr任务关联元数据库
解释一下hive 的 skew join?
set hive.optimize.skewjoin = true;
开启后,在运行时,会对数据进行扫描并检测哪个key会出现倾斜,对于会倾斜的key,用map join做处理,不倾斜的key正常处理。
hive 几种join
内连接 ,左右外联 ,全连接 ,笛卡尔积,(mapjoin ,skew join 是开启配置 实现 shuffle前对数据分配,另一个是应对数据倾斜的)
hive 行转列列转行
多行转一列:一般用case when,再做一个group by 去掉0值。
一行转多列:lateral view
select t.gameId, singleTag
from (
select gameId, tags from gamepublish.knights_game where date=20181127 limit 20
) t LATERAL VIEW explode(t.tags) v as singleTag
应该case when sum group by name
列转行:concat_ws
distinct 和 group by
在语义相同,有索引的情况下
group by和distinct都能使用索引,效率相同。
在语义相同,无索引的情况下:
distinct效率高于group by。原因是distinct 和 group by都会进行分组操作,但group by可能会进行排序,触发filesort,导致sql执行效率低下。
以上是关于常见大数据面试题汇总带答案的主要内容,如果未能解决你的问题,请参考以下文章