java常见疑难面试题及答案(阿里、蚂蚁、百度、美团)(三)

21.mysql两种引擎

MyISAM

1)不支持事务

2)不支持外键约束,只支持表锁

3)非聚集索引,索引文件的数据域存储指向数据文件的指针

4)支持全文索引

5)对于AUTO_INCREMENT类型的字段,可以和其他字段一起建立联合索引

Innodb

1)支持事务

2)支持行级锁和外键约束

3)主键索引采用聚集索引

4)不支持全文索引

22.什么是B树、B+树?

B树(B-树)是一种多路搜索树(不是二叉树),搜索时相当于二分查找。每个节点既保存索引,又保存数据。查询时间复杂度O(1)。

B+树是B树的变种,同样是多路,搜索时相当于二分查找。只有叶子节点保存数据,增加了相邻接点的指向指针(增加区间访问性)。查询时间复杂度是log(n)。

23.为什么Mysql使用B+树?

1)B+树的磁盘读写代价更低,B+树的内部节点并没有指向关键字具体信息的指针。

2)B+树的查询效率更加稳定,由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。

3)由于B+树的数据都存储在叶子结点中,分支结点均为索引。B+树只需要遍历叶子节点就可以实现整棵树的遍历,而B树不支持这样的操作或者说效率太低。在数据库中基于范围的查询是非常频繁的,所以通常B+树用于数据库索引。

24.如何设计一个高并发系统

1)系统拆分:拆分子系统,降低系统压力,同时数据库分开,减少数据压力

2)缓存:读多写少的数据可以放在缓存中,减少数据库压力

3)MQ:异步处理后续业务,削峰、解耦合。

4)分库分表:减少单表数据量,提高数据库操作性能

5)读写分离:数据库写主读从

6)ElasticSearch:一些比较简单的查询、统计、全文搜索的操作,可以考虑用 es 来承载

25.ArrayList,LinkedList的区别和使用场景

1)ArrayList是基于数组实现的,LinkedList是基于双链表实现的

2)ArrayList搜索和读取数据是很快的,可以直接返回数组中index位置的元素,但是要插入、删除数据却是开销很大的(除非靠近末尾),需要移动数组中插入、删除位置之后的的所有元素。

3)LinkedList的随机访问集合元素时性能较差,需要遍历双向链表,但是插入、删除操作非常快。(靠近末尾查找时间长)

4)LinkedList需要更多的内存,因为ArrayList的每个索引的位置是实际的数据,而LinkedList中的每个节点中存储的是实际的数据和前后节点的位置。

使用场景:

查询较多用ArrayList,插入、删除较多用LinkedList

26.加载器双亲委派模型及破坏

双亲委派是指特定的类加载器在接到加载类的请求时,首先将加载任务委托给父类加载器,如果父类加载器可以完成类加载任务,就成功返回。只有父类加载器无法完成此加载任务时,才去加载当前类。

可以避免重复加载,同时委派方式加载更加安全可靠

如果由各个类加载器自行加载的话,如果自己编写了一个称为java.lang.Object的类,那系统将会出现多个不同的Object类, Java类型体系中最基础的行为就无法保证。

双亲委派破坏

第一次:

JDK1.2引入双亲委派模型的时候,由于类加载器和抽象类java.lang.ClassLoader则是JDK1.0时候就已经存在,为了向前兼容,java.lang.ClassLoader添加了一个新的proceted方法findClass()。可以把自己的类加载逻辑写到findClass()方法中,在loadClass()方法的逻辑里,如果父类加载器加载失败,则会调用自己的findClass()方法来完成加载,这样就可以保证新写出来的类加载器是符合双亲委派模型的。

第二次:

双亲委派模型解决了各个类加载器的基础类统一问题,但是如果基础类又要调用用户的代码,却无法实现。
因此在java设计团队添加了线程上下文件类加载器(Thread Context ClassLoader)。这个类加载器可以通过java.lang.Thread类的setContextClassLoader()方法进行设置,如果创建线程时还未设置,它将会从父线程中继承一个。如果在应用程序的全局范围内都没有设置过,那么这个类加载器默认就是应用程序类加载器。有了线程上下文类加载器,可以通过使用这个线程上下文类加载器去加载所需要的代码。Java中所有涉及SPI(Service Provider Interface,通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类)的加载动作基本上都采用这种方式,例如JNDI,JDBC,JCE,JAXB和JBI等。

