1.HotSpot为什么要把堆空间分为新生代和老年代?

答案解析:将java堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。
比如在新生代中,每次收集都会有大量对象死去,所以可以选择复制算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集。而老年代的对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以我们必须选择“标记-清除”或“标记-整理”算法进行垃圾收集

2.Tomcat中类加载的顺序?

答案:
当应用需要到某个类时,则会按照下面的顺序进行类加载:
1 使用bootstrap引导类加载器加载
2 使用system系统类加载器加载
3 使用应用类加载器在WEB-INF/classes中加载
4 使用应用类加载器在WEB-INF/lib中加载
5 使用common类加载器在CATALINA_HOME/lib中加载

3.为什么使用消息队列?

参考答案:面试官问你这个问题,期望的一个回答是说,你们公司有个什么业务场景,这个业务场景有个什么技术挑战,如果不用MQ可能会很麻烦,但是你现在用了MQ之后带给了你很多的好处。消息队列的常见使用场景,其实场景有很多,但是比较核心的有3个:解耦、异步、削峰。

4.请简单谈谈Redis 持久化机制

答:Redis是一个支持持久化的内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。
RDB是Redis默认的持久化方式。按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件。即Snapshot快照存储,对应产生的数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周期。( 快照可以是其所表示的数据的一个副本,也可以是数据的一个复制品。)
AOF:Redis会将每一个收到的写命令都通过Write函数追加到文件最后,类似于MySQL的binlog。当Redis重启是会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。
当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复

5.Memcache与Redis的区别都有哪些?

答:1)、存储方式 Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis有部份存在硬盘上,redis可以持久化其数据
2)、数据支持类型 memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型 ,提供list,set,zset,hash等数据结构的存储
3)、使用底层模型不同 它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。 Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
4). value 值大小不同:Redis 最大可以达到 1gb;memcache 只有 1mb。
5)redis的速度比memcached快很多
6)Redis支持数据的备份,即master-slave模式的数据备份

6.tomcat 中JVM如何调优?

GC调优
调优步骤
日志分析
1,监控GC的状态
使用各种JVM工具,查看当前日志,分析当前JVM参数设置,并且分析当前堆内存快照和gc日志,根据实际的各区域内存划分和GC执行时间,觉得是否进行优化;
 2,分析结果,判断是否需要优化
如果各项参数设置合理,系统没有超时日志出现,GC频率不高,GC耗时不高,那么没有必要进行GC优化;如果GC时间超过1-3秒,或者频繁GC,则必须优化;
 3,调整GC类型和内存分配
如果内存分配过大或过小,或者采用的GC收集器比较慢,则应该优先调整这些参数,并且先找1台或几台机器进行beta,然后比较优化过的机器和没有优化的机器的性能对比,并有针对性的做出最后选择;
4,不断的分析和调整
通过不断的试验和试错,分析并找到最合适的参数
5,全面应用参数
如果找到了最合适的参数,则将这些参数应用到所有服务器,并进行后续跟踪。

目的
GC的时间够小
GC的次数够少
发生Full GC的周期足够的长,时间合理,最好是不发生。
注:如果满足下面的指标,则一般不需要进行GC:
   Minor GC执行时间不到50ms;
   Minor GC执行不频繁,约10秒一次;
   Full GC执行时间不到1s;
   Full GC执行频率不算频繁,不低于10分钟1次;

 

7.HashMap 和 HashTable 有什么区别?

参考答案:①、HashMap 是线程不安全的,HashTable 是线程安全的;
②、由于线程安全,所以 HashTable 的效率比不上 HashMap;
③、HashMap最多只允许一条记录的键为null,允许多条记录的值为null,而 HashTable 不允许;
④、HashMap 默认初始化数组的大小为16,HashTable 为 11,前者扩容时,扩大两倍,后者扩大两倍+1;
⑤、HashMap 需要重新计算 hash 值,而 HashTable 直接使用对象的 hashCode

8.什么是Tomcat的Valve?

参考答案:在一个大的组件中直接处理这些繁杂的逻辑处理,使用管道(pipeline)可以把把多个对象连接起来,而Valve(阀门)整体看起来就像若干个阀门嵌套在管道中,而处理逻辑放在阀门上。 
管道(Pipeline)就像一个工厂中的生产线,负责调配工人(valve)的位置,valve则是生产线上负责不同操作的工人。

