其他互联网大厂面试题
下载链接:全部大厂面试题及答案PDF
1.简历写什么问什么,注意所⽤技术产品的同类产品⽣态及对⽐。
2.kafka数据分区和消费者的关系, kafka的数据offset读取流程, kafka内部如何保证顺序,结合外部组件如何保证消费者的顺序
1 、 kafka数据分区和消费者的关系: 1个partition只能被同组的⼀个consumer消费,同组的consumer则起到均衡效果
2 、 kafka的数据offset读取流程
1.连接ZK集群,从ZK中拿到对应topic的partition信息和partition的Leader的相关信息
2.连接到对应Leader对应的broker
3.consumer将⾃⼰保存的offset发送给Leader
4.Leader根据offset等信息定位到segment (索引⽂件和⽇志⽂件)
5.根据索引⽂件中的内容,定位到⽇志⽂件中该偏移量对应的开始位置读取相应⻓度的数据并返回给consumer
3 、 kafka内部如何保证顺序:
kafka只能保证partition内是有序的,但是partition间的有序是没办法的。爱奇艺的搜索架构,是从业务上把需要有序的打到同⼀ 个partition。
3.cms垃圾回收机制
1、概念: CMS全称 Concurrent Mark Sweep,是⼀款并发的、使⽤标记 -清除算法的垃圾回收器,
2 、使⽤场景: GC过程短暂停,适合对时延要求较⾼的服务,⽤户线程不允许⻓时间的停顿。
3、缺点:
1 、服务⻓时间运⾏,造成严重的内存碎⽚化。
2 、算法实现⽐较复杂(如果也算缺点的话)。
4 、实现机制:根据GC的触发机制分为:
1 、周期性Old GC (被动): 2s执⾏⼀次;
2 、主动Old GC:触发条件:
i. YGC过程发⽣Promotion Failed,进⽽对⽼年代进⾏回收
ii. ⽐如执⾏了System.gc(),前提是没有参数ExplicitGCInvokesConcurrent
iii. 其它情况...
4.mapreduce原理
1、简介: mapreduce源⾃google的⼀篇⽂章,将海量数据处理的过程拆分为map和reduce。 mapreduce 成为了最早的分布式计算框 架,这样即使不懂的分布式计算框架的内部运⾏机制的⽤户,也可以利⽤分布式的计算框架实现分布式的计算,并在hadoop上⾯运⾏。
2 、设计思想:
hadoop ⽂件系统 ,提供了⼀个分布式的⽂件系统,但是hadoop⽂件系统读写的操作都涉及到⼤量的⽹络的操作,并不能很好 的完成实时性⽐较强的任务。
但是hadoop可以给上⾯的应⽤提供⼀个很好的⽀持。⽐如hadoop⽂件系统上⾯可以运⾏mapreduce。 mapreduce是⼀个计算的 框架, mapreduce是⼀个分布式的计算框架,这样mapreduce利⽤分布式的⽂件系统,将不同的机器上完成不同的计算,然后就计算结果 返回。这样很好的利⽤了分布式的⽂件系统。
数据分布式的存储,然后计算的时候,分布式的计算,然后将结果返回。这样的好处就是不会涉及到⼤量的⽹络传输数据。
3、优点: mapreduce的计算框架的优点是,极强的扩展能⼒,可以在数千台机器上并发的执⾏。其次,有很好的容错性,另外,就 是向上的接⼝简洁。⽤户只需要写map和reduce函数,即可完成⼤规模数据的并⾏处理。
4、缺点: mapreduce并不适合对实时性要求⽐较⾼的场景,⽐如交互式查询或者是流式计算。另外,也不适合迭代类的计算(⽐如 机器学习类的应⽤)。
1、mapreduce的启动时间⽐较长,对于批处理的任务,这个问题并不算⼤。但是对于实时性⽐较⾼的任务,其启动时间长的缺点就很 不合适了。
2、mapreduce⼀次执⾏的过程⾥⾯,往往涉及到多出磁盘读写,以及⽹络的传输。对于迭代的任务,这样很好的开销需要很多次,明显降低了效率。
3、⽽Storm和Spark,⼀个是流式计算的框架,⼀个是机器学习的框架。他们更适合解决这类型的任务。
5.nio,bio,sellector/epoll,aio,netty⾃带编解码器, netty优势, java内存模型
Netty⾼性能:
1、NIO异步⾮阻塞通信
2、“零拷⻉ ”
3、内存池ByteBuf
4、Netty提供了多种内存管理策略,通过在启动辅助类中配置相关参数,可以实现差异化的定制。
5、⾼效的 Reactor线程模型: Reactor单线程(多线程、主从)模型,指的是所有的IO操作都在同⼀个NIO线程上⾯完成
6、为了尽可能提升性能, Netty采⽤了串⾏⽆锁化设计,在IO线程内部进⾏串⾏操作,避免多线程竞争导致的性能下降。表⾯上看,串⾏化设计似乎CPU利⽤率不⾼,并发程度不够。但是, 通过调整NIO线程池的线程参数,可以同时启动多个串⾏化的线程并⾏运⾏,这种局部⽆锁化的串 ⾏线程设计相⽐⼀个队列 -多个⼯作线程模型性能更优。
7、⾼效的并发编程: Netty的⾼效并发编程主要体现在如下⼏点:
-
volatile的⼤量、正确使⽤;
-
CAS和原⼦类的⼴泛使⽤;
-
线程安全容器的使⽤;
-
通过读写锁提升并发性能。
8、⾼效的序列化框架:
9、灵活的 TCP参数配置能⼒:合理设置TCP参数在某些场景下对于性能的提升可以起到显著的效果,例如SO_RCVBUF和SO_SNDBUF。如果设置不当,对性能的影响是⾮常⼤的。
6.akka模型
1、概念: Akka是⼀个构建在JVM上,基于Actor模型的的并发框架,为构建伸缩性强,有弹性的响应式并发应⽤提⾼更好的平台。
2 、Actor模型: Akka的核⼼就是Actor,所以不得不说Actor, Actor模型我通俗的举个例⼦,假定现实中的两个⼈,他们只知道对⽅ 的地址,他们想要交流,给对⽅传递信息,但是⼜没有⼿机,电话,⽹络之类的其他途径,所以他们之间只能⽤信件传递消息,很像 现实中的的邮政系统,你要寄⼀封信,只需根据地址把信投寄到相应的信箱中,具体它是如何帮你处理送达的,你就不需要了解了, 你也有可能收到收信⼈的回复,这相当于消息反馈。上述例⼦中的信件就相当于Actor中的消息, Actor与Actor之间只能通过消息通信。
7.java arraylist,linkedlist区分及实现原理, hashmap和concurrenthashmap区分及实现原理, concurrenthashmap 1.7和1.8区分, 实现细节, linkedhashmap排序原理,应⽤如何保证数据幂等
1 、java arraylist,linkedlist区分及实现原理:
1. ArrayList是实现了基于动态数组的数据结构,⽽LinkedList是基于链表的数据结构;
2. 对于随机访问get和set, ArrayList要优于LinkedList,因为LinkedList要移动指针;
3. 对于添加和删除操作add和remove,⼀般⼤家都会说LinkedList要⽐ArrayList快,因为ArrayList要移动数据。
2 、 concurrenthashmap 1.7和1.8区分:
去除 Segment + HashEntry + Unsafe的实现,改为 Synchronized + CAS + Node + Unsafe的实现其实 Node 和 HashEntry 的内容⼀样,但是HashEntry是⼀个内部类。
⽤ Synchronized + CAS 代替 Segment ,这样锁的粒度更⼩了,并且不是每次都要加锁了, CAS尝试失败了在加锁。 put()⽅法中 初始化数组⼤⼩时, 1.8不⽤加锁,因为⽤了个 sizeCtl变量,将这个变量置为-1,就表明table正在初始化。
3 、 linkedhashmap排序原理:
public LinkedHashMap() {
// 调⽤HashMap的构造⽅法,其实就是初始化Entry[] table
super();
// 这⾥是指是否基于访问排序,默认为false
accessOrder
}
1 、 LinkedHashMap存储数据是有序的,⽽且分为两种:插⼊顺序和访问顺序。默认为插⼊顺序。
2 、 LinkedHashMap有⾃⼰的静态内部类Entry,它继承了HashMap.Entry,定义如下 :
Entry<K ,V> extends HashMap .Entry<K ,V> {
// These fields comprise the doubly linked list used for iteration
Entry<K ,V> before , after ;
Entry(int hash , K key , V value , HashMap .Entry<K ,V> next)
super(hash , key , value , next) ;
}
3、所以LinkedHashMap构造函数,主要就是调⽤HashMap构造函数初始化了⼀个Entry[] table,然后调⽤⾃身的init初始化了⼀ 个只有头结点的双向链表。
8.⽆穷数就top K问题,提供多个⽅案
1 、最简单且最容易想到的算法是对数组进⾏排序(快速排序),然后取最⼤或最⼩的 K个元素。总的时间复杂度为 O(NlogN)+O(K)=O(NlogN)。该算法存在以下问题:
1. 快速排序的平均复杂度为O(N*logN),但最坏时间复杂度为O(n2),不能始终保证较好的复杂度
2. 只需要前k⼤或k⼩的数 , ,实际对其余不需要的数也进⾏了排序,浪费了⼤量排序时间
总结:通常不会采取该⽅案。
2 、虽然我们不会采⽤快速排序的算法来实现TOP-K问题,但我们可以利⽤快速排序的思想,在数组中随机找⼀个元素key,将数组分 成两部分Sa和Sb,其中Sa的元素>=key, Sb的元素<key,然后分析两种情况:
1. 若Sa中元素的个数⼤于或等于k,则在Sa中查找最⼤的k个数
2. 若Sa中元素的个数⼩于k,其个数为len,则在Sb中查找k-len个数字
如此递归下去,不断把问题分解为更⼩的问题,直到求出结果。
3、寻找N个数中的第K⼤的数,可以将问题转化寻找N个数中第K⼤的问题。对于⼀个给定的数 p, 可以在O(N)的时间复杂度内找出 所有不⼩于P的数。
根据分析,可以使⽤⼆分查找的算法思想来寻找N个数中第K⼤的数。假设 N个数中最⼤的数为Vmax,最⼩的数为Vmin, 那么N个数 中第K⼤的数⼀定在区间[Vmin,Vmax]之间。然后在这个区间使⽤⼆分查找算法。
总结:该算法实际应⽤效果不佳,尤其是不同的数据类型需要确定max - min > delta,因此时间复杂度跟数据分布有关。 整个算法的 时间复杂度为O(N * log (Vmax-Vmin) /delta),在数据分布平均的情况下,时间复杂度为O(N * logN)。
4 、上⾯⼏种解法都会对数据访问多次,那么就有⼀个问题,当数组中元素个数⾮常⼤时,如: 100亿,这时候数据不能全部加载到 内存,就要求我们尽可能少的遍历所有数据。针对这种情况,下⾯我们介绍⼀种针对海量数据的解决⽅案。
在学习堆排序的过程中,我们知道了堆这种数据结构。为了查找Topk⼤的数,我们可以使⽤⼤根堆来存储最⼤的K个元素。⼤根堆的 堆顶元素就是最⼤ K个数中最⼩的⼀个。每次考虑下⼀个数x时,如果x ⽐堆顶元素⼩,则不需要改变原来的堆。如果想x ⽐堆顶元素⼤,那 么⽤ x替换堆顶元素,同时,在替换之后, x可能破坏最⼩堆的结构,需要调整堆来维持堆的性质。
总结:该算法只需要扫描所有的数据⼀次,且不会占⽤太多内存空间(只需要容纳K个元素的空间),尤其适合处理海量数据的场 景。算法的时间复杂度为O(N * logk),这实际上相当于执⾏了部分堆排序。
5 、TOP-K问题是⼀个经典的问题,这个问题是存在线性算法的,只不过算法的使⽤范围有⼀定的限制。如果所有N个数都是正整 数,且他们的取值范围并不⼤,可以考虑申请空间,记录每个整数出现的次数,然后再从⼤到⼩取最⼤的K个。实际就是利⽤计数排序的 思想。 假设所有整数都在(0, maxN)区间,利⽤⼀个数组count[maxN]来记录每个整数出现的次数。 count[i]表示整数i在N个数中出现 的次数。只需要扫描⼀遍就可以得到count数组,然后寻找第K⼤的元素。
这是⼀个典型的以空间换取时间的做法。当数组中取值范围⽐较⼤时,是及其浪费空间的。如[3,1...9999],为了求出最⼤的K个元 素,需要额外申请⼀个⻓度为10000的数组。
极端情况下,如果 N 个整数各不相同,我们甚⾄只需要⼀个 bit 来存储这个整数是否存在,这样可节省很⼤的内存空间。
9.a,b,c三张表,做关联查询,如何优化,可做外键,只在c表加a表外键即可。
-
对于要求全⾯的结果时,我们需要使⽤连接操作( LEFT JOIN / RIGHT JOIN / FULL JOIN);
-
不要以为使⽤MySQL的⼀些连接操作对查询有多么⼤的改善,核⼼是索引;
-
对被驱动表的join字段添加索引;