阿里一面面经(附答案)_IT业界

 

j

 

岗位:Java 国际事业部

电面,一小时。

工作经验: 2年。

八点多左右来了电话,我投的未来酒店,没想到面的是阿里,我还懵逼的问了下是谁,略尴尬。

 

 

先自我介绍,说了下项目情况,主要工作。针对我的工作经验开始问问题了:

1.一般的SQL优化思路?

    我给讲了下我们系统报表的优化,多表关联拆分成单表,用Java组装其他表信息,主要查询条件建索引等。

    如果是MySql,可以看看执行计划,可以戳下我的另一篇:MySql调优初探

 

2.为什么业务选用Cassandra做数据库?

    我说了下系统业务特点,并发量,数据量,各方面分析了选用Cassandra的理由,中间还问了为什么不用Mysql,在这过程我讲了下项目的生产架构部署。想更多了解Cassandra,可以戳我的另外两篇:Cassandra实战 笔记-《Cassandra内部数据存储结构》和 Cassandra实战 笔记-《Cassandra的集群机制》

 

3.接着他问,Nginx 负载均衡策略,有哪些负载均衡算法?

    我回答了几种常见的,随机,轮询,他说加权轮询呢?一般用在什么场景,我随机应变,说一般是针对服务器配置不同,给配置高的权重大点,能够处理更多的请求。

 

4.HashMap 底层原理?查询的时间复杂度?

    这个很常规,我讲了下Put的过程,多线程下可能会线程不安全,扩容时可能会出现的问题:

    1)put的时候导致的多线程数据不一致。

    2)另外一个比较明显的线程不安全的问题是HashMap的get操作可能因为resize而引起死循环(cpu100%)

时间复杂度:1.8引入红黑树,查找数据的最坏情况复杂度从O(n)降到O(log n),正常是O(1);

    墙裂推荐美团的技术博客:Java 8系列之重新认识HashMap

 

5.ConcurrentHashMap?

一般这个问题会接着问,我说了下1.7的Segment分端锁的思想,1.8的CAS和Sychorinized如何保证线程安全。

6.作为上面延伸,问了一般情况怎么保证线程安全问题?

    volatile,Sychorinized,Lock,CAS 无锁编程(最后这个我装了下13,最理想的就是无锁编程)。

 

7.volatile作用及其底层原理?

    保证变量线程可见,根据并发编程艺术上说的,还讲到了CPU多级缓存。

 

8.Sychorinized和Lock区别?

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

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

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

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

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

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

 

9.线程有哪几种创建方式?

    继承Thread或者实现Runnable接口,线程池创建;    

 

10.线程池几个核心参数,说一下?基本原理?

    检测核心线程数是否达到corePoolSize, 没有则创建新线程, 否则进入阻塞队列

    检测阻塞队列是否已满, 没有则直接放入, 否则进入下一步

    检测线程数是否达到线程池最大容量大小maximumPoolSize, 没有则创建新线程, 否则根据饱和策略处理

        core线程池满? -> 等待队列满? -> 整个线程池满? -> 饱和策略

   Q&A

    如何根据CPU的核数来设计线程大小

    计算密集型

    无需设置过大的线程池工作队列, 工作队列长度 = CPU核心数 || CPU核心数+1

    IO密集型

    适当加大工作队列长度

 

11.Minor GC和Full GC?

 

12.FULL GC产生有哪些情况,线上如何排查(给了具体情况去分析)?

    导致Full GC的原因:

    1)碎片化,由于CMS在老年代回收时,采用的是标记清理(Mark-Sweep)算法,它在垃圾回收时并不会压缩堆,日积月累,导致老年代的碎片化问题会越来越严重,直到发生单线程的Mark-Sweep-Compact GC,即FullGC,会完全STW。如果堆比较大的话,STW的时间可能需要好几秒,甚至十多秒,几十秒都有可能。

    2)显示System.gc调用;

    3)堆空间不够;

    4)JVM自身Bug。

具体可以参考:GC一些长时间停顿问题排查及解决办法

 

13.一致性哈希?

    核心就是Hash环,一致性hash的特性:单调性、分散性、平衡性,当服务结点较少时候可以引入虚拟节点,然后还可以谈谈均匀一致性哈希,怎么保证不发生数据倾斜。具体可以参考:深入浅出一致性Hash原理

 

14.RPC 原理?如过自己设计一个,简单说下思路?

    【RPC 专栏】简单了解RPC实现原理

    最简单的回答思路:

    上来你的服务就得去注册中心注册吧,你是不是得有个注册中心,保留各个服务的信息,可以用 zookeeper 来做,对吧。

    然后你的消费者需要去注册中心拿对应的服务信息吧,对吧,而且每个服务可能会存在于多台机器上。

    接着你就该发起一次请求了,咋发起?当然是基于动态代理了,你面向接口获取到一个动态代理,这个动态代理就是接口在本地的一个代理,然后这个代理会找到服务对应的机器地址。

    然后找哪个机器发送请求?那肯定得有个负载均衡算法了,比如最简单的可以随机轮询是不是。

    接着找到一台机器,就可以跟它发送请求了,第一个问题咋发送?你可以说用 netty 了,nio 方式;第二个问题发送啥格式数据?你可以说用 hessian 序列化协议了,或者是别的,对吧。然后请求过去了。

    服务器那边一样的,需要针对你自己的服务生成一个动态代理,监听某个网络端口了,然后代理你本地的服务代码。接收到请求的时候,就调用对应的服务代码。

 

15.说说常见限流算法?实现思路?

    令牌桶算法,令牌桶算法是比较常见的限流算法之一,大概描述如下:

    1)所有的请求在处理之前都需要拿到一个可用的令牌才会被处理;

    2)根据限流大小,设置按照一定的速率往桶里添加令牌;

    3)桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃活着拒绝;

    4)请求达到后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除;

    5)令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保证足够的限流;

    漏桶算法,漏桶算法其实很简单,可以粗略的认为就是注水漏水过程,往桶中以一定速率流出水,以任意速率流入水,当水超过桶流量则丢弃,因为桶容量是不变的,保证了整体的速率。

    想看看两种算法区别的可以戳下面:

     常用的限流算法

 

16.Shiro 底层原理?

 

阿里一面面经(附答案)_IT业界_02

 

17.ELK我怎么做?具体的一些项目情况(我项目中有写到)

    我就描述了下我们系统当时开发Dashboard的过程,主要是定时任务从数据库抓取数据到es,Kibana制作Dashboard,前端结合E-charts做了个世界地图,然后展示各个中心不同的Dashboard。    

18.Redis集群,你们生产系统的策略?创建的有哪些集群策略?

    我们生产是三主三从的策略。

    可以参考:redis的三种集群方式

 

精彩推荐

  • 小白如何从零开始学习Java?

   

 

公众号

阿里一面面经(附答案)_IT业界_03