早上10点,开始了腾讯面试。在4.2投递,内推官叫我别填项目经验,防止别的部门锁了。然后经历了被锁,不面试,困了8天,等了两天,不知道是不是要结束了,始终没有人捞。
终于,在内推即将结束的前6天 , 找实验室师兄联系他同事,得到了一次面试的机会。
最后的评价是:做的很多,但是不了解原理,不会主动去学习。。
本科生,发了ei,sci,也开发了上线项目,还是第一次有人说我不主动学习。。所以,面试的时候,一定要让对方充分了解你,不然很可能就。。。哎,正式批见。
凉经献上:
1. hashmap的变化:红黑树的效率,冲突解决方法除了拉链法和开放定址法,还有什么吗?
答:红黑树是为了解决拉链法的链表过长带来的查询效率底下的问题。除了拉链和开放定址外,面试官还说有二维数组法。
2. 操作系统的fork操作,带来的进程问题,通信问题。(问我fork。。还真的不了解,java对这个涉及挺少的)
答:
- 一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
- 一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
3. 怎么解决bug问题,有用日志吗?
有的,解决bug,生产环节是debug。部署环节是log,log看不出则jstack去dump出堆信息。
4. redis怎么实现缓存同步的?(当时说项目没有用,但是忘了补充说知道原理和方式。面试经验不足)
答:项目中reids只是一个读取的作用,写入的数据,都是直接写入mysql,而读取的数据都是永远不变的,比如学校名字之类的。不过,要想进行缓存同步,还是有几种方案的。
- 首先,可以采用回写的方式,每次更新完数据库后,立即同步redis。
- 也可以采用先更新redis,再去同步mysql。而后,还可以通过异步的方式,利用消息队列,进行数据库同步。即:写入了redis后,由消息队列进行一个同步的操作。
- 当然,为了保证可用性,我们redis要设置为集群,代码写好对应的降级服务,察觉到了reids无法写入,我们先写入mysql。等待reids恢复后,redis根据日志完成同步后,再进一步此期间发生改变的mysql。
5. reids的缓存穿透和缓存雪崩问题和避免方式。(这方面没有仔细看,结果被重点问了,没回答好)
答:
- 缓存穿透:大量请求某个不存在的数据。方式一:自己创建这个数据,key是数据查询名,value为空,存入redis,时间设置短一点,可以防止别人进行穿透攻击mysql。方式二:还可以采用过滤的方式,讲这个不存在的数据直接过滤了。相当于降级服务。
- 缓存雪崩:假设大量的数据都缓存了一个小时,那么到了一个小时后,这批缓存就都过期了。此时,mysql的访问会大大增加,可能会顶不住。方式一:采用消息队列给请求排排队,一个个来。方式二:数据的缓存进行随机偏移。在一个小时的基础上,偏移一个较小的随机数。方式三:使用互斥锁:jvm锁机制;分布式锁机制,实现给大量请求排排队,结合双重检验原则,还可以让他们中,只有一个请求进行了更新,其他人又回去redis取数据。方式四:双缓存机制。一个备用缓存redis节点,当主缓存redis无法读取,mysql获取锁失败的时候,就直接去备份redis中取数据(注意,这个redis中的数据,应该是比主redis要持久点,才可以保证去备用redis取数据是行得通的)。
- 缓存击穿:类似于穿透,都是想跳过redis,对mysql下手。通过短时间内大量访问一个mysql中有的数据,而redis中没有的数据,从而使得mysql负荷变大。方式:设置热点数据(如果不是恶意攻击,我们是可以知道那个数据存在被大量访问的情况的)永不过期;加互斥锁,强制同步。
6. 双重检验锁在单例模式的应用
答:当同一时刻来访的线程,发现没有实例时,会进入同步代码段,在其中进行new,而后,一个new出来了,另一个进入此段代码,也有一个判断,是否对象被new出来。此时,结果是:已经new出来了。那么,他就不会在new,确保了单例模式。
7. tcp怎么接受分批来的报文?(粘包问题还是大一的时候看的,忘得差不多了,复习没看,回答的不好)
答:有个缓冲区,接收到的tcp数据放入缓存区,由应用层主动读取数据;
发送的时候,也是有缓冲区,缓冲区满了,或者一定时间到了,进行send的。
这两个会引出粘包问题。
6. ssl是怎么实现安全的?
答:
答:
基本考察的知识点是:慢查询,explain查看使用何种索引,针对sql优化,建立联合索引,索引覆盖,或者避免索引无效情况。
针对查询时间过长问题:
- 进行建立复合索引的方式优化。
- 重构查询,将复杂查询转化为几条简单查询;
- 重构查询,将查询大量数据的语句,改为查询几次,每次只查询一小部分。
- 分解关联查询,涉及多个表的时候,每次查询一个表的数据,返回到java后台,进行逻辑处理。(将查询分解后,执行单个查询可以减少锁的竞争。让缓存的效率更高。)
- 查询的速度快慢是从全表扫描到索引扫描、范围扫描、唯一索引查询、常数引用等。
- 一般来说,可以直接唯一索引用where查询的,会在存储引擎层面完成任务,最快;而通过索引覆盖的方式完成查询的,是在mysql服务器层完成任务;而从数据库查出数据,再进行嵌套,过滤之类的操作的,是很慢的。
- 如果说发现查询需要扫描大量的数据但只返回少数的行,使用索引覆盖合适,或者可以单独建立一个表格
9. mysql的两个引擎的差别
答:
- innodb支持行级锁和外键,而myisam不支持
- innodb没有缓存行数,myisam缓存了
- innodb删除一个表是一行行删除的,myisam是直接删除表
- innodb存储文件是索引和数据放在一起,而myisam是拆分的
- innodb比较适合修改多的情况,而myisam是查询
10. mysql的慢查询日志
答:慢查询是mysql提供的一种日志机制,可以记录一个sql语句使用的查询时间和排队时间等信息,从而找出有问题的sql语句。分析原因:是查询时间消耗过多,还是在哪儿被阻塞了,如等I/O操作完成,也可能使行锁等,或者是网络太慢,出现了网关配置问题。
13. tcp和udp的差别
答:
- tcp是面向连接的字节流,提供可靠服务;udp是面向数据报文的,尽最大努力交付
- tcp有拥塞控制,丢失重传等功能,而udp没有
- tcp发送数据都将按序到达,udp没有
- tcp是一对一的,udp可以广播
- tcp适用于一些安全性比较高的场景,udp则是快速响应的场景
- tcp占用资源高。udp低
14. tcp发送多个大文件的时候,会怎么发送和接收?udp呢?
答:会将文件分组发送。
其中,发送是send函数进行发送,本质就是一个fifo队列,sendQ。所有的数据放入队列中(在一个缓冲区),而后,一定的时间,或者缓冲区满了,将会push发送。
接收端收到数据,将放入recvQ,一个接受队列,在缓冲区中。而后是一个recv函数调用,负责将队列中的数据取出,通知应用层读取处理。
同时,发送端为了将多个发往接收端的包,更加高效的的发给接收端,于是采用了优化算法(Nagle算法),将多次间隔较小、数据量较小的数据,合并成一个数据量大的数据块,然后进行封包。此时,可能出现粘包问题。
粘包就是指:两个文件的包被封装到一个大的包内。由于tcp是面向字节流传输的,所以,客户端直接识别一个大包内的数据,是识别不出,包内有两个文件的字节的。这就是粘包问题。
解决方案:
- 可以设置sleep(),让send保证隔一段时间发送,这样每次发送的都是一组,没有封包(下策);
- tcp进行短链接,哪怕是发送一次大文件,也发送一个组,断开一次。不采用http1.1后的长连接方式;(下策)
- TCP提供了强制数据立即传送的操作指令push
- 可以关闭send的优化算法nagle,不要进行封包;
- 可以在发送的时候,在每一组的头部记录分组长度,让服务器可以判断出,一组的分割位置(上策);
- 也可以两边协商,每读取到200个字节,就视为一组,客户端发送的时候也如此,即可实现;(上策)
- 设置特定的界定符,并且注意实现透明传输;(上策)
udp不会出现这种情况,udp的缓存区无论多大,每次收到一个udp报文,服务端都是立刻调用recv传到应用层,然后应用层用链表进行排队。一个个处理信息,也就是自然而然就有了边界。tcp是有negal算法,不是一个信息就发送,而是发送端socket满了(或者到了时间)以后再发送数据。所以接收方一次recv,只解析一个头部,里面粘包的头部,不解析,就导致了丢包,数据错乱。
16. http的长连接是怎么实现的,和websocket的区别
答:
- websocket是长连接,通过字段keep-alive实现,每一个的通信,省略了握手,但是还是要header;而websocket则是正在的长连接,每次的消息,只要很少的header就好了
- http的长连接Keep-Alive不会永久保持连接,它有一个保持时间,是伪连接。
- keep-alive双方并没有建立正真的连接会话,服务端可以在任何一次请求完成后关闭。WebSocket 它本身就规定了是正真的、双工的长连接,两边都必须要维持住连接的状态。
17. 观察者模式:
实现监听的关键,主题中记录了很多的观察者。每次主题有更新,都调用观察者,进行同步更新。
全部评论
(26) 回帖