金三银四:蚂蚁金服JAVA后端面试题及答案之二面


一面参考这篇文章:蚂蚁金服JAVA后端面试题及答案之一面

二面

22、你有什么问题想问我的吗?

1、自我介绍、工作经历、技术栈

2、项目中你学到了什么技术?

3、微服务划分的粒度?

4、微服务的高可用怎么保证的?

负载均衡与反向代理,隔离,限流,降级,超时与重试,回滚,压力测试与应急预案

5、常用的负载均衡,该怎么用,你能说下吗?

1、http重定向

当http代理(比如浏览器)向web服务器请求某个URL后,web服务器可以通过http响应头信息中的Location标记来返回一个新的URL。这意味着HTTP代理需要继续请求这个新的URL,完成自动跳转。

2、DNS负载均衡

DNS 负责提供域名解析服务,当访问某个站点时,实际上首先需要通过该站点域名的DNS服务器来获取域名指向的IP地址,在这一过程中,DNS服务器完成了域名到IP地址的映射,同样,这样映射也可以是一对多的,这时候,DNS服务器便充当了负载均衡调度器,它就像http重定向转换策略一样,将用户的请求分散到多台服务器上,但是它的实现机制完全不同。

3、反向代理负载均衡

这个肯定大家都有所接触,因为几乎所有主流的Web服务器都热衷于支持基于反向代理的负载均衡。它的核心工作就是转发HTTP请求。

相比前面的HTTP重定向和DNS解析,反向代理的调度器扮演的是用户和实际服务器中间人的角色:

1、任何对于实际服务器的HTTP请求都必须经过调度器

2、调度器必须等待实际服务器的HTTP响应,并将它反馈给用户(前两种方式不需要经过调度反馈,是实际服务器直接发送给用户)

4、IP负载均衡(LVS-NAT)

因为反向代理服务器工作在HTTP层,其本身的开销就已经严重制约了可扩展性,从而也限制了它的性能极限。那能否在HTTP层面以下实现负载均衡呢?

NAT服务器:它工作在传输层,它可以修改发送来的IP数据包,将数据包的目标地址修改为实际服务器地址

5、直接路由(LVS-DR)

NAT是工作在网络分层模型的传输层(第四层),而直接路由是工作在数据链路层(第二层),貌似更屌些。它通过修改数据包的目标MAC地址(没有修改目标IP),将数据包转发到实际服务器上,不同的是,实际服务器的响应数据包将直接发送给客户羰,而不经过调度器

6、IP隧道(LVS-TUN)

基于IP隧道的请求转发机制:将调度器收到的IP数据包封装在一个新的IP数据包中,转交给实际服务器,然后实际服务器的响应数据包可以直接到达用户端。目前Linux大多支持,可以用LVS来实现,称为LVS-TUN,与LVS-DR不同的是,实际服务器可以和调度器不在同一个WANt网段,调度器通过 IP隧道技术来转发请求到实际服务器,所以实际服务器也必须拥有合法的IP地址。

总体来说,LVS-DR和LVS-TUN都适合响应和请求不对称的Web服务器,如何从它们中做出选择,取决于你的网络部署需要,因为LVS-TUN可以将实际服务器根据需要部署在不同的地域,并且根据就近访问的原则来转移请求,所以有类似这种需求的,就应该选择LVS-TUN。

6、网关能够为后端服务带来哪些好处?

后端服务器可以专心处理业务请求,节省了大量连接管理的开销

7、Spring Bean 的生命周期

8、xml 中配置的 init、destroy 方法怎么可以做到调用具体的方法?

9、反射的机制

大家都知道,要让Java程序能够运行,那么就得让Java类要被Java虚拟机加载。Java类如果不被Java虚拟机加载,是不能正常运行的。现在我们运行的所有的程序都是在编译期的时候就已经知道了你所需要的那个类的已经被加载了。

Java的反射机制是在编译并不确定是哪个类被加载了,而是在程序运行的时候才加载、探知、自审。使用在编译期并不知道的类。这样的特点就是反射

