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 底层原理?
17.ELK我怎么做?具体的一些项目情况(我项目中有写到)
我就描述了下我们系统当时开发Dashboard的过程,主要是定时任务从数据库抓取数据到es,Kibana制作Dashboard,前端结合E-charts做了个世界地图,然后展示各个中心不同的Dashboard。
18.Redis集群,你们生产系统的策略?创建的有哪些集群策略?
我们生产是三主三从的策略。
可以参考:redis的三种集群方式
精彩推荐
-
小白如何从零开始学习Java?
公众号