9.使用 MyBatis 的 mapper 接口调用时有哪些要求?

参考答案:
1)Mapper接口方法名和 mapper.xml 中定义的每个 sql 的 id 相同;
2)Mapper接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型相同;
3)Mapper接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的 resultType 的类型相同;
4)Mapper.xml文件中的 namespace 即是 mapper 接口的类路径。

10.请描述下JVM中对象创建需要的几个步骤?

参考答案:1)检查加载
先执行相应的类加载过程。如果没有,则进行类加载。
2)分配内存
分配方式两种:指针碰撞和空闲列表,java堆空间规整的话采用指针碰撞,不规整采用空闲列表
3)内存空间初始化
JVM需要将分配到的内存空间都初始化为零值(如int值为0,boolean值为false等等)。
4)设置
虚拟机要对对象进行必要的设置,例如这个对象是哪个类的实例、如何才能找到类的元数据信息、对象的哈希码、对象的GC分代年龄等信息。这些信息存放在对象的对象头之中。
5)对象初始化
最后调用构造方法。

11.Redis单线程为什么这么快?

参考答案:(一)纯内存操作
(二)单线程操作,避免了频繁的上下文切换
(三)采用了非阻塞I/O多路复用机制
(四)RESP协议简单

12.SpringCloud断路器的作用

参考答案:当一个服务调用另一个服务由于网络原因或者自身原因出现问题时 ,调用者就会等待被调者的响应,
当更多的服务请求到这些资源时,导致更多的请求等待,这样就会发生连锁效应,断路器就是解决这一问题的。
 
断路器有完全打开状态:
 一定时间内,达到一定的次数无法调用,并且多次检测没有恢复的迹象,断路器完全打开,那么下次的请求不会请求到该服务。
 半开:
短时间内有回复迹象,断路器会将部分请求发送给服务,当能正常调用时,断路器关闭。
 关闭:
当服务一直处于正常状态,能正常调用,断路器关闭。

13.为什么要有TIME_WAIT状态?

TIME_WAIT状态存在有两个原因。 
<1>可靠终止TCP连接。如果最后一个ACK报文因为网络原因被丢弃,此时server因为没有收到ACK而超时重传FIN报文,处于TIME_WAIT状态的client可以继续对FIN报文做回复,向server发送ACK报文。
<2>保证让迟来的TCP报文段有足够的时间被识别和丢弃。连接结束了,网络中的延迟报文也应该被丢弃掉,以免影响立刻建立的新连接。

14.什么是缓存穿透?如何解决?

参考答案:缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)。这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题。
解决办法;
最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

 15.什么是缓存雪崩?如何解决?