第三次:
用户对程序的动态性的追求导致的,例如OSGi(Open Service Gateway Initiative,以Java为技术平台的动态模块化规范)的出现。在OSGi环境下,类加载器不再是双亲委派模型中的树状结构,而是网状结构。

27.跳表怎么实现的

跳表是一种随机化的数据结构,原有链表上添加多级索引,通过索引实现快速查找,每个元素插入时随机生成它的level(防止索引节点下数据过多,跳表退化成单链表),最低层包含所有的元素。遍历链表的时候通过索引遍历,减少遍历次数。时间复杂度能做到 O(logn) ,但是数据结构所占空间是2N。

目前开源软件 Redis 和 LevelDB 都有用到它,效率和红黑树差不多(查找区间内所有元素效率比红黑色略高

28.什么是NginX,如何做负载均衡

Nginx是一个使用c语言开发的高性能http服务器,能够支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定。

1)反向代理:接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端。

2)动静分离:所有动态资源的请求交给应用服务器,静态资源的请求(图片、视频、CSS、JavaScript文件等)则直接由Nginx返回到浏览器,这样能大大减轻应用服务器的压力

3)负载均衡:当用户访问网站时,选择一台压力较小的服务器,然后将该访问请求引入该服务器,保证服务器集群中的每个服务器压力趋于平衡。负载均衡配置一般都需要同时配置反向代理,通过反向代理跳转到负载均衡。

Nginx的负载均衡是通过upstream实现的

1)轮训,请求按时间顺序逐一分配到不同的后端服务器,如果后端某台服务器宕机,故障系统被自动剔除。

upstream webname {  
server 192.168.0.1:8080;  
server 192.168.0.2:8080;  

2)权重,权重和访问比率成正比,用于后端服务器性能不均的情况。

upstream webname {  
server 192.168.0.1:8080 weight 2;  
server 192.168.0.2:8080 weight 1;  

3)按后端服务器的响应时间来分配请求,响应时间短的优先分配。(需要下载Nginx的upstream_fair模块)

upstream webname {  
server 192.168.0.1:8080;  
server 192.168.0.2:8080;
fair;

4)按访问URL的hash结果来分配请求,使每个URL定向到同一个后端服务器。(需要安装Nginx 的hash软件包,且在upstream中加入hash语句后,server语句不能写入weight等其他参数)

upstream webname {  
ip_hash;  
server 192.168.0.1:8080;  
server 192.168.0.2:8080;  

29.一致性哈希的一致性是什么意思?

按照hash算法,将节点哈希到一个具有2的32次方个桶的环中。对数据进行哈希计算,按顺时针方向将其映射到离其最近的节点上。(SortedMap::tailMap)

当有节点出现故障时,按照算法的映射方法,受影响的仅仅为环上故障节点开始逆时针方向至下一个节点之间区间的数据对象。当有节点出现变动时,将新增节点开始逆时针方向至下一个节点之间区间的数据重新映射,不会影响所有节点。

为了满足平衡性引入了虚拟节点,虚拟节点是实际节点在 hash 空间的复制品,一个实际节点对应了若干个虚拟节点,虚拟节点在 hash 空间中以hash值排列。(虚拟节点的hash计算可以采用对应节点的IP地址加数字后缀的方式)

30.数据库三大范式

一范式(1NF)数据库表每一项都是不可再分的项,所有的属性都是单一的。

二范式(2NF)是建立在一范式的基础上的,表中要有一列属性可以将实体完全区分,这个属性就是主键,即每一个属性完全依赖于主键。非主属性不能依赖于主键的部分属性,必须依赖于主键的所有属性。

三范式(3NF)是建立在二范式的基础上的。一个数据表中不能包含已经在别的表中的非关键信息,属性不依赖其他非主属性。

你可能感兴趣的:(java常见疑难面试题及答案(阿里、蚂蚁、百度、美团)(三))