反射机制通过void setAccessible(boolean flag)方法可以得到一个类的private的方法和属性,使用这些private的方法和属性

10、Object 类中的方法

1,构造函数

2,hashCode和equale函数用来判断对象是否相同,

3,wait(),wait(long),wait(long,int),notify(),notifyAll()

4,toString()和getClass,

5,clone()

6,finalize()用于在垃圾回收

11、hashcode 和 equals 方法常用地方

12、对象比较是否相同

equals通常用来比较两个对象的内容是否相等,==用来比较两个对象的地址是否相等

13、hashmap put 方法存放的时候怎么判断是否是重复的

先比较key的hashCode,再比较相等或equals的,所以重写hashCode()和equals()方法即可实现添加重复元素。

14、Object toString 方法常用的地方,为什么要重写该方法

常用在对象模型类

因为假如User是一个用户的对象,如果User.toString();结果是不正常的,因为User对象中可能有多个属性,如年龄,姓名等,这个toString后无法知道具体的是那个属性转换为字符串

15、Set 和 List 区别?

Set(集):集合中的对象不按特定方式排序,并且没有重复对象。它的有些实现类能对集合中的对象按特定方式排序。

List(列表):集合中的对象按索引位置排序,可以有重复对象,允许按照对象在集合中的索引位置检索对象。

16、ArrayList 和 LinkedList 区别

ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构

ArrayList 继承AbstractList

LinkedList 继承AbstractSequentialList

ArrayList 采用的是数组形式来保存对象的,这种方式将对象放在连续的位置中,所以最大的缺点就是插入删除时非常麻烦

LinkedList 采用的将对象存放在独立的空间中,而且在每个空间中还保存下一个链接的索引 但是缺点就是查找非常麻烦 要丛第一个索引开始

17、如果存取相同的数据,ArrayList 和 LinkedList 谁占用空间更大?

对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针

对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据,若要从数组中删除或插入某一个对象,需要移动后段的数组元素,从而会重新调整索引顺序,调整索引顺序会消耗一定的时间,相反,LinkedList是使用链表实现的,若要从链表中删除或插入某一个对象,只需要改变前后对象的引用即可

18、Set 存的顺序是有序的吗?

无序

Set是Map的一个马甲,主要逻辑都交给Map实现

19、常见 Set 的实现有哪些?

HashSet

LinkedHashSet

TreeSet

20、TreeSet 对存入对数据有什么要求呢?

TreeSet集合是用来对象元素进行排序的,同样他也可以保证元素的唯一

21、HashSet 的底层实现呢?

22、TreeSet 底层源码有看过吗?

TreeSet的底层实现是TreeMap

public TreeSet(Comparator<? super E> comparator) {

this(new TreeMap<>(comparator));

}

23、HashSet 是不是线程安全的?为什么不是线程安全的?

说白了,HashSet就是限制了功能的HashMap,所以了解HashMap的实现原理

24、Java 中有哪些线程安全的 Map?

Concurrenthashmap

25、Concurrenthashmap 是怎么做到线程安全的?

ConcurrentHashMap的大部分操作和HashMap是相同的,例如初始化,扩容和链表向红黑树的转变等。但是,在ConcurrentHashMap中,大量使用了U.compareAndSwapXXX

的方法,这个方法是利用一个CAS算法实现无锁化的修改值的操作,他可以大大降低锁代理的性能消耗。这个算法的基本思想就是不断地去比较当前内存中的变量值与你指定的

一个变量值是否相等,如果相等,则接受你指定的修改的值,否则拒绝你的操作。因为当前线程中的值已经不是最新的值,你的修改很可能会覆盖掉其他线程修改的结果。这一

点与乐观锁,SVN的思想是比较类似的。

同时,在ConcurrentHashMap中还定义了三个原子操作,用于对指定位置的节点进行操作。这三种原子操作被广泛的使用在ConcurrentHashMap的get和put等方法中,

正是这些原子操作保证了ConcurrentHashMap的线程安全。

