文写这篇主要是想复盘一下我的两次面试经历,一个是B站的后端开发岗,另一个是百度的搜索研发。文章涵盖了MySQL、Golang、 计算机网络、Elasticsearch、 分布式、搜索的一些知识。
写在前面
1.你之前是负责搜索的,那我想听一下你们搜索系统的大致流程
说实在还挺惊讶面试官会问这个的,因为对方是一个后端工程师,所以就没讲多细致,答的很general,大体来说就是,query分析->粗排召回->精排算特征-> learning to rank计算score ->返回结果,每个再展开来说一些即可。面试官问这个相当于在问项目,确定简历的真实性,所以这个没啥参考性。
2.MySQL的事务隔离级别有哪些?
总共是四大隔离级别,理解以后用自己的话答就好了
面试官还是比较满意这个答案的,但接下来面试官问:
3.以上事务隔离是如何实现的?
老实回答,这题我不会,面试官提示MVCC,我还是不会hhh。回去翻了一些资料,在这里补充一下答案。所谓的MVCC就是MultipleVersion Concurrency Control,多版本并发控制,从名字上也可以看出来,它是使用版本号来对数据进行并发控制的。实际上,在数据表的每一列,都存储两个隐藏列,一个是trx_id,代表事务的ID,另一个是roll_pointer,指向其上一个版本的记录,如此组成一个记录的版本链,接下来就可以讲ReadView了,它存储着一种用来记录当前活跃状态的读写事务,用于判定该transaction可见到的数据版本。
4.MySQL索引的原理是什么?
B+树,本质上它是将瘦长的平衡二叉树,改造成一个矮扁的平衡多叉树从而减少IO查询次数,平均查询复杂度仍能保证O(logN),另外与B树不同的是,除了叶子结点外,其他结点均不存储数据,另外叶子结点之间,用链表方式相连以加速查询。当然视面试官的反应,可以再补充B+树的插入和删除操作。
5.MySQL建立索引时,应该注意什么?
这个按照自己的经验来回答了,三点:1.对区分度高的列做索引, 对于那种只有两三个值的做索引并没有多大意义。2.建立联合索引时要满足最左匹配原则,例如SELECT * FROM TABLE WHERE A=1 AND B=2 AND C=3,此时需要对ABC建联合索引, 对ABC单独建三个索引是没用的。面试官又问,那我对BAC建联合索引就命中不了索引了吗?我说是的,被面试官怼了一下,其实MySQL在很久以前就在查询优化器里加入了这个feature,是可以命中的。3.只对需要作为查询条件的列建索引,否则会拖慢插入速度。
6.MySQL存储引擎由哪些?他们有什么区别?应用场景是怎样的
也是一道经典MySQL题了,主要分为Innodb和MyISAM,最主要的区别在于InnoDB采用的簇集索引,MyISAM采用的是非簇集索引。
对于非簇集索引来说,叶子结点存放的值实际上是data域的地址,data和 索引是完全分离的。
7.用户从输入URL到看到浏览器展示结果,经过了哪些过程?越详细越好。
8.redis的数据类型有哪些?在哪些场景使用?
string, set, list, hash dict, zset
string就是经常用的key value键值对;
hash dict可以表示一个对象,是一个field和value的映射表;
set就是集合,用hash来实现的;
list本质上是个双端队列, 可以实现从左边add也可以从右边add
zset是有序集合, 用跳表来实现,可以用来实现实时排行榜。
9.redis设置过期时间的原理是怎样的?
这个我没有看过,但是我猜了两种策略,给猜对了:1.惰性删除,像限流器那样,只有在get的时候去检查它是否expire,如果过期,就删除。2.定时删除。 具体的我没想对,回去看了一下,官方给出的答案是这样的:
Specifically this is what Redis does 10 times per second:
Test 20 random keys from the set of keys with an associated expire.
Delete all the keys found expired.
If more than 25% of keys were expired, start again from step 1.
也就是说,每秒做10次这样的行为: 从所有设置过期时间的key中, 随机选择20个key,删除所有过期的key, 如果25%的key都过期了,就回到步骤1再做一次。
10.你刚才提到了限流器,如何实现一个限流器?
限流器的原理就是令牌桶,按照一定的时间往桶里加入Token,如果桶已经满了丢弃令牌。每个新请求就消耗一个token, 如果token没了就拒绝服务请求。新请求来临时,会请求从桶中拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务请求,它的所有计算本质上都是惰性计算。
11.Goroutine为什么这么轻?
简单来说,因为它是发生在操作系统的用户态的,不需要进入内核态进行系统调用,操作系统的上下文切换会带来很大的开销,切goroutine和线程一样,共享堆,不共享栈。
Golang的垃圾回收是怎么做的?
很早之前看过,刚好被问到了就答的比较顺利。三色并发标记,基本思想是把内存中的所有对象分为黑白灰三类,一开始所有对象都是白色对象,然后把所有可达对象标记为灰色,再从所有灰色对象出发,将所有触及到的对象标记为灰色,自身灰色标记为黑色对象,如此循环往复,直到没有灰色对象为止,由于每次标记剩下的都是不可达的白色对象,所以直接将白色对象删除即可。
全部评论
(1) 回帖