1-Java基础
1.1-String和StringBuffer区别,为什么是可变的,不可变的
String 类中使用 final 关键字修饰字符数组来保存字符串,private final char value[],所以 String 对象是不可变的,String 类中使用 final 关键字修饰字符数组来保存字符串,private final char value[],所以 String 对象是不可变的
StringBuilder 与 StringBuffer 都继承自 AbstractStringBuilder 类,在 AbstractStringBuilder 中也是使用字符数组保存字符串char[]value 但是没有用 final 关键字修饰,所以这两种对象都是可变的
1.2-ArrayList和LinkedList区别,LindkedList中的列表是单向链表还是双向链表
1. 都不是线程安全的
2. ArrayList底层使用的是的Object数组,LinkedList底层使用的是双向链表
3. ArrayList支持随机访问
1.3-HashMap实现原理,put过程,put过程中多线程情况下会出现什么问题(会出现死循环,为什么会出现死循环),链表什么时候及为什么要转红黑树?为什么扩容的时候必须是2的幂次方……
1. JDK1.8之前 HashMap 底层是 数组+链表 ,1.8之后数组+链表+红黑树
2. 默认数组长度是16,默认扩容加载因子是0.75,链表长度大于8变为红黑树,小于6变为数组
3.当多线程put时,当数组需要扩容时重新进行rehash,transfer方法会修改链表中node的前后指针,有可能出现环链从而死锁
4. 这个数组下标的计算方法是 (n - 1) & hash , 另外扩容为2的幂次方,数组扩容时数据要么待在原来的下标, 或者移动到新数组的高位下标
1.4-HashTable怎么保证线程安全的
HashTable 内部的方法基本都经过synchronized 修饰,效率太低,被抛弃的集合,建议使用concurrentHashMap
1.5-ConcurrentHashMap实现线程安全的原理
JDK 1.7 首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。
JDK 1.8 ConcurrentHashMap取消了Segment分段锁,采用CAS和synchronized来保证并发安全。synchronized只锁定当前链表或红黑二叉树的首节点,这样只要hash不冲突,就不会产生并发,效率又提升N倍。
1.6-LinkedHashMap怎么做到有序的
主要是基于 HashMap + 双向链表
1.7-Java中线程的状态
线程创建之后处于初始状态,调用start之后处于ready状态,得到cup时候处于running状态,ready和running合称运行状态,当调用wait/join之后处于等待状态,需要调用notify/notifyAll回到运行状态,当调用sleep或者notify(long)处于超时等待状态,当超时时间执行完毕就自动恢复到运行状态,当调用sysnchroinzed处于阻塞状态,当获得锁之后回到运行状态,运行完成进入终止状态
1.8-Synchronized锁的实现原理,为什么monitorexit指令会出现两次
monitorenter、monitorexit、monitorexit
monitorenter 锁开始,monitorexit 锁正常退出,monitorexit 抛出异常锁退出
https://www.cnblogs.com/aspirant/p/11470858.html
1.9-RetrantLock实现原理,跟Synchronized的区别
ReentrantLock是基于AQS实现的,AQS核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。
- 两者都是可重入锁
- synchronized 依赖于 JVM 而 ReentrantLock 依赖于 API
- ReentrantLock 支持公平锁,非公平锁,中断等待,通知等
- https://www.cnblogs.com/xrq730/p/4979021.html
1.10-如何让线程A,B,C按照顺序执行(join,CountDownLatch)
join、CountDownLatch、单线程池
https://www.cnblogs.com/wenjunwei/p/10573289.html
1.11-Java中的几种常用线程池及他们的特点
- FixedThreadPool : 该方法返回一个固定线程数量的线程池。该线程池中的线程数量始终不变。当有一个新的任务提交时,线程池中若有空闲线程,则立即执行。若没有,则新的任务会被暂存在一个任务队列中,待有线程空闲时,便处理在任务队列中的任务。
- SingleThreadExecutor: 方法返回一个只有一个线程的线程池。若多余一个任务被提交到该线程池,任务会被保存在一个任务队列中,待线程空闲,按先入先出的顺序执行队列中的任务。
- CachedThreadPool: 该方法返回一个可根据实际情况调整线程数量的线程池。线程池的线程数量不确定,但若有空闲线程可以复用,则会优先使用可复用的线程。若所有线程均在工作,又有新的任务提交,则会创建新的线程处理任务。所有线程在当前任务执行完毕后,将返回线程池进行复用。
- ScheduledThreadPool:这是个可重用固定个数的线程池,当前线程数大于总数则会进行等待,并且可以设置线程延迟执行时间
1.12-线程池参数,工作过程,线程池拒绝策略,线程池中任务队列的特点
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
ThreadPoolExecutor
3 个最重要的参数:
-
corePoolSize
: 核心线程数线程数定义了最小可以同时运行的线程数量。 -
maximumPoolSize
: 当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。 -
workQueue
: 当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。 -
handler
:饱和(拒绝)策略。
ThreadPoolExecutor
其他常见参数:
-
keepAliveTime
:当线程池中的线程数量大于corePoolSize
的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了keepAliveTime
才会被回收销毁; -
unit
:keepAliveTime
参数的时间单位。 -
threadFactory
:executor 创建新线程的时候会用到。
拒绝策略:
-
ThreadPoolExecutor.AbortPolicy
:抛出RejectedExecutionException
来拒绝新任务的处理。 -
ThreadPoolExecutor.CallerRunsPolicy
:调用执行自己的线程运行任务。您不会任务请求。但是这种策略会降低对于新任务提交速度,影响程序的整体性能。另外,这个策略喜欢增加队列容量。如果您的应用程序可以承受此延迟并且你不能任务丢弃任何一个任务请求的话,你可以选择这个策略。 -
ThreadPoolExecutor.DiscardPolicy
: 不处理新任务,直接丢弃掉。 -
ThreadPoolExecutor.DiscardOldestPolicy
: 此策略将丢弃最早的未处理的任务请求。
workQueue:(阻塞队列)
ArrayBlockingQueue:
一个对象数组+一把锁+两个条件
入队与出队都用同一把锁
在只有入队高并发或出队高并发的情况下,因为操作数组,且不需要扩容,性能很高
采用了数组,必须指定大小,即容量有限
LinkedBlockingQueue:
一个单向链表+两把锁+两个条件
两把锁,一把用于入队,一把用于出队,有效的避免了入队与出队时使用一把锁带来的竞争。
在入队与出队都高并发的情况下,性能比ArrayBlockingQueue高很多
采用了链表,最大容量为整数最大值,可看做容量无限
DelayQueue:
DelayQueue中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。DelayQueue是一个没有大小限制的队列,因此往队列中插入数据的操作(生产者)永远不会被阻塞,而只有获取数据的操作(消费者)才会被阻塞。
1.13-乐观锁(CAS)和悲观锁(Synchronized,RetrantLock),CAS原理,ABA问题,CAS的优缺点,CAS轮询占用CPU为什么还有很多实现都是用的CAS
1.14-Volatile的作用
依靠内存屏障实现
1.可见性 读取主内存
2.有序性防止指令重排
1.15-内存屏障
内存屏障(Memory Barrier,或有时叫做内存栅栏,Memory Fence)是一种CPU指令,用于控制特定条件下的重排序和内存可见性问题。Java编译器也会根据内存屏障的规则禁止重排序。
https://www.cnblogs.com/snow-man/p/10876362.html
1.16-JMM内存模型
我们常说的JVM内存模式指的是JVM的内存分区;而Java内存模式是一种虚拟机规范。
Java虚拟机规范中定义了Java内存模型(Java Memory Model,JMM),用于屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的并发效果,JMM规范了Java虚拟机与计算机内存是如何协同工作的:规定了一个线程如何和何时可以看到由其他线程修改过后的共享变量的值,以及在必须时如何同步的访问共享变量。
https://zhuanlan.zhihu.com/p/29881777
1.17-Threadlocal原理
ThreadLocal
内部维护的是一个类似 Map
的ThreadLocalMap
数据结构,key
为当前对象的 Thread
对象,值为 Object 对象。
如果你创建了一个ThreadLocal
变量,那么访问这个变量的每个线程都会有这个变量的本地副本,这也是ThreadLocal
变量名的由来。他们可以使用 get()
和 set()
方法来获取默认值或将其值更改为当前线程所存的副本的值,从而避免了线程安全问题。
1.18-死锁:产生死锁必须具备以下四个条件,避免死锁破坏四个条件其中的一个即可
- 互斥条件:该资源任意一个时刻只由一个线程占用。
- 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不剥夺条件:线程已获得的资源在末使用完之前不能被其他线程强行剥夺,只有自己使用完毕后才释放资源。
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
2-JVM
2.1-JVM内存结构(运行时数据区)
线程私有的:
1.程序计数器
2.虚拟机栈
3.本地方法栈
线程共享的:
1.堆
2.方法区
3.直接内存(非运行时数据区的一部分)
2.2-常用垃圾回收算法
1.标记清除
2.标记整理
3.复制算法
4.分代收集算法
2.3-常常用的垃圾收集器
1.Serial / Serial Old
Serial/SerialOld收集器是最基本最古老的收集器,它是一个单线程收集器,并在在它进行垃圾收集时,必须暂停所有的用户线程。Serial收集器是针对新生代的收集器,采用的是复制算法 Serial Old收集器是针对老年代的收集器,采用的是复制-整理算法。
2.ParNew
ParNew收集器是Serial收集器的多线程版本,使用多个线程进行垃圾回收
3.Parallel Scavenge
Parallel Scavenge收集器是一个新生代的多线程收集器,使用复制算法,它在回收期间需要暂停其他的用户线程。
4.Parallel Old
Parallel Old是Parallel Scavenge收集器的老年代版本,使用的是标记-整理算法
5.CMS
CMS收集器是一种以获取最短停顿时间为目标的收集器,它是一种并发收集器,采用的是标记-清除算法
6.G1
G1收集器是当今收集器技术发展最前沿的成果,它是一款面向服务端应用的收集器,它能充分利用多CPU,多核环境,因此它是一款并行与并发的收集器
2.3-垃圾回收过程
判断哪些对象死亡,将死亡的对象进行清除
分代收集详述:
1、所有new出来的对象都会最先分配到新生代区域中,两个survivor(S0和S1)区域初始化是为空的;
2、当伊甸园区域满了之后,就会引发一次minor garbage collection(小型垃圾回收);
3、当在minor garbage collection(小型垃圾回收),存活下来的对象就会被移到S0区域;
4、当伊甸园区域再次填满时,又会发生下一次垃圾回收,存活下来的对象会被移到survivor区域,而未存活的对象则被直接删除,但是,不同的是,在这次垃圾回收中,存活对象和之前在S0区域中的对象都会移到S1区域中。一旦所有对象都被移到S1区域中,那么S0中的对象就会被清除;
5、下一次的垃圾回收的时候,又会重复上次的步骤,清除需要回收的对象,并且切换一次survivor区域,所有存活的对象都被移到S0,伊甸园区域和S1区域被清除;
6、重复以上步骤,并记录对象的年龄(记录垃圾回收的次数),当有对象的年龄达到一定的阈值时,就将新生代中的对象移到到老年代
7、接下来垃圾回收就会重复以上步骤,不断的进行对象的清除和年代的移动;
8、当达到老年代回收条件时会触发Major GC进行老年代回收
2.4堆内存的分代:Eden,from,to,Old
<img src="https://img-blog.csdn.net/20160330210437130" alt="分代算法" style="zoom:60%;" />
2.5-JVM1.7和1.8的区别,去掉了永久代,改成了Metaspace,为什么
JDK 1.8 的时候,方法区(HotSpot的永久代)被彻底移除了(JDK1.7就已经开始了),取而代之是元空间,元空间使用的是直接内存
1.整个永久代有一个 JVM 本身设置固定大小上限,无法进行调整和优化
2.简化垃圾回收
3.虚拟机整合
2.6-CMS收集器工作过程及特点
工作过程: 初始标记-->并发标记-->重新标记-->并发清除
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。它而非常符合在注重用户体验的应用上使用。
CMS(Concurrent Mark Sweep)收集器是HotSpot虚拟机第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作。
2.7-G1收集器工作过程及特点
1.初始标记
2.并发标记
3.最终标记
4.筛选回收
G1 (Garbage-First)是一款面向服务器的垃圾收集器,主要针对配备多颗处理器及大容量内存的机器. 以极高概率满足GC停顿时间要求的同时,还具备高吞吐量性能特征.
2.8-怎么进行JVM调优
https://www.iteye.com/blog/pengjiaheng-552456
2.9-用什么查看内存映像,jmap+MAT
2.10-怎么排查CPU飙高,top+jstack
2.11 公司的jvm参数
-Xmn512m 年轻代大小(1.4or lator)
-Xms1024m 初始堆大小 物理内存的1/64(<1GB)
-Xmx1024m 最大堆大小 物理内存的1/4(<1GB)
-XX:+UseConcMarkSweepGC 使用CMS内存收集
-XX:CMSInitiatingOccupancyFraction=70 使用cms作为垃圾回收使用70%后开始CMS收集
-XX:MaxDirectMemorySize=256m
-XX:+UseCMSInitiatingOccupancyOnly 使用手动定义初始化定义开始CMS收集
-XX:SurvivorRatio=8 Eden区与Survivor区的大小比值
-XX:+ExplicitGCInvokesConcurrent
-XX:MetaspaceSize=128m 设置元数据空间初始大小(取代-XX:PermSize)
-XX:MaxMetaspaceSize=256m 设置元数据空间最大值(取代之前-XX:MaxPermSize)
-XX:-OmitStackTraceInFastThrow
-XX:+PrintGCDetails 输出格式
-XX:+PrintGCDateStamps 打印GC日期
-Xloggc:/var/www/logs/gc-%t.log 把相关日志信息记录到文件以便分析.
-XX:+UseGCLogFileRotation 开启滚动日志记录
-XX:NumberOfGCLogFiles=5 滚动数量,命名为filename.0, ..... filename.n-1, 然后再从filename.0 开始,并覆盖已经存在的文件
-XX:GCLogFileSize=10m 文件大小
-XX:+HeapDumpOnOutOfMemoryError 出现内存溢出时存储堆信息
-XX:HeapDumpPath=/var/www/logs 堆快照存储位置
-Djava.io.tmpdir=/var/www/tmp
3-MySQL
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1hWR8GzJ-1588925877291)(/Users/yqx/Desktop/数据库索引总结.png)]
3.1-Mysql的索引原理B+树,聚簇索引,辅助索引的区别,为什么辅助索引不直接报存数据而是主键的值
聚簇索引:树的叶节点data域保存了完整的数据记录
辅助索引:辅助索引的叶节点data域存储相应记录主键的值(不是地址)
回表:在根据辅助索引查找时,则需要先取出主键的值,再走一遍主索引
3.2-什么情况下索引会失效
- or
- like 以 % 开头,以%结尾会命中索引,eg: '三%'
- 隐式转换
- 不遵循最左原则
- MYSQL优化器估计使用索引比全部扫描要慢
- !=或<>
- is null 、 is not null
3.3-联合索引什么情况会失效
遵循最左原则,eg:联合索引a,b,c
命中索引:a、a,b、a,b,c
https://zhuanlan.zhihu.com/p/108179618
https://zhuanlan.zhihu.com/p/108179618
https://zhuanlan.zhihu.com/p/108179618
3.4-怎么判断对一个表的哪个字段建索引,建索引要注意什么
- 在经常需要搜索查询的列上创建索引,可以加快搜索的速度;
- 在作为主键的列上创建索引,强制该列的唯一性和组织表中数据的排列结构;
- 在经常用在连接的列上创建索引,这些列主要是一些外键,可以加快连接的速度;
- 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;
- 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询 时间;
- 在经常使用在Where子句中的列上面创建索引,加快条件的判断速度;
- 为经常出现在关键字order by、group by、distinct后面的字段,建立索引。
1.尽量量选择区分度⾼高的列列作为索引,区分度的公式是count(distinct col)/ count(*),表示字段不不重复的⽐比例例,⽐比例例越⼤大扫描的记录数越少
2.单个索引中的字段数最好不不超过3个
3.对⻓长度⼤大于100的字段建⽴立索引时,按需求恰当的使⽤用前缀索引
3.5-InnoDB和MyISAM的区别
- InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;
- InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;
- InnoDB:是聚集索引,数据文件是和(主键)索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。
MyISAM:是非聚集索引,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的 - InnoDB支持表、行(默认)级锁,而MyISAM支持表级锁
3.6-MySQL的锁,表锁,行锁
- 表级锁: MySQL中锁定 粒度最大 的一种锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。其锁定粒度最大,触发锁冲突的概率最高,并发度最低,MyISAM和 InnoDB引擎都支持表级锁。
- 行级锁: MySQL中锁定 粒度最小 的一种锁,只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。
3.7-Mysql的乐观锁
https://zhuanlan.zhihu.com/p/29150809
3.8-MySQL的MVCC
https://segmentfault.com/a/1190000012650596
3.9-Mysql的四种隔离级别分别解决了什么问题,怎么解决的,默认哪种隔离级别,Mysql的脏读,幻读等
3.10-怎么进行SQL优化(慢查询+explain执行计划)
http://blog.itpub.net/31555484/viewspace-2565387
3.11-Explain执行计划
https://www.jianshu.com/p/fd781d6e1158
3.12-Mysql主从复制原理,怎么解决主从复制延迟问题
https://www.cnblogs.com/idoljames/p/11694039.html
3.13-Mysql的分库分表弄过吗,分表之后有什么问题,怎么解决(分页查询问题怎么解决?)
4-Redis
4.1-Redis常用的数据类型,有了解这些数据类型底层是怎么实现的吗
string、list、hash、set、zset
4.2-Redis的缓存雪崩,缓存击穿问题怎么解决,布隆过滤器原理
雪崩:缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。
击穿:缓存穿透说简单点就是大量请求的 key 根本不存在于缓存中,导致请求直接到了数据库上,根本没有经过缓存这一层
1.最基本的就是首先做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端。比如查询的数据库 id 不能小于 0、传入的邮箱格式不对的时候直接返回错误消息给客户端等等。
2.布隆过滤器
4.3-Redis的热点key怎么发现,怎么解决
4.4-数据量很多的情况下,怎么用redis怎么统计日活,月活,bitmap,hyperLog……
https://www.cnblogs.com/yulibostu/articles/10337444.html
4.5-Redis的Master/slave和集群的区别,哨兵是干什么的
1.主从:一个Master可以有多个Slaves,写主,读从,master节点挂了以后,不会slave节点重新选一个master
2.集群:cluster的出现是为了解决单机Redis容量有限的问题,将Redis的数据根据一定的规则分配到多台机器,通过cluster可以实现主从和master重选功能。多主多从,最小的是3主3从,必须是基数,涉及到master的选举
3.哨兵:sentinel模式是建立在主从模式的基础上,当master节点挂了以后,sentinel会在slave中选择一个做为master,并修改它们的配置文件,其他slave的配置文件也会被修改,比如slaveof属性会指向新的master,sentinel可以理解为是主从的一个代理
4.6-你们的Redis用的哪种部署方式
cluster
4.7-Redis和memercached区别,哪个单线程,哪个多线程
4.8-Redis的持久化,aof,rdb
4.9-Redis的缓存淘汰策略
- volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
- volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
- volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
- allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的)
- allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
- no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!
4.0版本后增加以下两种:
- volatile-lfu:从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰
- allkeys-lfu:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的key
4.10-用过哪些redis的数据类型
string、list、hash、set
4.11-Redis的发布订阅
4.12-Redis怎么实现分布式锁,redis分布式锁当前业务没有执行完但是锁过期了怎么办,锁续期
加锁
SET resource-name anystring NX EX max-lock-time
解锁
if redis.call("get",KEYS[1]) == ARGV[1]
then
return redis.call("del",KEYS[1])
else
return 0
end
https://blog.csdn.net/lzhcoder/article/details/88387751
https://juejin.im/post/5d122f516fb9a07ed911d08c
4.13-数据库与缓存双写不一致怎么解决
5-Zookeeper
zookeeper=文件系统+监听通知机制。
5.1-Zk有哪些节点类型
1.持久化目录节点(PERSISTENT)
客户端与zookeeper断开连接后,该节点依旧存在
2.持久化顺序编号目录节点(PERSISTENT_SEQUENTIAL)
客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号
3.临时目录节点(EPHEMERAL)
客户端与zookeeper断开连接后,该节点被删除
4.临时顺序编号目录节点(EPHEMERAL_SEQUENTIAL)
客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号
5.2-Zk的原理ZAB协议,master选举过程,数据同步过程
http://www.jasongj.com/zookeeper/fastleaderelection/
https://www.cnblogs.com/hongdada/p/8145075.html
5.3-Zk如何实现分布式锁,跟redis的分布式锁有哪些区别
https://blog.csdn.net/sunfeizhi/article/details/51926396
Apache的开源库Curator,它是一个ZooKeeper客户端,Curator提供的InterProcessMutex是分布式锁的实现,acquire方法用于获取锁,release方法用于释放锁。
https://www.cnblogs.com/mengchunchen/p/9647756.html
5.4-Zk跟eureka的区别
https://www.cnblogs.com/chihirotan/p/11366394.html
6-Dubbo
6.1-Dubbo的工作过程原理
1)第一步,provider向注册中心去注册
2)第二步,consumer从注册中心订阅服务,注册中心会通知consumer注册好的服务
3)第三步,consumer调用provider
4)第四步,consumer和provider都异步的通知监控中心
-
Dubbo的负载均衡,集群容错策略
Random LoadBalance:随机策略。按照概率设置权重,比较均匀,并且可以动态调节提供者的权重。
RoundRobin LoadBalance:轮询策略。轮询,按公约后的权重设置轮询比率。会存在执行比较慢的服务提供者堆积请求的情况,比如一个机器执行的非常慢,但是机器没有挂调用(如果挂了,那么当前机器会从Zookeeper的服务列表删除),当很多新的请求到达该机器后,由于之前的请求还没有处理完毕,会导致新的请求被堆积,久而久之,所有消费者调用这台机器上的请求都被阻塞。
LeastActive LoadBalance:最少活跃调用数。如果每个提供者的活跃数相同,则随机选择一个。在每个服务提供者里面维护者一个活跃数计数器,用来记录当前同时处理请求的个数,也就是并发处理任务的个数。所以如果这个值越小说明当前服务提供者处理的速度很快或者当前机器的负载比较低,所以路由选择时候就选择该活跃度最小的机器。如果一个服务提供者处理速度很慢,由于堆积,那么同时处理的请求就比较多,也就是活跃调用数目越大,这也使得慢的提供者收到更少请求,因为越慢的提供者的活跃度越来越大。
ConsistentHash LoadBalance:一致性Hash策略。一致性Hash,可以保证相同参数的请求总是发到同一提供者,当某一台提供者挂了时,原本发往该提供者的请求,基于虚拟节点,平摊到其他提供者,不会引起剧烈变动。
容错策略:
失败重试
快速失败
失败安全
失败自动恢复
并行调用
广播调用
6.2-Dubbo的配置优先级顺序,消费方>提供方,方法>类>全局
6.3-Dubbo协议
6.4-Zookeeper注册中心挂了,影响服务调用吗
不影响,本地会缓存一份服务提供者的调用地址
6.6-Dubbo为什么要用zookeeper作为注册中心
6.7-Dubbo服务治理用了哪些
https://blog.csdn.net/qq_40369435/article/details/92087995
6.8-让你实现一个RPC框架怎么做
https://itweknow.cn/blog-site/posts/3998282649.html
https://blog.csdn.net/justloveyou_/article/details/79441306
1.网络编程 socket
2.java - rmi
6.9-Dubbo的zookeeper注册中心中存储了什么内容
https://blog.csdn.net/u012988901/article/details/84394168
6.10-Dubbo的降级,mock
7-MQ(RabbitMQ)
7.1-用MQ有哪些好处,你系统中怎么用的
异步、解耦、削峰
7.2-Rabbitmq的工作过程
消息生产者连接到RabbitMQ Broker,创建connection,开启channel。
生产者声明交换机类型、名称、是否持久化等。
发送消息,并指定消息是否持久化等属性和routing key。
exchange收到消息之后,根据routing key路由到跟当前交换机绑定的相匹配的队列里面。
消费者监听接收到消息之后开始业务处理,然后发送一个ack确认告知消息已经被消费。
RabbitMQ Broker收到ack之后将对应的消息从队列里面删除掉。
7.3-Rabbitmq的exchange类型及特点
Fanout:
该类型不处理路由键,会把所有发送到交换器的消息路由到所有绑定的队列中。优点是转发消息最快,性能最好。
Direct:
该类型的交换器将所有发送到该交换器的消息被转发到RoutingKey指定的队列中,也就是说路由到BindingKey和RoutingKey完全匹配的队列中
Topic:
该类型的交换器将所有发送到Topic Exchange的消息被转发到所有RoutingKey中指定的Topic的队列上面。Exchange将RoutingKey和某Topic进行模糊匹配,其中“”用来匹配一个词,“#”用于匹配一个或者多个词。例如“com.#”能匹配到“com.rabbitmq.oa”和“com.rabbitmq”;而"login."只能匹配到“com.rabbitmq”。
headers:
该类型的交换器不依赖路由规则来路由消息,而是根据消息内容中的headers属性进行匹配。headers类型交换器性能差,在实际中并不常用。
7.4-Rabbitmq怎么进行顺序消费
RabbitMq
保证顺序消费:顺序消息扔到一个queue,一个消费者进行消费
Kafka保证顺序:
Kafka一个partition只能对应一个消费者
设定一个只有一个partition的topic
需要顺序消费的数据设定相同的topic,进入到同一个partiton中
重点就是顺序操作要放到一个队列或者线程队列中
7.6-Rabbitmq的可靠性消息投递(怎么保证消息不丢失)
https://www.jianshu.com/p/2c5eebfd0e95
https://blog.csdn.net/u012211603/article/details/85707760
7.7-Rabbitmq的消息什么时候会成为死信
1.消息被拒绝 (basic.reject / basic.nack) 并且 reQueue=false 2.消息 TTL 过期 3.队列达到最大长度了
7.8-Rabbitmq怎么实现延迟队列
1.死信队列,创建两个队列,一个队列设置超时后路由到另一个队列
2.插件
7.9-消费方挂了,但是没有进行ack会有问题吗?(没有问题,消息会重回队列,然后发给其他的消费方)
7.10-Rabbitmq你们是怎么部署的,单机还是集群
集群
7.11-Rabbitmq怎么做到消息不重复消费
1.做消息幂等,redis啊,数据库啊
7.12-其他的mq,kafka,rocketmq用过吗
- kafka
8-Spring和SpringMVC
8.1-Springmvc的工作过程
8.2-Spring的bean的生命周期
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用 Java Reflection API 创建一个Bean的实例。
- 如果涉及到一些属性值 利用
set()
方法设置一些属性值。 - 如果 Bean 实现了
BeanNameAware
接口,调用setBeanName()
方法,传入Bean的名字。 - 如果 Bean 实现了
BeanClassLoaderAware
接口,调用setBeanClassLoader()
方法,传入ClassLoader
对象的实例。 - 与上面的类似,如果实现了其他
*.Aware
接口,就调用相应的方法。 - 如果有和加载这个 Bean 的 Spring 容器相关的
BeanPostProcessor
对象,执行postProcessBeforeInitialization()
方法 - 如果Bean实现了
InitializingBean
接口,执行afterPropertiesSet()
方法。 - 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
- 如果有和加载这个 Bean的 Spring 容器相关的
BeanPostProcessor
对象,执行postProcessAfterInitialization()
方法 - 当要销毁 Bean 的时候,如果 Bean 实现了
DisposableBean
接口,执行destroy()
方法。 - 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
8.3-Beanfactory和factorybean的区别
https://www.cnblogs.com/aspirant/p/9082858.html
8.4-Spring的IOC,aop,以及是怎么实现的,jdk动态代理与cglib的区别,JDK动态代理的原理了解吗
https://www.zhihu.com/question/23277575/answer/169698662
https://www.cnblogs.com/xdp-gacl/p/4249939.html
反射
动态代理(JDK动态代理,cglib动态代理)
https://www.zhihu.com/question/23641679
https://blog.csdn.net/briblue/article/details/73928350
8.5-Spring的切面有哪些关键内容,切点,切面,织入
- 通知(Advice): AOP 框架中的增强处理。通知描述了切面何时执行以及如何执行增强处理。
- 连接点(join point): 连接点表示应用执行过程中能够插入切面的一个点,这个点可以是方法的调用、异常的抛出。在 Spring AOP 中,连接点总是方法的调用。
- 切点(PointCut): 可以插入增强处理的连接点。
- 切面(Aspect): 切面是通知和切点的结合。
- 引入(Introduction):引入允许我们向现有的类添加新的方法或者属性。
- 织入(Weaving): 将增强处理添加到目标对象中,并创建一个被增强的对象,这个过程就是织入。
8.6-你项目里面mysql的读写分离是怎么做的,AOP + 自定义注解 + 实现AbstractRoutingDataSource
8.7-Spring中的事务传播行为
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
9-Mybatis
9.1-看过mybatis的源码吗,知道它的拦截器吗
https://blog.csdn.net/weixin_39494923/article/details/91534658
分页插件
https://www.cnblogs.com/dengpengbo/p/10579631.html
9.2-Mybatis的二级缓存了解不
https://blog.csdn.net/luanlouis/article/details/41408341
https://www.cnblogs.com/cxuanBlog/p/11324034.html
https://www.cnblogs.com/cxuanBlog/p/11333021.html
[https://blog.csdn.net/Yang_Hui_Liang/article/details/88291752
](https://blog.csdn.net/Yang_Hui_Liang/article/details/88291752
10-SpringBoot
10.1-Springboot有什么好处
https://www.zhihu.com/question/39483566
https://blog.csdn.net/qq_32595453/article/details/81141643
10.2-Springboot自动装配原理
10.3-Springboot的常用注解
10.4-SpringCloud
10.5-Springcloud的常用组件,怎么用的
10.6-Eureka跟zookeeper的区别
10.7-Hystrix的使用,原理知道吗
11-网络及Http协议相关
11.1-http协议
11.2-https的加密过程原理
11.3- 其他可能被问到的,url从浏览器输入到响应的过程,TCP协议三次握手,四次挥手,TCP和UDP的区别
12-IO相关
- BIO、NIO、AIO
- 什么是阻塞,非阻塞,同步,异步
- Reactor模型知道吗
- Netty用过吗
- ByteBuffer用过吗
13-Tomcat
-
Tomcat是什么,对请求做了什么
-
让你实现一个Tomcat怎么做
14-数据结构及算法相关
- 手写二叉树的深度
- 链表的元素删除
- 怎么判断链表有没有环
- 链表反转
15-设计模式
常用的设计模式
单例,工厂,代理,策略,模板,观察者,装饰,适配器……..
-
程序中有大量的if else配置怎么解决
适配器模式
项目中有用过哪些设计模式
16-分布式相关
-
如何设计一个可以承载高并发的系统或者接口,要考虑哪些因素?
分布式事务了解哪些解决方案
https://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html
-
对微服务的理解,为什么要做微服务,微服务系统会出现什么问题,怎么解决
-
常用限流算法有哪些
做过系统监控吗
-
分布式系统中日志追踪
https://www.cnblogs.com/tong-yuan/p/12128796.html
zipkinpinpoint
-
系统怎么做接口防刷
聚安全-美杜莎
图片验证码
-
怎么实现接口的幂等
17-场景问题
- 多个商户支付路由,每个商户都会有每天支付总金额,总笔数限制,怎么进行支付路由
- 一共5000个商品,每个用户进来会看到这5000个商品中的一部分,比如10个,同一个人每次进来看到的商品不能与之前的重复,用redis怎么实现
- 大量的用户访问,比如一天好几百万的访问量Redis怎么统计日活,月活
- 查询数据进行redis缓存,每次的查询条件可能都不一样,怎么做到尽可能的缓存查询结果但是不能重复缓存……..
- 假如单笔支付限额一万,但是用户要支付两万块钱,你的支付系统怎么做