在ConcurrentHashMap没有出现以前,jdk使用hashtable来实现线程安全,但是hashtable是将整个hash表锁住,所以效率很低下。

ConcurrentHashMap将数据分别放到多个Segment中,默认16个,每一个Segment中又包含了多个HashEntry列表数组,

对于一个key,需要经过三次hash操作,才能最终定位这个元素的位置,这三次hash分别为:

对于一个key,先进行一次hash操作,得到hash值h1,也即h1 = hash1(key);

将得到的h1的高几位进行第二次hash,得到hash值h2,也即h2 = hash2(h1高几位),通过h2能够确定该元素的放在哪个Segment;

将得到的h1进行第三次hash,得到hash值h3,也即h3 = hash3(h1),通过h3能够确定该元素放置在哪个HashEntry。

每一个Segment都拥有一个锁,当进行写操作时,只需要锁定一个Segment,而其它Segment中的数据是可以访问的。

26、HashTable 你了解过吗?

Hashtable既不支持Null key也不支持Null value。Hashtable的put()方法的注释中有说明

Hashtable是线程安全的,

Hashtable是线程安全的,它的每个方法中都加入了Synchronize方法,效率比较低

Hashtable默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。

Hashtable在计算元素的位置时需要进行一次除法运算,而除法运算是比较耗时的。

27、如何保证线程安全问题?

28、synchronized、lock

synchronized是java中的一个关键字,也就是说是Java语言内置的特性

如果一个代码块被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况:

1)获取锁的线程执行完了该代码块,然后线程释放对锁的占有;

2)线程执行发生异常,此时JVM会让线程自动释放锁

那么如果这个获取锁的线程由于要等待IO或者其他原因(比如调用sleep方法)被阻塞了,但是又没有释放锁,其他线程便只能干巴巴地等待,试想一下,这多么影响程序执行效率。

因此就需要有一种机制可以不让等待的线程一直无期限地等待下去(比如只等待一定的时间或者能够响应中断),通过Lock就可以办到

再举个例子:当有多个线程读写文件时,读操作和写操作会发生冲突现象,写操作和写操作会发生冲突现象,但是读操作和读操作不会发生冲突现象。

但是采用synchronized关键字来实现同步的话,就会导致一个问题:

如果多个线程都只是进行读操作,所以当一个线程在进行读操作时,其他线程只能等待无法进行读操作。

因此就需要一种机制来使得多个线程都只是进行读操作时,线程之间不会发生冲突,通过Lock就可以办到。

另外,通过Lock可以知道线程有没有成功获取到锁。这个是synchronized无法办到的

29、volatile 的原子性问题?为什么 i++ 这种不支持原子性?从计算机原理的设计来讲下不能保证原子性的原因

30、happens before 原理

31、cas 操作

java.util.concurrent包中借助CAS实现了区别于synchronized同步锁的一种乐观锁

cas是比较并交换算法

CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做

JDK提供了AtomicReference类来保证引用对象之间的原子性,就可以把多个变量放在一个对象里来进行CAS操作。

32、lock 和 synchronized 的区别?

1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;

2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;

3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。

5)Lock可以提高多个线程进行读操作的效率。

在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。

类别

synchronized

Lock

存在层次

Java的关键字,在jvm层面上

是一个类

锁的释放

1、以获取锁的线程执行完同步代码,释放锁 2、线程执行发生异常,jvm会让线程释放锁

在finally中必须释放锁,不然容易造成线程死锁

锁的获取

假设A线程获得锁,B线程等待。如果A线程阻塞,B线程会一直等待

分情况而定,Lock有多个锁获取的方式,具体下面会说道,大致就是可以尝试获得锁,线程可以不用一直等待

锁状态

无法判断

可以判断

锁类型

可重入 不可中断 非公平

可重入 可判断 可公平(两者皆可)

性能

少量同步

大量同步

33、公平锁和非公平锁

公平和非公平锁的队列都基于锁内部维护的一个双向链表,表结点Node的值就是每一个请求当前锁的线程。公平锁则在于每次都是依次从队首取值