参考答案:缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间
(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。
缓存雪崩一般使用加锁( 最多的解决方案)来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。还有一个简单方案就时讲缓存失效时间分散开。

 

16.当出现Hash冲突时,Jdk时如何处理的?(算法跟数据结构)

参考答案:相同的数据通过hash函数得到相同的key值。这时候,就产生了hash冲突。解决hash冲突的方式有两种。一种是挂链式,也叫拉链法,在产生冲突的hash地址指向一个链表,将具有相同的key值的数据存放到链表中。。

17.HashSet和HashMap的区别是什么?JDK是如何实现HashSet的呢?(依旧是算法和数据结构哦)

参考答案:HashMap实现了Map接口 HashSet实现了Set接口
HashMap储存键值对 HashSet仅仅存储对象
使用put()方法将元素放入map中 使用add()方法将元素放入set中
HashSet内部就是使用HashMap实现,只不过HashSet里面的HashMap所有的value都是同一个Object而已

18.在java中守护线程和用户线程的区别?(并发面试题)

参考答案:java中的线程分为两种:守护线程(Daemon)和用户线程(User)。
任何线程都可以设置为守护线程和用户线程,通过方法Thread.setDaemon(bool on);true则把该线程设置为守护线程,反之则为用户线程。Thread.setDaemon()必须在Thread.start()之前调用,否则运行时会抛出异常。
两者的区别: 
唯一的区别是判断虚拟机(JVM)何时离开,Daemon是为其他线程提供服务,如果全部的User Thread已经结束,Daemon 没有可服务的线程,JVM关闭。
扩展:Thread Dump打印出来的线程信息,含有daemon字样的线程即为守护进程

19.死锁与活锁的区别,死锁与饥饿的区别?

参考答案:
死锁:是指两个或两个以上的进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 
产生死锁的必要条件: 
互斥条件:所谓互斥就是进程在某一时间内独占资源。
请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 
不剥夺条件:进程已获得资源,在末使用完之前,不能强行剥夺。 
循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
活锁:任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,失败。
活锁和死锁的区别在于,处于活锁的实体是在不断的改变状态,所谓的“活”, 而处于死锁的实体表现为等待;活锁有可能自行解开,死锁则不能。
饥饿:一个或者多个线程因为种种原因无法获得所需要的资源,导致一直无法执行的状态。

20.InnoDB引擎的主键索引是用什么数据结构存储的?普通索引又是用什么结构存储的?

答案解析: InnoDB使用B+Tree的方式存储索引。Innodb的一个表可能包含多个索引,每个索引都使用B+树来存储。而索引包括聚集索引(clustered index )和非聚簇索引(secondary index),聚集索引使用表的主键作为索引键,叶子节点包含表的所有字段。二级索引只包含索引键和聚集索引键(主键)的内容,不包括其他字段。

21.B+tree如何进行优化?

答案解析:创建索引的时候尽量使用唯一性大的列来创建索引,由于使用b+tree做为索引,以innodb为例,一个树节点的大小由“innodb_page_size”,为了减少树的高度,同时让一个节点能存放更多的值,索引列尽量在整数类型上创建,如果必须使用字符类型,也应该使用长度较少的字符类型。

22.为什么JDK1.8中的ConCurrentHashMap的get操作不需要加锁?

答案解析:
在1.8中ConcurrentHashMap的get操作全程不需要加锁,这也是它比其他并发集合比如hashtable、用Collections.synchronizedMap()包装的hashmap;安全效率高的原因之一。

get操作全程不需要加锁是因为Node的成员val是用volatile修饰的和数组用volatile修饰没有关系。

数组用volatile修饰主要是保证在数组扩容的时候保证可见性。

23.JDK13中对Socket做了什么优化?

答案解析:
用一个易于维护和Debug的,更简单、更现代的实现来取代java.net.Socket和java.net.ServerSocket。Socket和ServerSocket可以追溯到JDK1.0,它们的实现混合了Java和C代码,维护和调试都非常痛苦。而且其实现用线程栈来进行IO buffer,导致某些场景需要调大Xss。
全新实现的NioSocketImpl,用来取代PlainSocketImpl,它的优点如下:
1、非常容易维护和Debug;
2、直接使用JDK的NIO实现,不需要自己的本地代码;
3、结合了buffer cache机制,所以不需要用线程栈来进行IO操作;
4、用JUC的锁取代synchronized修饰的方法;

24.索引优化的几点原则

参考答案:
1. 尽量全值匹配
   如果你使用了复合索引,而你查询的列是索引列,不要使用select * 而用索引列

2. 最佳左前缀法则
   创建复合索引的时候,要考虑索引的使用场景,比如创建复合索引key(a,b,c) 在出现where条件的时候一定要出现a,只有a,b,c同时出现在where条件里,这个索引才是最高效的。

3. 不在索引列上做任何操作
       比如各种函数等,不要再索引列上使用

4. 范围条件放最后
在sql中经常需要使用between,<=等访问查询,如果范围查询的列为a,需要创建一个包括a,b,c的索引,索引创建顺序不应该是key(a,b,c)而应该是(b,c,a)

5. Like查询要当心
like查询的时候,尽量使用“关键字%”而不要使用“%关键字”后者会导致索引失效

6. 字符类型加引号
    如果是字符类型比如 sex char(1) 不要出现 where sex = 1 这样会导致索引失效,要 sex=’1’

25.Spring在Bean创建过程中是如何解决循环依赖的?

答:循环依赖只会存在在单例实例中,多例循环依赖直接报错。
A类实例化后,把实例放map容器中,A类中有一个B类属性,A类实例化要进行IOC依赖注入,这时候B类需要实例化,B类实例化跟A类一样,实例化后方map容器中。B类中有一个A类属性,接着B类的IOC过程,又去实例化A类,这时候实例化A类过程中从map容器发现A类已经在容器中了,就直接返回了A的实例,依赖注入到B类中A属性中,B类IOC完成后,B实例化就完全完成了,就返回给A类的IOC过程。这就是循环依赖的解决。

26.什么是Ajax长轮询?

答案:客户端使用ajax发出请求,服务器端会阻塞请求直到有数据传递或超时才返回。客户端JavaScript响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。当客户端处理接收的数据、重新建立连接时,服务器端可能有新的数据到达;这些信息会被服务器端保存直到客户端重新建立连接,客户端会一次把当前服务器端所有的信息取回。

27.什么是Server-sent-events?

答案:流方式(长连接),又叫Server-sent-events(SSE),是 HTML5规范的一个组成部分,服务器向客户端声明,接下来要发送的是流信息(streaming)。
也就是说,发送的不是一次性的数据包,而是一个数据流,会连续不断地发送过来。这时,客户端不会关闭连接,会一直等着服务器发过来的新的数据流。本质上,这种通信就是以流信息的方式,完成一次用时很长的下载。SSE 就是利用这种机制,使用流信息向浏览器推送信息。它基于 HTTP 协议,目前除了 IE/Edge,其他浏览器都支持。

28.Docker的CMD命令与ENTRYPOINT区别?

答:CMD指定的入口可以被覆盖,而ENTRYPOINT是无法覆盖的

29.服务器推送技术在互联网领域哪里用的到和看得到?

答:一般互联网应用的扫码登录,扫码支付后自动跳转,网页即时通信,在线文档编辑

30.Server-sent-events与 WebSocket的区别是什么?

答:SSE 与 WebSocket 作用相似,都是建立浏览器与服务器之间的通信渠道,然后服务器向浏览器推送信息。总体来说,WebSocket更强大和灵活。因为它是全双工通道,可以双向通信;SSE是单向通道,只能服务器向浏览器发送。SSE使用HTTP协议,现有的服务器软件都支持。WebSocket是一个独立协议。SSE属于轻量级,使用简单;WebSocket协议相对复杂。SSE默认支持断线重连,WebSocket需要自己实现。SSE一般只用来传送文本,二进制数据需要编码后传送,WebSocket默认支持传送二进制数据。SSE 支持自定义发送的消息类型

31.请描述负载均衡原理?

答案: 负载均衡是高可用网络基础架构的的一个关键组成部分,有了负载均衡,我们通常可以将我们的应用服务器部署多台,然后通过负载均衡将用户的请求分发到不同的服务器用来提高网站、应用、数据库或其他服务的性能以及可靠性

32.以下关于使用ZK完成服务注册与发现错误的是?

A.服务注册使用零时节点
B.消费方连接zk获得注册列表
C.从zk获得注册地址后可直接调用
D.为了监听节点的变化,需要使用ZK的watch机制
答案:C,从zk获取注册地址是个集合,需要使用一定的负载算法获取其中的某一个来调用

33.在什么样的场景下@Transactional会失效?如何解决?

正确答案:在spring容器中,在一个类内部A方法和B方法都加了@Transactional注解,如果A方法中直接调用B方法,则B方法的事务会失效;可以使用AopContext获取当前对象的动态代理,避免B方法事务失效的问题;

34.对服务器进行心跳检测,如果服务器在线则30s之后再次发起心跳检测,如果服务器不在线,发送短信通知并停止心跳检测,这个场景如何实现?

参考答案:通过定时任务线程池ScheduledExecutorService的scheduleAtFixedRate方法启动线程每隔30s ping一次服务器,启动之后scheduleAtFixedRate方法会返回当前线程的异步执行结果的引用Future,如果服务器在线,线程会每隔30s触发一次,如果服务区不在线则通过Future.cancel停止本次心跳检测

35.多线程编程对我们有什么实际意义?

答:按照我们一般的业务实现,我们会在一个方法中调用所有相关的业务方法。这种实现带来的问题有什么?第一,耦合,所有相关的业务方法成了一个业务流程上的必不可少的一步,前面的流程断了,后面的就没法走,整个业务就无法完成,但是有些业务方法其实并不是业务流程上必不可少的一环,是否执行,执行是否成功对业务影响并不大;第二,业务流程上有几个步骤,这个处理时间就是这几个步骤时间的相加,业务越多,步骤越多,处理时间当然就越多
那怎么解决这个问题?让这些业务并行起来而且减少相互之间的关联?当然是请出我们的线程,既可以解耦,又可以提高性能。

36.Netty 高性能表现在哪些方面?

答案:IO 线程模型:同步非阻塞,用最少的资源做更多的事。
          内存零拷贝:尽量减少不必要的内存拷贝,实现了更高效率的传输。
          内存池设计:申请的内存可以重用,主要指直接内存。内部实现是用一颗二叉查找树管理内存分配情况。
          串形化处理读写:避免使用锁带来的性能开销。即消息的处理尽可能在同一个线程内完成,期间不进行线程切换,这样就避免了多线程竞争和同步锁。表面上看,串行化设计似乎CPU利用率不高,并发程度不够。但是,通过调整NIO线程池的线程参数,可以同时启动多个串行化的线程并行运行,这种局部无锁化的串行线程设计相比一个队列-多个工作线程模型性能更优。
          高性能序列化协议:支持 protobuf 等高性能序列化协议。
          高效并发编程的体现:volatile的大量、正确使用;CAS和原子类的广泛使用;线程安全容器的使用;通过读写锁提升并发性能。

37.MyBatis是怎么通过mapper接口访问数据库?

答案:mybatis是通过sqlSession这个入口才能访问数据库;首先通过动态代理在内存中生成mapper接口的实现类,实现类中的方法要做三个翻译,第一将请求转发给sqlsession中指定的方法,第二拼接sql语句的唯一标识(namespace+id),第三传递查询参数;通过这三步翻译,基于sqlSession完成对数据库的访问;

38.为什么HashMap中数组的容量为2的次幂?

答案:因为在插入元素时,元素定位的数组位置时把hashCode和容量进行按位与计算。使用2的次幂进行计算时可以减少碰撞的发生,并且让散列尽可能的均匀分布。

39.常用的Mysql复制架构有哪些?

答:1)一主多从
在主库读取请求压力非常大的场景下, 可以通过配置一主多从复制架构实现读写分离, 把大量对实时性要求不是特别高的读请求通过负载均衡分布到多个从库上, 降低主库的读取压力,在主库出现异常宕机的情况下, 可以把一个从库切换为主库继续提供服务 。
2)多级复制
一主多从的架构能够解决大部分读请求压力特别大的场景的需求, 考虑到 MysQL的复制是主库“推送” Binlog日志到从库,主库的 I/0压力和网络压力会随着从库的增加而增长(每个从库都会在主库上有一个独立的 Binlog Dump线程来发送事件), 而多级复制架构解决了一主多从场景下,主库额外的 I/0和网络压力。
3)双主复制/Dual Master
其实就是主库 Master和 Master2互为主从, client客户端的写请求都访问主库 Master,而读请求可以选择访问主库 Master或 Master2。

