(美团)
一、网络每层的协议
物理层:比特
数据链路层:帧 (网桥,交换机)
网络层:数据报 (路由器)
运输层:报文段/用户数据报
应用层:报文
二、RPC和Restful的区别,serviceMatch是什么
RPC:调用本地服务(方法)一样调用服务器的服务(方法),RPC框架需要考虑解决通讯(长短连接)、寻址(IP、端口、方法名)、序列化与反序列化(二进制数据的序列化和反序列化);
Restful:基于HTTP协议,通过HTTP协议定义的通用动词方法(GET、PUT、DELETE、POST) ,以URI对网络资源进行唯一标识;
区别:
1、从使用来看,Http接口只关注服务提供方(服务端),对于客户端怎么调用,调用方式怎样并不关心;而RPC服务则需要客户端接口与服务端保持一致,服务端提供一个方法,客户端通过接口直接发起调用;
2、 从性能角度看,使用Http时,Http本身提供了丰富的状态功能与扩展功能,但也正由于Http提供的功能过多,导致在网络传输时,需要携带的信息更多,从性能角度上讲,较为低效。而RPC服务网络传输上仅传输与业务内容相关的数据,传输数据更小,性能更高;
三、死锁产生的原因
什么是死锁
死锁是指多个进程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进
死锁产生的条件
- 互斥:一个资源每次只能被一个进程使用。
- 请求与保持:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不可剥夺:进程已获得的资源,在末使用完之前,不能强行剥夺。
- 循环等待:若干进程之间形成一种头尾相接的循环等待资源关系。
打破死锁的方法
- 打破互斥条件:将独占式资源改为虚拟资源(不太可行)
- 打破请求与保持条件:采用资源预分配策略,即进程运行前申请全部资源,满足则运行
- 打破不可剥夺条件:当一个进程占有一独占性资源又申请另一独占性资源而无法满足时,则放出原占有的资源
- 打破循环等待条件:实现资源有序分配策略
四、CPU占用升高的原因
首先我们通过top
命令查看当前CPU消耗过高的进程是哪个,从而得到进程id;然后通过top -Hp <pid>
来查看该进程中有哪些线程CPU过高,一般超过80%就是比较高的,80%左右是合理情况。这样我们就能得到CPU消耗比较高的线程id。接着通过该线程id的十六进制表示(printf "%x\n" )在jstack(jstack 进程ID|grep tid(16进制线程小写英文)-A60)日志中查看当前线程具体的堆栈信息。
在这里我们就可以区分导致CPU过高的原因具体是Full GC次数过多还是代码中有比较耗时的计算了。如果是Full GC次数过多,那么通过jstack
得到的线程信息会是类似于VM Thread之类的线程,而如果是代码中有比较耗时的计算,那么我们得到的就是一个线程的具体堆栈信息。如下是一个代码中有比较耗时的计算,导致CPU过高的线程信息:
参考:https://blog.csdn.net/u013256816/article/details/94518811
(小米)
五、索引失效的情况
- 不在索引列上做任何操作(计算,函数,(自动或者手动)类型装换),会导致索引失效而导致全表扫描;
- 使用不等于(!= 或者<>)的时候,无法使用索引,会导致索引失效
- 使用is not null 或者 is null会导致无法使用索引
- like查询是以%开头,索引会失效变成全表扫描,覆盖索引。
- 如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)。要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引
- 如果mysql使用全表扫描要比使用索引快,则不会使用到索引
查看一条SQL是否使用了索引,可以在前面加上EXPLAIN关键字
上图为使用了索引,下图没有。只要type类型不是ALL,就是使用了索引。其他类型可参照 https://www.cnblogs.com/david97/p/8072164.html
复合索引的生效规则
最佳左前缀原则——从前往后依次使用生效,如果中间某个索引没有使用,那么断点前面的索引起作用,断点后面的索引不起作用
(0) select * from mytable where a=3 and b=5 and c=4;
abc三个索引都在where条件里面用到了,而且都发挥了作用
(1) select * from mytable where c=4 and b=6 and a=3;
这条语句列出来只想说明 mysql没有那么笨,where里面的条件顺序在查询之前会被mysql自动优化,效果跟上一句一样
(2) select * from mytable where a=3 and c=7;
a用到索引,b没有用,所以c是没有用到索引效果的
(3) select * from mytable where a=3 and b>7 and c=3;
a用到了,b也用到了,c没有用到,这个地方b是范围值,也算断点,只不过自身用到了索引
(4) select * from mytable where b=3 and c=4;
因为a索引没有使用,所以这里 bc都没有用上索引效果
(5) select * from mytable where a>4 and b=7 and c=9;
a用到了 b没有使用,c没有使用
(6) select * from mytable where a=3 order by b;
a用到了索引,b在结果排序中也用到了索引的效果,前面说了,a下面任意一段的b是排好序的
(7) select * from mytable where a=3 order by c;
a用到了索引,但是这个地方c没有发挥排序效果,因为中间断点了,使用 explain 可以看到 filesort
(8) select * from mytable where b=3 order by a;
b没有用到索引,排序中a也没有发挥索引效果
MySQL主要提供2种方式的索引:B-Tree索引,Hash索引
B树索引具有范围查找和前缀查找的能力,对于有N节点的B树,检索一条记录的复杂度为O(LogN)。相当于二分查找。
哈希索引只能做等于查找,但是无论多大的Hash表,查找复杂度都是O(1)。
显然,如果值的差异性大,并且以等值查找(=、 <、>、in)为主,Hash索引是更高效的选择,它有O(1)的查找复杂度。
如果值的差异性相对较差,并且以范围查找为主,B树是更好的选择,它支持范围查找。
六、Mybatis中 ${} 和 #{} 的区别
使用#{}意味着使用的预编译的语句,即在使用jdbc时的preparedStatement,sql语句中如果存在参数则会使用 ? 作占位符,并且在使用#{}时形成的sql语句,已经带有引号,也就是说默认当成字符串处理;
使用${}时的sql不会当做字符串处理,是什么就是什么。
所以,我们最好是能用#{}则用它,因为它可以防止sql注入,且是预编译的,在需要原样输出时才使用${},如,
select * from ${tableName} order by ${id} 这里需要传入表名和按照哪个列进行排序。