非公平锁在等待锁的过程中, 如果有任意新的线程妄图获取锁,都是有很大的几率直接获取到锁的

(在ReentrantLock中很明显可以看到其中同步包括两种,分别是公平的FairSync和非公平的NonfairSync。公平锁的作用就是严格按照线程启动的顺序来执行的,不允许其他线程插队执行的;而非公平锁是允许插队的。

默认情况下ReentrantLock是通过非公平锁来进行同步的,包括synchronized关键字都是如此,因为这样性能会更好。因为从线程进入了RUNNABLE状态,可以执行开始,到实际线程执行是要比较久的时间的。而且,在一个锁释放之后,其他的线程会需要重新来获取锁。其中经历了持有锁的线程释放锁,其他线程从挂起恢复到RUNNABLE状态,其他线程请求锁,获得锁,线程执行,这一系列步骤。如果这个时候,存在一个线程直接请求锁,可能就避开挂起到恢复RUNNABLE状态的这段消耗,所以性能更优化)

34、Java 读写锁

35、读写锁设计主要解决什么问题?

多线程,

读操作可以共享,写操作是排他的,读可以有多个在读,写只有唯一个在写,同时写的时候不允许读

解决了读和读可以同时进行,读和写不能同时进行,写和写不能同时进行

36、你项目除了写 Java 代码,还有前端代码,那你知道前端有哪些框架吗?

Vue layer react element

37、MySQL 分页查询语句

LIMIT [offset,] rows

offset指定要返回的第一行的偏移量,rows第二个指定返回行的最大数目

38、MySQL 事务特性和隔离级别

一、事务的基本要素(ACID)

1、原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节。事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有发生一样。也就是说事务是一个不可分割的整体,就像化学中学过的原子,是物质构成的基本单位。

2、一致性(Consistency):事务开始前和结束后,数据库的完整性约束没有被破坏 。比如A向B转账,不可能A扣了钱,B却没收到。

3、隔离性(Isolation):同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。

4、持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,不能回滚。

二、事务的并发问题

1、脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据

2、不可重复读:事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。

3、幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。

MySQL事务隔离级别

事务隔离级别

脏读

不可重复读

幻读

读未提交(read-uncommitted)

不可重复读(read-committed)

可重复读(repeatable-read)

串行化(serializable)

39、不可重复读会出现在什么场景?

40、sql having 的使用场景

如果需要对组函数的结果作为条件,那么不能使用where子句,必须使用having子句

41、前端浏览器地址的一个 http 请求到后端整个流程是怎么样?

能够说下吗?

域名解析 --> 发起TCP的3次握手 --> 建立TCP连接后发起http请求 -->服务器响应http请求,浏览器得到html代码 -->浏览器解析html代码,并请求html代码中的资源(如js、css、图片等) --> 浏览器对页面进行渲染呈现给用户

42、http 默认端口,https 默认端口

HTTP协议代理服务器常用端口号:80/8080/3128/8081/9080

HTTPS服务器,默认的端口号为443/tcp 443/udp

43、DNS 你知道是干嘛的吗?

DNS是指:域名服务器(Domain Name Server)。在Internet上域名与IP地址之间是一一对应的,域名虽然便于人们记忆,但机器之间只能互相认识IP地址,它们之间的转换工作称为域名解析,域名解析需要由专门的域名解析服务器来完成,DNS就是进行域名解析的服务器

44、你们开发用的 ide 是啥?你能说下 idea 的常用几个快捷键吧?

45、代码版本管理你们用的是啥?

46、git rebase 和 merge 有什么区别?

47、你们公司加班多吗?

一面参考这篇文章:蚂蚁金服JAVA后端面试题及答案之一面

欢迎工作一到五年的Java工程师朋友们加入Java高级架构:867581223

群内提供免费的Java架构学习资料(里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码,

MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料)

合理利用自己每一分每一秒的时间来学习提升自己,不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代!



猜你喜欢

转载自blog.51cto.com/13689432/2364155