40.Mysql集群的可行方案有哪些?

答:1)MySQL Cluster
由Mysql本身提供,优势:可用性非常高,性能非常好。每份数据至少可在不同主机存一份拷贝,且冗余数据拷贝实时同步。但它的维护非常复杂,存在部分Bug,目前还不适合比较核心的线上系统,所以不推荐。
2)DRBD磁盘网络镜像方案
Distributed Replicated BlockDevice,其实现方式是通过网络来镜像整个设备(磁盘)。它允许用户在远程机器上建立一个本地块设备的实时镜像,与心跳链接结合使用,也可看做一种网络RAID。
优势:软件功能强大,数据可在底层快设备级别跨物理主机镜像,且可根据性能和可靠性要求配置不同级别的同步。IO操作保持顺序,可满足数据库对数据一致性的苛刻要求。但非分布式文件系统环境无法支持镜像数据同时可见,性能和可靠性两者相互矛盾,无法适用于性能和可靠性要求都比较苛刻的环境,维护成本高于MySQL Replication。另外,DRBD也是官方推荐的可用于MySQL高可用方案之一,所以这个大家可根据实际环境来考虑是否部署。
3)MySQL Replication
在实际应用场景中,MySQL Replication是使用最为广泛的一种提高系统扩展性的设计手段。众多的MySQL使用者通过Replication功能提升系统的扩展性后,通过简单的增加价格低廉的硬件设备成倍 甚至成数量级地提高了原有系统的性能。

 

最后更新于2020-1-9

 

 

最后修改于 2019-10-17 14:05:04
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付
上一篇