一网打尽天下。
###真题
- 自己的面试的真题
- 4、面试内容
- 考察内容会相对偏基础,给大家一个参考范围(不限于以下内容):
- 1)基础知识
- 算法与数据结构(可能有在线编程1-2道,难度是 easy middle 之间):排序算法,简单的二叉树,大数相关
- 操作系统与网络:多线程与多进程,内存分页,磁盘管理,死锁及如何避免,http(s)协议的安全性,tcp三次握手与可靠传输
- 数据库:乐观锁与悲观锁,数据库索引的底层数据结构,数据库的原子性
- 2)编程语言(Java为例):HashMap扩容、一致性hash,ConcurrentHashMap,GC原理,Integer与int差别,设计模型(单例、工厂等),NIO等
- 3)项目经验:描述清楚项目背景,项目的实现与技术难点,自己在项目中的贡献,上述也适用于论文
- 4)开放题:一般在最后两轮面试会有,主要考察理解能力和反应能力
-
二面也是技术面,对简历里面的项目再总结一下哈,可以说清楚项目的意义、如何做、碰到的问题与解决方法;再就是一些基础相关的,可以理解原理并思考原因
- 网络相关
- https的加密方式,原理
- 使用了对称加密+非对称加密(交换密钥)+CA证书(SSL层验证)三种方式进行加密。SSL层就负责加密解密
- https://zhuanlan.zhihu.com/p/25976060 - https://www.jianshu.com/p/b894a7e1c779
- ssh(和https的不同?) https://blog.csdn.net/liubo2012/article/details/8894143
- 加密算法 https://zhuanlan.zhihu.com/p/27395037
- http缺点 http://cycle263.github.io/blogs/http/articles/https.html
- HTTPS 协议(HyperText Transfer Protocol over Secure Socket Layer):可以理解为HTTP+SSL/TLS, 即 HTTP 下加入 SSL 层,HTTPS 的安全基础是 SSL
- tcp为什么三次握手和四次挥手
-
- tcp 头部 https://www.cnblogs.com/li-hao/archive/2011/12/07/2279912.html
- 有ACK/SYN/PIN/序号/确认序号/窗口大小等内容
- tcp为什么三次握手和四次挥手 https://juejin.im/post/5b1e9c65f265da6e26099bf3
- 三次握手可以很好的避免网络超时导致的丢包情况,服务器和客户端都要分别收到正确的ACK之后才能表示连接建立,如果未收到,就会启用超时重传机制。当然如果网络确实比较差,导致连接无法建立,也不可能一直重传。操作系统中会有设置重传次数这个字段,以避免无效重转。
- 至于为啥是四次挥手,本质的原因是咱们的tcp连接是全双工的,在两个方向都需要关闭,所以两个方向都需要发送一个关闭请求和确认请求。
- tcp如何保证可靠传输csnote https://cyc2018.github.io/CS-Notes/#/notes/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%20-%20%E4%BC%A0%E8%BE%93%E5%B1%82?id=tcp-%e5%8f%af%e9%9d%a0%e4%bc%a0%e8%be%93
-
- 讲一下OSI7层模型,传输层是干什么的
-
- 超时重传是TCP协议保证数据可靠性的一个重要机制,其原理是在发送某一个数据以后就开启一个计时器,在一定时间内如果没有得到发送的数据报的ACK报文,那么就重新发送数据,直到发送成功为止。三次握手,正常的数据传输,以及四次握手过程中只要出现超时情况,都会触发重传。
-
设置重传时间间隔RTO RTO = RTTs (加权平均往返时间) + 4RTTd(偏差的加权平均值)
- 传输层 :为进程提供通用数据传输服务。由于应用层协议很多,定义通用的传输层协议就可以支持不断增多的应用层协议。运输层包括两种协议:传输控制协议 TCP,提供面向连接、可靠的数据传输服务,数据单位为报文段;用户数据报协议 UDP,提供无连接、尽最大努力的数据传输服务,数据单位为用户数据报。TCP 主要提供完整性服务,UDP 主要提供及时性服务。
- https://blog.csdn.net/u011774517/article/details/67631439
- csnote https://cyc2018.github.io/CS-Notes/#/notes/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%20-%20%E6%A6%82%E8%BF%B0?id=_2-osi
-
- 讲一下URL之后发生了什么
- 1.DNS域名解析;2.建立TCP连接;3.发送HTTP请求;4.服务器处理请求;5.返回响应结果;6.关闭TCP连接;7.浏览器解析HTML;8.浏览器布局渲染;
- 讲一下TCP和UDP的区别
- 1.基于连接与无连接;
- 2.对系统资源的要求(TCP较多,UDP少);
- 3.UDP程序结构较简单;
- 4.流模式与数据报模式 ;
- 5.TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。
- TCP握手各个阶段的名字 https://cyc2018.github.io/CS-Notes/#/notes/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%20-%20%E4%BC%A0%E8%BE%93%E5%B1%82?id=tcp-%e7%9a%84%e5%9b%9b%e6%ac%a1%e6%8c%a5%e6%89%8b
- DNS用的什么协议
- DNS在进行区域传输的时候使用TCP协议,其它时候则使用UDP协议;
- DNS的规范规定了2种类型的DNS服务器,一个叫主DNS服务器,一个叫辅助DNS服务器。在一个区中主DNS服务器从自己本机的数据文件中读取该区的DNS数据信息,而辅助DNS服务器则从区的主DNS服务器中读取该区的DNS数据信息。当一个辅助DNS服务器启动时,它需要与主DNS服务器通信,并加载数据信息,这就叫做区传送(zone transfer)。
- 为什么既使用TCP又使用UDP? 首先了解一下TCP与UDP传送字节的长度限制: UDP报文的最大长度为512字节,而TCP则允许报文长度超过512字节。当DNS查询超过512字节时,协议的TC标志出现删除标志,这时则使用TCP发送。通常传统的UDP报文一般不会大于512字节。
- 区域传送时使用TCP,主要有一下两点考虑: 1.辅域名服务器会定时(一般时3小时)向主域名服务器进行查询以便了解数据是否有变动。如有变动,则会执行一次区域传送,进行数据同步。区域传送将使用TCP而不是UDP,因为数据同步传送的数据量比一个请求和应答的数据量要多得多。 2.TCP是一种可靠的连接,保证了数据的准确性。
- 域名解析时使用UDP协议: 客户端向DNS服务器查询域名,一般返回的内容都不超过512字节,用UDP传输即可。不用经过TCP三次握手,这样DNS服务器负载更低,响应更快。虽然从理论上说,客户端也可以指定向DNS服务器查询的时候使用TCP,但事实上,很多DNS服务器进行配置的时候,仅支持UDP查询包。
- DNS在进行区域传输的时候使用TCP协议,其它时候则使用UDP协议;
- HTTP协议和IP协议
- TPC/IP协议是传输层协议,主要解决数据如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据。关于TCP/IP和HTTP协议的关系,网络有一段比较容易理解的介绍:“我们在传输数据时,可以只使用(传输层)TCP/IP协议,但是那样的话,如果没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用到应用层协议,应用层协议有很多,比如HTTP、FTP、TELNET等,也可以自己定义应用层协议。WEB使用HTTP协议作应用层协议,以封装HTTP 文本信息,然后使用TCP/IP做传输层协议将它发到网络上。”
- TCP 为什么 慢
- 网络丢包/服务器超载主动丢包 超时重传,速率降低一半
- https的加密方式,原理
- java容器
- ArrayList多线程什么问题
- hashmap https://cyc2018.github.io/CS-Notes/#/notes/Java%20%E5%AE%B9%E5%99%A8?id=_1-%e5%ad%98%e5%82%a8%e7%bb%93%e6%9e%84
- hashmap是一个数组链表 具体是包含entry数组的table;transient Entry[] table; Entry 存储着键值对。它包含了四个字段 hashcode,key,value,next
- 链表的插入是以头插法方式进行的.查找计算键值对所在的桶;在链表上顺序查找,时间复杂度显然和链表的长度成正比。
- hash原理/一致性原理? 通过移位和异或操作,将高位与地位的特征结合起来降低哈希冲突的概率。 https://www.zhihu.com/question/20733617
- hashmap如何确定下标:4.1 计算 hash 值 + 扰动 4.2 取模
- 扩容-基本原理?使得平均查找次数的复杂度为 O(N/M)。 和扩容相关的参数主要有:capacity-必须保证为 2 的 n 次方、size-键值对数量、threshold-size 的临界值,当 size 大于等于 threshold 就必须进行扩容操作 和 load_factor。HashMap 总是使用2的幂作为哈希表的大小。
- hash一致性-扩容-重新计算桶下标,?对于一个 Key,它的哈希值如果在第 5 位上为 0,那么取模得到的结果和之前一样;如果为 1,那么得到的结果为原来的结果 +16。
- 计算数组容量:mask+1 是大于原始数字的最小的 2 的 n 次方。
- 与 HashTable 的比较? HashTable 使用 synchronized 来进行同步。HashMap 可以插入键为 null 的 Entry。HashMap 的迭代器是 fail-fast 迭代器。HashMap 不能保证随着时间的推移 Map 中的元素次序是不变的
- HashSet 和 HashMap 区别:如果你看过 HashSet 源码的话就应该知道:HashSet 底层就是基于 HashMap 实现的
- java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别是HashMap Hashtable LinkedHashMap 和TreeMap.
- Hashmap 是一个最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的。 HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用 Collections的synchronizedMap方法使HashMap具有同步的能力,或者使用ConcurrentHashMap。
- Hashtable与 HashMap类似,它继承自Dictionary类,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了 Hashtable在写入时会比较慢。
- HashMap是一个最常用的Map,它根据键的hashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为NULL,允许多条记录的值为NULL。
- HashMap不支持线程同步,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致性。如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力。
- Hashtable与HashMap类似,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtable在写入时会比较慢。
- LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的。 在遍历的时候会比HashMap慢.
- TreeMap能够把它保存的记录根据键排序,默认是按升序排序,也可以指定排序的比较器。当用Iterator遍历TreeMap时,得到的记录是排过序的。
- HashMap线程安全吗,多线程什么问题
- concurrenthash在hashmap之上的改变 https://cyc2018.github.io/CS-Notes/#/notes/Java%20%E5%AE%B9%E5%99%A8?id=_1-%e5%ad%98%e5%82%a8%e7%bb%93%e6%9e%84
- 存储结构 ConcurrentHashMap 和 HashMap 实现上类似,最主要的差别是 ConcurrentHashMap 采用了分段锁(Segment),每个分段锁维护着几个桶(HashEntry),多个线程可以同时访问不同分段锁上的桶,从而使其并发度更高(并发度就是 Segment 的个数)。
- size 操作。每个 Segment 维护了一个 count 变量来统计该 Segment 中的键值对个数。如果尝试的次数超过 3 次,就需要对每个 Segment 加锁。
- JDK 1.8 的改动
- JDK 1.7 使用分段锁机制来实现并发更新操作,核心类为 Segment,它继承自重入锁 ReentrantLock,并发度与 Segment 数量相等。
- JDK 1.8 使用了 CAS 操作来支持更高的并发度,在 CAS 操作失败时使用内置锁 synchronized。
- 并且 JDK 1.8 的实现也在链表过长时会转换为红黑树。TreeMap、TreeSet以及JDK1.8之后的HashMap底层都用到了红黑树。红黑树就是为了解决二叉查找树的缺陷,因为二叉查找树在某些情况下会退化成一个线性结构。
- ConcurrentHashMap
- ConcurrentHashMap 和 Hashtable 的区别
- ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方式上不同。
- 底层数据结构: JDK1.7的 ConcurrentHashMap 底层采用 分段的数组+链表 实现,JDK1.8 采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。Hashtable 和 JDK1.8 之前的 HashMap 的底层数据结构类似都是采用 数组+链表 的形式,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的;
- 实现线程安全的方式(重要): ① 在JDK1.7的时候,ConcurrentHashMap(分段锁) 对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。(默认分配16个Segment,比Hashtable效率提高16倍。) 到了 JDK1.8 的时候已经摒弃了Segment的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。(JDK1.6以后 对 synchronized锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap,虽然在JDK1.8中还能看到 Segment 的数据结构,但是已经简化了属性,只是为了兼容旧版本;② Hashtable(同一把锁):使用 synchronized 来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态,如使用 put 添加元素,另一个线程不能使用 put 添加元素,也不能使用 get,竞争会越来越激烈效率越低。
- 各种锁机制,讲得非常好 https://tech.meituan.com/2018/11/15/java-lock.html
- Java中,synchronized关键字和Lock的实现类都是悲观锁。
- 而乐观锁认为自己在使用数据时不会有别的线程修改数据,所以不会添加锁,只是在更新数据的时候去判断之前有没有别的线程更新了这个数据。如果这个数据没有被更新,当前线程将自己修改的数据成功写入。如果数据已经被其他线程更新,则根据不同的实现方式执行不同的操作(例如报错或者自动重试)。乐观锁在Java中是通过使用无锁编程来实现,最常采用的是CAS算法,Java原子类中的递增操作就通过CAS自旋实现的。
- 悲观锁适合写操作多的场景,先加锁可以保证写操作时数据正确。
- 乐观锁适合读操作多的场景,不加锁的特点能够使其读操作的性能大幅提升。
// ------------------------- 悲观锁的调用方式 ------------------------- // synchronized public synchronized void testMethod() { // 操作同步资源 } // ReentrantLock private ReentrantLock lock = new ReentrantLock(); // 需要保证多个线程使用的是同一个锁 public void modifyPublicResources() { lock.lock(); // 操作同步资源 lock.unlock(); } // ------------------------- 乐观锁的调用方式 ------------------------- private AtomicInteger atomicInteger = new AtomicInteger(); // 需要保证多个线程使用的是同一个AtomicInteger atomicInteger.incrementAndGet(); //执行自增1
-
刚才提到了segment继承于ReetrantLock,那谈谈Synchronized和Lock的区别
- 请你谈谈关于Synchronized和lock
- synchronized是Java的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。JDK1.5以后引入了自旋锁、锁粗化、轻量级锁,偏向锁来有优化关键字的性能。Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
- 请你介绍一下Syncronized锁,如果用这个关键字修饰一个静态方法,锁住了什么?如果修饰成员方法,锁住了什么?
- synchronized修饰静态方法以及同步代码块的synchronized (类.class)用法锁的是类,线程想要执行对应同步代码,需要获得类锁。synchronized修饰成员方法,线程获取的是当前调用该方法的对象实例的对象锁。
- 死锁举例
- 第一种synchronized方式死锁:线程thread1先获取锁locka,然后在同步块里嵌套竞争锁lockb。而线程thread2先获取锁lockb,然后在同步块里嵌套竞争锁locka
- 第二种concurrent包Lock错误使用,导致死锁:java两种经典死锁例子,Lock发生死锁案列.
- CAS
- CAS(Compare-and-Swap),即比较并替换,是一种实现并发算法时常用到的技术,Java并发包中的很多类都使用了CAS技术。
- CompareAndSwap的缩写,中文意思是:比较并替换。CAS 指令需要有 3 个操作数,分别是内存地址 V、旧的预期值 A 和新值 B。当执行操作时,只有当 V 的值等于 A,才将 V 的值更新为 B。整个比较并替换的操作对一个操作数来说是一个原子操作。
- CAS的缺点 3点 https://www.cnblogs.com/loveLands/articles/9703474.html
- 红黑树
- 特点:每个节点非红即黑;根节点总是黑色的;每个叶子节点都是黑色的空节点(NIL节点);如果节点是红色的,则它的子节点必须是黑色的(反之不一定);从根节点到叶节点或空子节点的每条路径,必须包含相同数目的黑色节点(即相同的黑色高度);
- 红黑树这么优秀,为何不直接使用红黑树得了?
- 说一下自己对于这个问题的看法:我们知道红黑树属于(自)平衡二叉树,但是为了保持“平衡”是需要付出代价的,红黑树在插入新数据后可能需要通过左旋,右旋、变色这些操作来保持平衡,这费事啊。你说说我们引入红黑树就是为了查找数据快,如果链表长度很短的话,根本不需要引入红黑树的,你引入之后还要付出代价维持它的平衡。但是链表过长就不一样了。至于为什么选 8 这个值呢?通过概率统计所得,这个值是综合查询成本和新增元素成本得出的最好的一个值。
- 一致性hash
- 一致性哈希,就是提供一个hashtable,它能在节点加入离开时不会导致映射关系的重大变化
- 分布式一致性hash。如果Server的哈希等于Key的哈希,则把Key存放在该Server上;否则,寻找第一个大于Key哈希的Server,用于存放Key。但有Server增加、删除时,只要变动周边的Server映射关系即可,不用全部重新哈希。之所以有这样优良的特性是因为,Server和Key采用了同样的值域。还有最后一个问题,虚节点是如何产生的呢?也非常简单,就是在每个Server加个后缀,在做MD5哈希,取其32位。
- MD5哈希; MD5的结果为一个160bit的数字,取其前32位作为一个Integer
- arryalist和linkedlist的区别 - 1.ArrayList是实现了基于动态数组的数据结构,而LinkedList是基于链表的数据结构; - 2.对于随机访问get和set,ArrayList要优于LinkedList,因为LinkedList要移动指针; - 3.对于添加和删除操作add和remove,一般大家都会说LinkedList要比ArrayList快,因为ArrayList要移动数据。但是实际情况并非这样,对于添加或删除,LinkedList和ArrayList并不能明确说明谁快谁慢,下面会详细分析。
- 公平锁原理
- 公平锁在锁释放后会严格按照等到队列去取后续值,而非公平锁在对于新晋线程有很大优势。
- 联合索引
- 两个或更多个列上的索引被称作联合索引,联合索引又叫复合索引。对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。
- AQS 结合 公平锁
- AQS底层机制.对java并发机制熟悉的人都知道底层基本上都是基于AQS实现的,即AbstractQueuedSynchronizer.而且AQS里面又维护了一个队列,可以实现线程排队机制,也可以做等待唤醒操作。那到底公平锁和非公平锁的区别在哪?仔细看一下,NonfairSync中的lock方法首先会通过CAS修改state,而FairSync则直接通过acquire获取。因为acquire最终还是通过CAS修改state,只是里面内置了排队机制.而非公平锁则直接修改state的值,无需排队
- https://tech.meituan.com/2018/11/15/java-lock.html 根据代码可知,ReentrantLock里面有一个内部类Sync,Sync继承AQS(AbstractQueuedSynchronizer),添加锁和释放锁的大部分操作实际上都是在Sync中实现的。它有公平锁FairSync和非公平锁NonfairSync两个子类。ReentrantLock默认使用非公平锁,也可以通过构造器来显示的指定使用公平锁。通过上图中的源代码对比,我们可以明显的看出公平锁与非公平锁的lock()方法唯一的区别就在于公平锁在获取同步状态时多了一个限制条件:hasQueuedPredecessors()。
- 首先ReentrantLock和NonReentrantLock都继承父类AQS,其父类AQS中维护了一个同步状态status来计数重入次数,status初始值为0。当线程尝试获取锁时,可重入锁先尝试获取并更新status值,如果status == 0表示没有其他线程在执行同步代码,则把status置为1,当前线程开始执行。如果status != 0,则判断当前线程是否是获取到这个锁的线程,如果是的话执行status+1,且当前线程可以再次获取锁。而非可重入锁是直接去获取并尝试更新当前status的值,如果status != 0的话会导致其获取锁失败,当前线程阻塞。
- Object的方法都有哪些 https://zhb1208.iteye.com/blog/1418324
- 怎么判断两个对象相等?
- equals通常用来比较两个对象的内容是否相等,==用来比较两个对象的地址是否相等。Object类中的equals方法定义为判断两个对象的地址是否相等(可以理解成是否是同一个对象),地址相等则认为是对象相等。这也就意味着,我们新建的所有类如果没有复写equals方法,那么判断两个对象是否相等时就等同于“==”,也就是两个对象的地址是否相等。1、类未复写equals方法,则使用equals方法比较两个对象时,相当于==比较,即两个对象的地址是否相等。地址相等,返回true,地址不相等,返回false.2、类复写equals方法,比较两个对象时,则走复写之后的判断方式。通常,我们会将equals复写成:当两个对象内容相同时,则equals返回true,内容不同时,返回false。
- equals和hashCode
- hashCode的作用及与equals的关系。hashCode的作用是用来获取哈希码,也可以称作散列码。实际返回值为一个int型数据。用于确定对象在哈希表中的位置。Object中有hashcode方法,也就意味着所有的类都有hashCode方法。但是,hashcode只有在创建某个类的散列表的时候才有用,需要根据hashcode值确认对象在散列表中的位置,但在其他情况下没用。
- 请你解释Object若不重写hashCode()的话,hashCode()如何计算出来的?
- Object 的 hashcode 方法是本地方法,也就是用 c 语言或 c++ 实现的,该方法直接返回对象的 内存地址。
- 请你解释为什么重写equals还要重写hashcode?
- 因为自定义的类的hashcode()方法继承于Object类,其hashcode码为默认的内存地址,这样即便有相同含义的两个对象,比较也是不相等的
- 你知道java8的新特性吗,请简单介绍一下
- Lambda 表达式 − Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中。
- Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。
- jvm
- Java final volatile 关键字 volatile指令重排序 举个重排序例子
- final
- 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
- volatile不能保证线程安全 https://blog.csdn.net/chenchaofuck1/article/details/51702388
- volatile只能保证可见性 可见性指当一个线程修改了一个共享变量的值,其他线程能够立即得知这个修改,volatile的特殊规则就是read、load、use必须连续出现。assign、store、write动作必须连续出现。所以使用volatile变量能够保证必须先从主内存刷新最新的值,每次修改后必须立即同步回主内存当中。无法保证原子性,而自增操作并不是一个原子操作 https://kuaibao.qq.com/s/20180314G08I8P00?refer=spider
- 禁止指令重排序优化。
- 1)当程序执行到volatile变量的读操作或者写操作时,在其前面的操作的更改肯定全部已经进行,且结果已经对后面的操作可见;在其后面的操作肯定还没有进行;
- 2)在进行指令优化时,不能将在对volatile变量访问的语句放在其后面执行,也不能把volatile变量后面的语句放到其前面执行。
- java 缓存一致性 https://blog.csdn.net/sdr_zd/article/details/81323519
- Java并发编程中要保证的几个原则:原子性可见性有序性.
- 缓存一致性协议。这类协议有MSI、MESI(Illinois Protocol)、MOSI、Synapse、Firefly及 Dragon Protocol等。
- final
- happens-before原则
- 使用happens-before的概念来指定两个操作之间的执行顺序。由于这两个操作可以在一个线程之内,也可以是在不同线程之间。因此,JMM可以通过happens-before关系向程序员提供跨线程的内存可见性保证。
-
JVM对Java做了什么 堆和栈 垃圾回收算法
- jvm调优的方法
- 栈进行动态扩展时如果无法申请到足够内存,会抛出 OutOfMemoryError 异常。可以通过 -Xss 这个虚拟机参数来指定每个线程的 Java 虚拟机栈内存大小,在 JDK 1.4 中默认为 256K,而在 JDK 1.5+ 默认为 1M:
- 堆不需要连续内存,并且可以动态增加其内存,增加失败会抛出 OutOfMemoryError 异常。可以通过 -Xms 和 -Xmx 这两个虚拟机参数来指定一个程序的堆内存大小,第一个参数设置初始值,第二个参数设置最大值。
- 和堆一样不需要连续的内存,并且可以动态扩展,动态扩展失败一样会抛出 OutOfMemoryError 异常。用于存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
- 运行时常量池: Class 文件中的常量池(编译器生成的字面量和符号引用)会在类加载后被放入这个区域。
- 调优参数 https://zhuanlan.zhihu.com/p/58896619
- 调优过程 https://youzhixueyuan.com/jvm-performance-optimization.html
- 直接内存 NIO nativeIO, 搞得像C++
- 在 JDK 1.4 中新引入了 NIO 类,它可以使用 Native 函数库直接分配堆外内存,然后通过 Java 堆里的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在堆内存和堆外内存来回拷贝数据。
- 因为DirectByteBuffer是通过虚引用(Phantom Reference)来实现堆外内存的释放的。
- jvm的GC机制
- cms停顿了几次?为什么要有这些停顿? https://zhuanlan.zhihu.com/p/42934904
- CMS并非没有暂停,而是用两次短暂停来替代串行标记整理算法的长暂停,它的收集周期是这样:初始标记(CMS-initial-mark) -> 并发标记(CMS-concurrent-mark) -> 重新标记(CMS-remark) -> 并发清除(CMS-concurrent-sweep) ->并发重设状态等待下次CMS的触发(CMS-concurrent-reset)。其中的1,3两个步骤需要暂停所有的应用程序线程的。第一次暂停从root对象开始标记存活的对象,这个阶段称为初始标记;第二次暂停是在并发标记之后, 暂停所有应用程序线程,重新标记并发标记阶段遗漏的对象(在并发标记阶段结束后对象状态的更新导致)。第一次暂停会比较短,第二次暂停通常会比较长,并且 remark这个阶段可以并行标记。
- FullGC,MinorGC https://youzhixueyuan.com/the-difference-between-minor-gc-major-gc-full-gc.html
- Minor GC和Major GC其实就是年轻代GC和年老年GC的俗称。而在Hotspot VM具体实现的收集器:Serial GC, Parallel GC, CMS, G1 GC中,大致可以对应到某个Young GC和Old GC算法组合。
- Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历16次Minor GC还能在新生代中存活的对象,才会被送到老年代。永远有一个survivor space是空的,另一个非空的survivor space无碎片。
- Full GC定义是相对明确的,就是针对整个新生代、老生代、元空间(metaspace,java8以上版本取代perm gen)的全局范围的GC。
- 深入详解JVM内存模型与JVM参数详细配置 https://youzhixueyuan.com/jvm-memory-model-and-parameter-configuration.html
- 垃圾回收算法: https://youzhixueyuan.com/jvm-garbage-collection-algorithm.html
- cms停顿了几次?为什么要有这些停顿? https://zhuanlan.zhihu.com/p/42934904
- java类加载器有哪些
- 方法 loadClass()抛出的是 java.lang.ClassNotFoundException异常;方法 defineClass()抛出的是 java.lang.NoClassDefFoundError异常。
- 启动(Bootstrap)类加载器 扩展(Extension)类加载器 系统(System)类加载器
- 代理模式:双亲委派模型的工作过程如下:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都会传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求(它的搜索范围内没找到这个类)时,自加载器才会尝试自己加载。
- 代理模式:双亲委派模型是为了保证 Java 核心库的类型安全。所有 Java 应用都至少需要引用 java.lang.Object类,也就是说在运行的时候,java.lang.Object这个类需要被加载到 Java 虚拟机中。如果这个加载过程由 Java 应用自己的类加载器来完成的话,很可能就存在多个版本的 java.lang.Object类,而且这些类之间是不兼容的。通过双亲委派模型,对于 Java 核心库的类的加载工作由启动类加载器来统一完成,保证了 Java 应用所使用的都是同一个版本的 Java 核心库的类,是互相兼容的。
- Class.forName是一个静态方法,同样可以用来加载类。该方法有两种形式:Class.forName(String name, boolean initialize, ClassLoader loader)和 Class.forName(String className)。第一种形式的参数 name表示的是类的全名;initialize表示是否初始化类;loader表示加载时使用的类加载器。第二种形式则相当于设置了参数 initialize的值为 true,loader的值为当前类的类加载器。
- java反射机制及应用
- 反射则是一开始并不知道我要的类对象是什么,自然也无法使用 new 关键字来创建对象了。反射就是在运行时才知道要初始化/操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。
- 获取反射中的Class对象
- 第一种,使用 Class.forName 静态方法。当你知道该类的全路径名时,你可以使用该方法获取 Class 类对象。 Class.forName(“类的路径”).
- 第二种,使用 .class 方法。类名.class;
- 第三种,使用类对象的 getClass() 方法。实例.getClass()。
- 通过反射创建类对象 Class 对象的 newInstance() 方法 Constructor 对象的 newInstance() 方法
- 反射的功能:通过反射获取类属性、成员变量和方法、构造器,在运行时创建对象,在运行时调用对象的方法
- getFields() 方法 ; getDeclaredFields()
- synchronized 底层实现,4种锁。https://blog.csdn.net/javazejian/article/details/72828483
- synchronized可以保证在同一个时刻,只有一个线程可以执行某个方法或者某个代码块(主要是对方法或者代码块中存在共享数据的操作),同时synchronized可保证一个线程的变化(主要是共享数据的变化)被其他线程所看到(保证可见性,完全可以替代Volatile功能),这点确实也是很重要的。
- synchronized底层语义原理:Java 虚拟机中的同步(Synchronization)代码块基于进入和退出管程(Monitor)对象实现, 同步方法并不是调用指令读取运行时常量池中方法的 ACC_SYNCHRONIZED 标志来隐式实现的。
- 存在哪? java对象头 https://www.jianshu.com/p/a1e8170ed63c
- Java中提供了两种实现同步的基础语义:synchronized方法和synchronized块
- synchronized锁的状态;共有四种,只能从低到高升级,不会出现锁的降级。
- 无锁
- 无锁的特点就是修改操作在循环内进行,线程会不断的尝试修改共享资源。如果没有冲突就修改成功并退出,否则就会继续循环尝试。如果有多个线程修改同一个值,必定会有一个线程能修改成功,而其他修改失败的线程会不断重试直到修改成功。上面我们介绍的CAS原理及应用即是无锁的实现。无锁无法全面代替有锁,但无锁在某些场合下的性能是非常高的。
- 偏向锁
- 为了减少同一线程获取锁(会涉及到一些CAS操作,耗时)的代价而引入偏向锁。如果一个线程获得了锁,那么锁就进入偏向模式,此时Mark Word 的结构也变为偏向锁结构,当这个线程再次请求锁时,无需再做任何同步操作,即获取锁的过程。但是对于锁竞争比较激烈的场合,偏向锁就失效了。
- 轻量级锁(1.6之后加入的)
- 倘若偏向锁失败,虚拟机并不会立即升级为重量级锁,此时Mark Word 的结构也变为轻量级锁的结构。轻量级锁能够提升程序性能的依据是“对绝大部分的锁,在整个同步周期内都不存在竞争”,注意这是经验数据。需要了解的是,轻量级锁所适应的场景是线程交替执行同步块的场合,如果存在同一时间访问同一锁的场合,就会导致轻量级锁膨胀为重量级锁。
- 自旋锁
- 虚拟机让当前想要获取锁的线程做几个空循环(这也是称为自旋的原因),一般不会太久,可能是50个循环或100循环,在经过若干次循环后,如果得到锁,就顺利进入临界区。如果还不能获得锁,那就会将线程在操作系统层面挂起,这就是自旋锁的优化方式,这种方式确实也是可以提升效率的。最后没办法也就只能升级为重量级锁了。
- 重量级锁
- 效率低下,因为监视器锁(monitor)是依赖于底层的操作系统的Mutex Lock来实现的,而操作系统实现线程之间的切换时需要从用户态转换到核心态,这个状态之间的转换需要相对比较长的时间。
- https://juejin.im/post/5bfe6ddee51d45491b0163eb#heading-3
- 无锁
- synchronized的可重入性
- 当一个线程再次请求自己持有对象锁的临界资源时,这种情况属于重入锁,请求将会成功,在java中synchronized是基于原子性的内部锁机制,是可重入的,因此在一个线程调用synchronized方法的同时在其方法体内部调用该对象另一个synchronized方法,是允许的。
- 实现接口与继承类的区别
- 一个类只能继承一个类,但是可以实现多个接口。接口里面的方法都是抽象方法,必须要重写所有的方法。接口抽象的方法都要被重写,而继承的类不必这样。继承一般开发中用的会相比少一点,接口相比就应该会多一点.,接口主要是实现一种松耦合,便于以后的维护、升级,继承主要是提高代码的可重用性,很多东西都可以在父类中做好。子类可以直接用.
- JavaNIO和IO区别,如果分别用他们实现QQ有什么区别
- NIO是为了弥补IO操作的不足而诞生的,NIO的一些新特性有:非阻塞I/O,选择器,缓冲以及管道。管道(Channel),缓冲(Buffer) ,选择器( Selector)是其主要特征。1,IO是面向流的,NIO是面向块(缓冲区)的。2,IO是阻塞的,NIO是非阻塞的。
- 线程池知道吗?为什么用线程池,有什么好处 https://blog.csdn.net/qq_33453910/article/details/81413285
- 不使用线程池的话,所创建的线程数无法控制,比如一下子创建了几百几千个线程,电脑一下子就崩溃了。1:提高效率 创建好一定数量的线程放在池中,等需要使用的时候就从池中拿一个,这要比需要的时候创建一个线程对象要快的多。2:方便管理 可以编写线程池管理代码对池中的线程统一进行管理,比如说系统启动时由该程序创建100个线程,每当有请求的时候,就分配一个线程去工作, 如果刚好并发有101个请求,那多出的这一个请求可以排队等候,避免因无休止的创建线程导致系统崩溃
- java中的有哪些线程池?1.newCachedThreadPool创建一个可缓存线程池程;2.newFixedThreadPool 创建一个定长线程池;3.newScheduledThreadPool 创建一个定长线程池;4.newSingleThreadExecutor 创建一个单线程化的线程池
- 栈上的空间什么时候分配的
- Java栈内存是每个线程执行的时候分配的。 https://blog.csdn.net/Renirvana/article/details/54630785
- Java final volatile 关键字 volatile指令重排序 举个重排序例子
- 微服务相关
- 微服务vs巨石服务 https://www.cnblogs.com/linezero/p/microservices.html
- 最后还要强调:系统分解的目标并不仅仅是搞出一堆很小的服务,这不是目标;真正的目标是解决巨石型应用在业务急剧增长时遇到的问题。
- High frequency release.High density worker role.Flexible Scale up.Quickly start.Friendly to streaming.
- 每个服务足够内聚,足够小,代码容易理解、开发效率提高;服务之间可以独立部署,微服务架构让持续部署成为可能;每个服务可以各自进行x扩展和z扩展,而且,每个服务可以根据自己的需要部署到合适的硬件服务器上;提高容错性(fault isolation),一个服务的内存泄露并不会让整个系统瘫痪;系统不会被长期限制在某个技术栈上。
- 开发人员要处理分布式系统的复杂性;开发人员要设计服务之间的通信机制,对于需要多个后端服务的user case,要在没有分布式事务的情况下实现代码非常困难;
- 1.微服务架构的通信机制
- 方案 RESTful HTTP请求 + 内部服务之间通信。需要API gateway,由它负责与客户度对接,并将客户端的请求转化成对内部服务的一系列调用。这样做还有个好处是,服务升级不会影响到客户端,只需要修改API gateway即可。
- API gateway:内部服务之间的通信方式有两种:基于HTTP协议的同步机制(REST、RPC);基于消息队列的异步消息处理机制(AMQP-based message broker)。
- Dubbo是阿里巴巴开源的分布式服务框架,属于同步调用,当一个系统的服务太多时,需要一个注册中心来处理服务发现问题,例如使用ZooKeeper这类配置服务器进行服务的地址管理:服务的发布者要向ZooKeeper发送请求,将自己的服务地址和函数名称等信息记录在案;服务的调用者要知道服务的相关信息,具体的机器地址在ZooKeeper查询得到。这种同步的调用机制足够直观简单,只是没有“订阅——推送”机制。
- AMQP-based的代表系统是kafka、RabbitMQ等。这类分布式消息处理系统将订阅者和消费者解耦合,消息的生产者不需要消费者一直在线;消息的生产者只需要把消息发送给消息代理,因此也不需要服务发现机制。
- 两种通信机制都有各自的优点和缺点,实际中的系统经常包含两种通信机制。例如,在分布式数据管理中,就需要同时用到同步HTTP机制和异步消息处理机制。
- 方案 RESTful HTTP请求 + 内部服务之间通信。需要API gateway,由它负责与客户度对接,并将客户端的请求转化成对内部服务的一系列调用。这样做还有个好处是,服务升级不会影响到客户端,只需要修改API gateway即可。
- 2.分布式数据管理
- (1)A读B请求 单缺点是多一次RPC调用、而且调用的服务B必须保持在线。处理:A处存放一份信用卡额度的副本
- (2)处理更新请求 当一份数据位于多个服务上时,必须保证数据的一致性。分布式事务(Distributed transactions)
- 六种微服务架构的设计模式
- 聚合器微服务设计模式/代理微服务设计模式客户端并不聚合数据,但会根据业务需求的差别调用不同的微服务。代理可以仅仅委派请求,也可以进行数据转换工作。
- 链式微服务设计模式/分支微服务设计模式
- 数据共享微服务设计模式.自治是微服务的设计原则之一,就是说微服务是全栈式服务。但在重构现有的“单体应用(monolithic application)”时,SQL数据库反规范化可能会导致数据重复和不一致。因此,在单体应用到微服务架构的过渡阶段,可以使用这种设计模式,如下图所示:
- 异步消息传递微服务设计模式.虽然REST设计模式非常流行,但它是同步的,会造成阻塞。因此部分基于微服务的架构可能会选择使用消息队列代替REST请求/响应.
- 微服务架构的5个关键问题:https://www.infoq.cn/article/btx6geZA_qwmyr07LbOb
- OAuth2 的四种模式该如何选择?
- 如何理解 Apollo 配置中心的架构?
- 微服务网关 Zuul 承担哪些核心职责
- 设计微服务的最佳实践是什么 https://cloud.tencent.com/developer/article/1346868
- RPC 的实现原理 https://liuzhengyang.github.io/2016/12/16/rpc-principle/
- 首先需要有处理网络连接通讯的模块,负责连接建立、管理和消息的传输。其次需要有编解码的模块,因为网络通讯都是传输的字节码,需要将我们使用的对象序列化和反序列化。剩下的就是客户端和服务器端的部分,服务器端暴露要开放的服务接口,客户调用服务接口的一个代理实现,这个代理实现负责收集数据、编码并传输给服务器然后等待结果返回。
- 说说 Dubbo 的实现原理 https://www.zhihu.com/question/52133065/answer/129153953
- dubbo作为rpc框架,实现的效果就是调用远程的方法就像在本地调用一样。如何做到呢?就是本地有对远程方法的描述,包括方法名、参数、返回值,在dubbo中是远程和本地使用同样的接口;然后呢,要有对网络通信的封装,要对调用方来说通信细节是完全不可见的,网络通信要做的就是将调用方法的属性通过一定的协议(简单来说就是消息格式)传递到服务端;服务端按照协议解析出调用的信息;执行相应的方法;在将方法的返回值通过协议传递给客户端;客户端再解析;在调用方式上又可以分为同步调用和异步调用;简单来说基本就这个过程
- rest 幂等性 http://blog.720ui.com/2016/restful_idempotent/
- 如何解决api层的速率限制或支持重试和断路等功能 == 为什么要用 service mesh ?
- 网络挑战是由于Kubernetes等流行的容器编排软件所带来的。Kubernetes构建的就是要支持微服务架构。这允许开发和运维人员将功能抽象成一组pod,并将其作为“service”暴露出来,并通过定义好的API进行访问。Kubernetes支持DNS和基于TCP的L4负载均衡。基于TCP L4负载均衡的问题是它无法与L7(应用程序和API层)交互。对于任何L4负载均衡都是如此;它不是容器和Kubernetes独有的东西。L4负载均衡提供了对连接级别(TCP)协议和指标的可见性,但仅此而已。这使得很难(真的不可能)解决高阶问题,例如每秒请求数或事务等L7指标以及基于路径分割流量(路由请求)。这也意味着您无法在API层进行速率限制或支持重试和断路等关键功能。在service mesh中,所有流量都通过sidecar代理进行有效路由。因此它可以自动生成并将所需的指标提供给网格的其它部分。对于在容器环境中部署传统应用程序的组织而言,这非常有价值。
- 如何保持用户状态? https://zhaohuabing.com/2018/05/22/user_authentication_authorization/
- Token和Seesion主要的不同点是存储的地方不同。Session是集中存储在服务器中的;而Token是用户自己持有的,一般以cookie的形式存储在浏览器中。Token中保存了用户的身份信息,每次请求都会发送给服务器,服务器因此可以判断访问者的身份,并判断其对请求的资源有没有访问权限。没有了cookie,session就没用了。
- 实现单点登录
- Now Technical transfer; Replicate service for more partners; Open API for Speech/text Models
- 必要的微服务架构知识
- API网关 http://developer.51cto.com/art/201807/579943.htm
- 部署方式 蓝绿发布,Rolling update(滚动发布) 灰度发布/金丝雀部署 https://www.jianshu.com/p/022685baba7d
- 微服务vs巨石服务 https://www.cnblogs.com/linezero/p/microservices.html
- 开源框架/分布式
- 什么是分布式事务 怎么做 https://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html
- CAP定理 一致性(Consistency) : 客户端知道一系列的操作都会同时发生(生效);可用性(Availability) : 每个操作都必须以可预期的响应结束。分区容错性(Partition tolerance) : 即使出现单个组件无法可用,操作依然可以完成。具体地讲在分布式系统中,在任何数据库设计中,一个Web应用至多只能同时支持上面的两个属性。显然,任何横向扩展策略都要依赖于数据分区。因此,设计人员必须在一致性与可用性之间做出选择。
- 其中,XA 是一个两阶段提交协议,该协议分为以下两个阶段:
- 第一阶段:事务协调器要求每个涉及到事务的数据库预提交(precommit)此操作,并反映是否可以提交.
- 第二阶段:事务协调器要求每个数据库提交数据。
- BASE理论;Basically Available(基本可用);Soft state(软状态);Eventually consistent(最终一致性)
- 分布式锁
- 2.1为何需要分布式锁。效率 https://juejin.im/post/5bbb0d8df265da0abd3533a5
- 5.1Redis分布式锁简单实现
- spring ioc aop springboot差别
- redis主从复制 Remote Dictionary Server
- azure redis
- 缓存穿透,缓存与数据库双写一致 https://www.cnblogs.com/Java3y/p/10266306.html
- 史上最全Redis面试49题(含答案):哨兵+复制+事务+集群+持久化等: https://segmentfault.com/a/1190000017339258 -Redis有哪几种数据淘汰策略?
- 主从复制是为了数据备份
- Redis是一个基于内存的高性能Key-Value存储系统,它支持存储的value类型很多,包括下面的和有序集合)。这些数据类型都支持push/pop、add/remove以及取交集和并集等丰富的操
- 数据结构 – hash:通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题。很好的解决了问题。 list:Redis list的实现为一个双向链表,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。
-
thrift RPC原理
- 如果登陆了如何其他服务器知道
- 微服务架构的身份认证问题
- SSO原理,应用场景
- 这种方案意味着每个面向用户的服务都必须与认证服务交互,这会产生大量非常琐碎的网络流量和重复的工作,当动辄数十个微应用时,这种方案的弊端会更加明显。单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。
- 分布式session方式
- 例如阿里有很多系统分割为多个子系统,独立部署后,不可避免的会遇到会话管理的问题,类似这样的电商网站一般采用分布式Session实现。再进一步可以根据分布式Session,建立完善的单点登录或账户管理系统。
- 客户端 Token 与 API 网关结合
- SSO原理,应用场景
- springboot 和 springmvc 和 spring 区别
-
缓存一致性
- LVS负载均衡怎么支持高并发,负载均衡发生在网络的哪一层
- LVS是四层负载均衡,也就是说建立在OSI模型的第四层——传输层之上,传输层上有我们熟悉的TCP/UDP,LVS支持TCP/UDP的负载均衡。
- 实现分布式锁
- 聊聊ZK和Consul
- ZK的实现,他是用来干嘛的
- 什么是分布式事务 怎么做 https://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html
- 数据库相关
- 数据库索引B树和B+树有什么区别,B+树的高度何时发生改变
- 卫星数据:指的是索引元素所指向的数据记录。比如数据库中的某一行。B树中无论中间节点还是叶子节点都带有卫星数据。B+树中,只有叶子节点带卫星数据,其他中间节点仅仅是索引,没有数据关联。
- 综合起来,B+树比B-树优势有三个:1、IO次数更少2、查询性能稳定3、范围查询简便。
- 创建索引的过程
- Like查询的过程
- 百度真题
- 面项目数据库,全程怼数据库(数据库索引优化,联合索引,如何建立索引,数据分裤分表,种类使用场景,如何对数据进行分裤有哪些方式)。面项目数据库(写出数据的表结构表中的字段,表之间的关联,用ER图画,不会,忘了。他说没关系,现在让你设计这个数据库表结构你会如何设计,设计完后,他说需求我写sql语句。我写的比较low,他们会不会数据库连接,左连接,右连接,全链接等)
- 数据库 事务 隔离级别
- 在说分布式事务之前,我们先从数据库事务说起。 数据库事务可能大家都很熟悉,在开发过程中也会经常使用到。但是即使如此,可能对于一些细节问题,很多人仍然不清楚。比如很多人都知道数据库事务的几个特性:原子性(Atomicity )、一致性( Consistency )、隔离性或独立性( Isolation)和持久性(Durabilily),简称就是ACID。但是再往下比如问到隔离性指的是什么的时候可能就不知道了,或者是知道隔离性是什么但是再问到数据库实现隔离的都有哪些级别,或者是每个级别他们有什么区别的时候可能就不知道了
- 数据库索引数据结构 哈希,B+树索引,优劣及应用比较,时间复杂度分析
- 数据库索引B树和B+树有什么区别,B+树的高度何时发生改变
- 操作系统 线程和进程 为什么切换线程消耗小 什么时候进程什么时候线程 虚拟内存 页式存储
- google的: 进程切换比线程切换开销大是因为进程切换时要切页表,而且往往伴随着页调度,因为进程的数据段代码段要换出去,以便把将要执行的进程的内容换进来。本来进程的内容就是线程的超集。而且线程只需要保存线程的上下文(相关寄存器状态和栈的信息)就好了,动作很小\
- 内存置换算法 FIFO LRU LFU OPT clock
- IO多路复用,五大IO模型
- select poll,epoll都是IO多路复用的一种机制,就是通过一种机制可以监视多个文件描述符,一旦某个文件描述符就绪(一般是读就绪或者写就绪),就能够通知进程进行相应的读写操作,他们三个本质上都是同步IO,因为 它们都需要在读写事件就绪后自己负责读写操作,也就是读写过程中是阻塞的,而异步IO无需自己进行读写,它只负责发起事件具体的实现由别的完成
- poll: 1、大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。 2、poll还有一个特点是“水平触发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd
- epoll: epoll支持水平触发和边缘触发,最大的特点在于边缘触发,它只告诉进程哪些fd刚刚变为就需态,并且只会通知一次。还有一个特点是,epoll使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用类似callback的回调机制来激活该fd,epoll_wait便可以收到通知
- 开放性问题
- 了解设计模式吗?
- 场景题 额度调整不加锁?
- 缓存系统如何提高命中率? https://www.cnblogs.com/dinglang/p/6117309.html
- 通过缓存预加载(预热)、增加存储容量、调整缓存粒度、缓存的失效和更新策略等手段来提高命中率
- 反问
- 公司技术栈
技术面问题
- 史上最全阿里面试题
- 知名公司的java面试题
- JMM主要就是围绕着如何在并发过程中如何处理原子性、可见性和有序性这3个特征来建立的,通过解决这三个问题,可以解除缓存不一致的问题。而volatile跟可见性和有序性都有关。
- 经典的133个问题列表
- 乐观锁
- 两种锁的使用场景 和 从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。
- java buffer机制
- mapreduce
- 进程通信
- gc设计模式
- 面向对象的特征
- final, finally, finalize 的区别
- int 和 Integer 有什么区别
- 重载和重写的区别
- 抽象类和接口有什么区别
- 说说反射的用途及实现
- 说说自定义注解的场景及实现
- HTTP 请求的 GET 与 POST 方式的区别
- session 与 cookie 区别
- session 分布式处理
- JDBC 流程
- MVC 设计思想
- equals 与 == 的区别
- 集合
- List 和 Set 区别
- List 和 Map 区别
- Arraylist 与 LinkedList 区别
- ArrayList 与 Vector 区别
- HashMap 和 Hashtable 的区别
- HashSet 和 HashMap 区别
- HashMap 和 ConcurrentHashMap 的区别
- HashMap 的工作原理及代码实现
- ConcurrentHashMap 的工作原理及代码实现
- 线程
- 创建线程的方式及实现
- sleep() 、join()、yield()有什么区别
- 说说 CountDownLatch 原理
- 说说 CyclicBarrier 原理
- 说说 Semaphore 原理
- 说说 Exchanger 原理
- 说说 CountDownLatch 与 CyclicBarrier 区别
- ThreadLocal 原理分析
- 讲讲线程池的实现原理
- 线程池的几种方式
- 线程的生命周期
- 锁机制
- 说说线程安全问题
- volatile 实现原理
- synchronize 实现原理
- synchronized 与 lock 的区别
- CAS 乐观锁
- ABA 问题
- 乐观锁的业务场景及实现方式
- 核心篇
- 数据存储
- MySQL 索引使用的注意事项
- 说说反模式设计
- 说说分库与分表设计
- 分库与分表带来的分布式困境与应对之策
- 说说 SQL 优化之道
- MySQL 遇到的死锁问题
- 存储引擎的 InnoDB 与 MyISAM
- 数据库索引的原理
- 为什么要用 B-tree
- 聚集索引与非聚集索引的区别
- limit 20000 加载很慢怎么解决
- 选择合适的分布式主键方案
- 选择合适的数据存储方案
- ObjectId 规则
- 聊聊 MongoDB 使用场景
- 倒排索引
- 聊聊 ElasticSearch 使用场景
- 缓存使用
- Redis 有哪些类型
- Redis 内部结构
- 聊聊 Redis 使用场景
- Redis 持久化机制
- Redis 如何实现持久化
- Redis 集群方案与实现
- Redis 为什么是单线程的
- 缓存奔溃
- 缓存降级
- 使用缓存的合理性问题
- 消息队列
- 消息队列的使用场景
- 消息的重发补偿解决思路
- 消息的幂等性解决思路
- 消息的堆积解决思路
- 自己如何实现消息队列
- 如何保证消息的有序性
- 框架篇
- Spring
- BeanFactory 和 ApplicationContext 有什么区别
- Spring Bean 的生命周期
- Spring IOC 如何实现
- 说说 Spring AOP
- Spring AOP 实现原理
- 动态代理(cglib 与 JDK)
- Spring 事务实现方式
- Spring 事务底层原理
- 如何自定义注解实现功能
- Spring MVC 运行流程
- Spring MVC 启动流程
- Spring 的单例实现原理
- Spring 框架中用到了哪些设计模式
- Spring 其他产品(Srping Boot、Spring Cloud、Spring Secuirity、Spring Data、Spring - AMQP 等)
- Netty
- 为什么选择 Netty
- 说说业务中,Netty 的使用场景
- 原生的 NIO 在 JDK 1.7 版本存在 epoll bug
- 什么是TCP 粘包/拆包
- TCP粘包/拆包的解决办法
- Netty 线程模型
- 说说 Netty 的零拷贝
- Netty 内部执行流程
- Netty 重连实现
- 微服务篇
- 微服务
- 前后端分离是如何做的
- 微服务哪些框架
- 你怎么理解 RPC 框架
- 说说 RPC 的实现原理
- 说说 Dubbo 的实现原理
- 你怎么理解 RESTful
- 说说如何设计一个良好的 API
- 如何理解 RESTful API 的幂等性
- 如何保证接口的幂等性
- 说说 CAP 定理、 BASE 理论
- 怎么考虑数据一致性问题
- 说说最终一致性的实现方案
- 你怎么看待微服务
- 微服务与 SOA 的区别
- 如何拆分服务
- 微服务如何进行数据库管理
- 如何应对微服务的链式调用异常
- 对于快速追踪与定位问题
- 微服务的安全
- 分布式
- 谈谈业务中使用分布式的场景
- Session 分布式方案
- 分布式锁的场景
- 分布是锁的实现方案
- 分布式事务
- 集群与负载均衡的算法与实现
- 说说分库与分表设计
- 分库与分表带来的分布式困境与应对之策
- 安全&性能
- 安全问题
- 安全要素与 STRIDE 威胁
- 防范常见的 Web 攻击
- 服务端通信安全攻防
- HTTPS 原理剖析
- HTTPS 降级攻击
- 授权与认证
- 基于角色的访问控制
- 基于数据的访问控制
- 性能优化
- 性能指标有哪些
- 如何发现性能瓶颈
- 性能调优的常见手段
- 说说你在项目中如何进行性能调优
- 工程篇
- 需求分析
- 你如何对需求原型进行理解和拆分
- 说说你对功能性需求的理解
- 说说你对非功能性需求的理解
- 你针对产品提出哪些交互和改进意见
- 你如何理解用户痛点
- 设计能力
- 说说你在项目中使用过的 UML 图
- 你如何考虑组件化
- 你如何考虑服务化
- 你如何进行领域建模
- 你如何划分领域边界
- 说说你项目中的领域建模
- 说说概要设计
- 设计模式
- 你项目中有使用哪些设计模式
- 说说常用开源框架中设计模式使用分析
- 说说你对设计原则的理解
- 23种设计模式的设计理念
- 设计模式之间的异同,例如策略模式与状态模式的区别
- 设计模式之间的结合,例如策略模式+简单工厂模式的实践
- 设计模式的性能,例如单例模式哪种性能更好。
- 业务工程
- 你系统中的前后端分离是如何做的
- 说说你的开发流程
- 你和团队是如何沟通的
- 你如何进行代码评审
- 说说你对技术与业务的理解
- 说说你在项目中经常遇到的 Exception
- 说说你在项目中遇到感觉最难Bug,怎么解决的
- 说说你在项目中遇到印象最深困难,怎么解决的
- 你觉得你们项目还有哪些不足的地方
- 你是否遇到过 CPU 100% ,如何排查与解决
- 你是否遇到过 内存 OOM ,如何排查与解决
- 说说你对敏捷开发的实践
- 说说你对开发运维的实践
- 介绍下工作中的一个对自己最有价值的项目,以及在这个过程中的角色
- 软实力
- 说说你的亮点
- 说说你最近在看什么书
- 说说你觉得最有意义的技术书籍
- 工作之余做什么事情
- 说说个人发展方向方面的思考
- 说说你认为的服务端开发工程师应该具备哪些能力
- 说说你认为的架构师是什么样的,架构师主要做什么
- 说说你所理解的技术专家