导图社区 Java面试br
关于Java面试br的思维导图,分享了数据库(MySQL)、百度面试、消息队列、工程篇、基础篇、web及framework、缓存(redis)、zookeeper、微服务篇相关内容。
编辑于2023-05-26 00:26:46 湖南Java面试<br>
数据库(MySQL)
MySQL中Btree和B+tree算法<br>
MySQL中in和exists应用场景<br>
MySQL索引使用的注意事项
SQL反模式
SQL优化
MySQL遇到的死锁问题
存储引擎的 InnoDB 与 MyISAM <br>
数据库索引的原理 <br>
为什么要用 B-tree
聚集索引与非聚集索引的区别
limit 20000 加载很慢怎么解决
ObjectId 规则
倒排索引
MongoDB/ElasticSearch使用场景 <br>
百度面试<br>
消息队列
消息队列使用场景
消息的重发补偿解决思路
消息的幂等性解决思路
消息的堆积解决思路
自己如何实现消息队列
如何保证消息的有序性
工程篇
需求分析
你如何对需求原型进行理解和拆分 <br>
说说你对功能性需求的理解 <br>
说说你对非功能性需求的理解 <br>
你针对产品提出哪些交互和改进意见 <br>
你如何理解用户痛点 <br>
设计能力
说说你在项目中使用过的 UML 图 <br>
你如何考虑组件化 <br>
你如何考虑服务化 <br>
你如何进行领域建模 <br>
你如何划分领域边界 <br>
说说你项目中的领域建模 <br>
说说概要设计 <br>
设计模式
你项目中有使用哪些设计模式 <br>
说说常用开源框架中设计模式使用分析 <br>
说说你对设计原则的理解 <br>
23种设计模式的设计理念 <br>
设计模式之间的异同,例如策略模式与状态模式的区别 <br>
设计模式之间的结合,例如策略模式+简单工厂模式的实践 <br>
设计模式的性能,例如单例模式哪种性能更好。 <br>
业务工程
你系统中的前后端分离是如何做的 <br>
说说你的开发流程 <br>
你和团队是如何沟通的 <br>
你如何进行代码评审 <br>
说说你对技术与业务的理解 <br>
说说你在项目中经常遇到的 Exception <br>
说说你在项目中遇到感觉最难Bug,怎么解决的 <br>
说说你在项目中遇到印象最深困难,怎么解决的 <br>
你觉得你们项目还有哪些不足的地方 <br>
你是否遇到过 CPU 100% ,如何排查与解决 <br>
你是否遇到过 内存 OOM ,如何排查与解决 <br>
说说你对敏捷开发的实践 <br>
说说你对开发运维的实践 <br>
介绍下工作中的一个对自己最有价值的项目,以及在这个过程中的角色 <br>
软实力
说说你的亮点 <br>
说说你最近在看什么书 <br>
说说你觉得最有意义的技术书籍 <br>
工作之余做什么事情 <br>
说说个人发展方向方面的思考 <br>
说说你认为的服务端开发工程师应该具备哪些能力 <br>
说说你认为的架构师是什么样的,架构师主要做什么 <br>
说说你所理解的技术专家 <br>
基础篇
面向对象的特征
final、finally、finalize的区别
int和Integer的区别
重载和重写的区别
抽象类和接口的区别
反射的用途及实现
jdbc流程
equals与==的区别,hashCode和equals的关系<br>
“==”两边若是基本数据类型,比较的是数值,复杂对象比较的是对象在内存中的地址,“equals”比较的是对象在内存中的地址。
ArrayList与LinkedList、Vector的区别
HashMap、Hashtable的区别
HashMap、ConcurrentHashMap的工作原理及代码实现
数据结构:树、排序算法、查找算法<br>
ThreadLocal原理及内存泄漏<br>
创建线程的方式及实现
sleep()/yield()/join()的区别
CountDownLatch/CyclicBarrier/Semaphore/Exchanger原理
线程池的实现原理及创建线程池的几种方式
线程的生命周期及安全问题
volatile/synchronized实现原理
synchronized与lock的区别
CAS乐观锁,ABA问题
乐观锁的业务场景及实现方式
JVM内存模型
类加载机制
线上频繁full gc怎么办?CPU使用率过高怎么办?
web及framework
Http get和post请求的区别,http1/http2/https的区别<br>
session和cookie的区别
mvc设计思想
tcp三次握手、四次挥手过程
Spring
Spring事务传播特性及隔离机制<br>
BeanFactory 和 ApplicationContext的区别
Spring Bean的生命周期
Spring IOC、AOP原理
动态代理cglib与jdk
Spring事务实现方法及底层原理
SpringMVC运行流程、启动流程
Spring单例的实现原理
如何自定义注解实现功能
Netty
为什么选择Netty及业务中使用Netty的场景
API使用简单,开发门槛低
功能强大,预置多种编解码功能,支持多种主流协议
定制能力强,可通过ChannelHandler对通讯框架灵活扩展
性能高
成熟、稳定,修复了已经发现的所有JDK NIO BUG
原生的 NIO 在 JDK 1.7 版本存在 epoll bug
为什么会TCP拆包黏包及解决方法
原因
应用程序写入的字节大小大于或小于套接口发送缓冲区大小
进行MSS大小的TCP分段
以太网帧的payload大于MTU进行IP分段
解决方法
由于底层TCP无法理解上层业务数据,所以底层无法保证数据包不被拆分和重组,这个问题只能通过上层应用协议栈设计来解决
消息定长,如每个报文大小固定长度为200字节,不够补空格
`FixedLengthFrameDecoder`
包尾增加回车换行符进行分割,如FTP协议
`LineBasedFrameDecoder、StringDecoder 、DelimiterBasedFrameDecoder`
将消息分为消息头和消息体,消息头包含表示消息(或消息体)总长度的字段,通常消息头的第一字段使用int32表示消息的总长度
更复杂的应用层协议
Netty线程模型
Netty的零拷贝
接收和发送ByteBuffer采用DDIRECT BUFFERS
使用堆外直接内存进行`socket`读写,不需要进行字节缓冲区的二次拷贝。如果使用传统堆内存`(HEAP BUFFERS)`进行`socket`读写,JVM会将堆内存`buffer`拷贝一份到直接内存,然后写入`socket`
实现CompositeByteBuf
对外将多个`ByteBuf`封装成一个`ByteBuf`,对外提供统一封装后的`ByteBuf`接口,`CompositeByteBuf`实际是个`ByteBuf`的装饰器,将多个`ByteBuf`组合成一个集合
文件传输
文件传输类`DefaultFileRegion`通过`transferTo`方法将文件发送到目标`Channel`中,很多操作系统将文件缓冲区的内容发送到目标`Channel`中,而不需要通过循环拷贝的方式,提升了传输性能,降低了`CPU`和内存占用
Netty内部执行流程及重连实现
缓存(redis)
redis使用场景,数据类型与内部结构
使用场景:缓存、排行榜系统、计数器应用、社交网络、消息队列系统
数据类型:string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合)
redis为什么是单线程的
纯内存访问
非阻塞I/O,使用epoll作为I/O多路复用实现,再加上自身事件处理模型将epoll中的连接、读写、关闭都转换为事件,不在网络I/O上浪费过多的时间<br>
单线程避免了线程切换和竞态产生的消耗
redis持久化机制及如何实现
RDB:把当前进程数据生成快照保存到硬盘的过程
触发机制
save命令:阻塞当前Redis服务器,直到完成为止,对内存较大的实例会造成长时间阻塞,线上不建议使用
bgsave命令:Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束
(bgsave)流程说明
1.执行bgsave命令,Redis父进程判断当前是否存在正在执行的子进程,如果存在,bgsave命令直接返回<br>
2.父进程执行fork操作创建子进程,fork操作过程中父进程会阻塞<br>
3.父进程fork完后,bgsave命令返回信息并不在阻塞父进程,可以继续响应其它命令
4.子进程创建RDB文件,根据父进程内存生成临时快照文件,完成后对原有文件进行原子替换
5.子进程发送信号给父进程表示完成,父进程更新统计信息
优缺点
1.RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间节点上的数据快照,适用于备份、全量复制等场景
2.Redis加载RDB恢复数据快于AOP方式
1.RDB方式数据没办法做到实时持久化/秒级持久化
bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,频繁执行成本高
2.RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,导致无法兼容
AOF:以独立日志方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的
redis集群方案及实现
Redis Cluster(3.0版本后官方提出)
穿透优化
- 是指查询一个根本不存在的数据,缓存层和存储层都不命中 - 缓存穿透将导致不存在的数据每次请求都要到存储层查询,失去了缓存保护后端存储的意义 - 造成缓存穿透的基本愿意有两个:自身业务或数据问题;恶意攻击、爬虫等造成大量空命中
缓存空对象
- 存储层不命中后,仍将空对象保留到缓存层中 - 存在两个问题:空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间,比较有效的方法是针对这类数据设置较短的过期时间,让其自动剔除;缓存层和存储层数据会有一段时间的不一致,可通过消息系统清除掉缓存层中的空对象
布隆过滤器拦截
在访问缓存层和存储层前,将存在的key用布隆过滤器提前保存起来,如果布隆过滤器查询不存在,那么就不会继续访问
缓存崩溃
缓存层由于某些原因不能提供服务,于是所有请求都会到达存储层,存储层调用量暴增
1. 保证缓存层高可用
`Redis Sentinel`和`Redis Cluster`都实现了高可用
2. 依赖隔离组件为后端限流并降级
对重要资源(如Redis、MySQL、HBase、外部接口)进行隔离,让某种资源单独运行在自己的线程池中
3. 提前演练
项目上线前,模拟缓存层宕机后,应用及后端负载情况及可能出现的问题
缓存降级
键过期策略
Redis采用的是惰性删除和定期删除
定时删除:设置键的过期时间的同时,创建一个定时器
定期删除:每隔一段时间对Redis进行一次检查
惰性删除:每次获取键时,检查取得的键是否过期
内存淘汰机制
- 是指键被Redis主动地从实例中删除,从而产生读miss的情况 - 通过配置redis.conf中的maxmemory来开启内存淘汰功能,为0表示对内存未限制
noeviction(默认):当内存使用达到阈值时,所有引起申请内存的命令会报错
allkeys-lru:主键空间中,优先移除最近未使用的
allkeys-random:主键空间中,随机移除
volatile-lru:设置了过期时间的键空间中,优先移除最近未使用的
volatile-random:设置了过期时间的键空间中,随机移除
volatile-ttl:设置了过期时间的键空间中,优先移除过期时间更早的
zookeeper
选主过程
1.每个Server发出一个投票
由于是初始情况,每个服务器会将自己作为`Leader`服务器来进行投票,每次投票最基本的元素包括:所推举的服务器的`myid`和`ZXID`
2.每个服务器接收来自各方的投票,检查是否是本轮投票、是否来自LOOKING状态的服务器
3.处理投票
接收到其它服务器的投票后,针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK,PK规则如下: - 优先检查`ZXID`:`ZXID`较大的服务器优先作为`Leader` - 如果`ZXID`相同,那么比较`myid`,`myid`较大的作为`Leader`
4.统计投票
每次投票后,服务器都会统计所有投票,判断是否已经有过半的机器接收到相同的投票
5.改变服务器状态
一旦确定了`Leader`,每个服务器会更新自己的状态:如果是`Follower`,那么就变更为`FOLLOWERING`,如果是`Leader`,就变更为`LEADERING`
集群间如何进行通讯
zk集群工作过程中,都是由`Leader`服务器负责进行各服务器间的协调,同时,各服务器间的网络通讯,都是通过不同类型的消息传递来实现的
数据同步型
是指在`Learner`和`Leader`服务器进行数据同步的时候,网络通讯所用到的消息,通常有`DIFF`、`TRUNC`、`SNAP`和`UPDODATE`
服务器初始化型
是指在整个集群或新机器初始化时,`Leader`和`Learner`间相互通讯所使用的消息类型,常见的有`OBSERVERINFO`、`FOLLOWERINFO`、`LEADERINFO`、`ACKEPOCH`、`NEWLEADER`
请求处理型
是指在请求处理过程中,`Leader`和`Learner`间互相通讯所使用的消息,常见的有`REQUEST`、`PROPOSAL`、`ACK`、`COMMIT`、`INFORM`和`SYNC`
会话管理型
是指zk在进行会话管理的过程中,和`Leader`服务器间互相通讯所使用的消息,常见的有`PING`和`REVALIDATE`
节点加密方式
分布式锁的实现过程
排它锁
- 简称X锁(Exclusive Locks),又称写锁/独占锁,核心是如何保证当前有且仅有一个事务获得锁,并且释放锁后,所有正在等待获取所的事务都能被通知。 - 需要获取排它锁时,客户端通过调用`create()`接口,在`/exclusive_lock`节点下创建临时节点`/exclusive_lock/lock`,zk会保证所有客户端中只有一个客户端创建成功,所有**没有**获取到锁的客户端需要到`/exclusive_lock`节点上注册一个子节点变更的`Watcher`监听,实时监听`lock`节点的变更情况 - 释放锁: - 当获取锁的客户端机器宕机,zk上的这个临时节点会被移除; - 正常执行业务逻辑完成后,客户端主动删除自己创建的临时节点
共享锁
简称S锁(Shared Locks),又称读锁,如果事务T1对数据对象O1加上了共享锁,那么当前事务只能对O1进行读取操作,其它事务也只能对O1加共享锁,直到O1所有共享锁都被释放
羊群效应
锁改进
微服务篇
微服务
前后端分离是如何做的 <br>
如何理解RPC框架及其实现原理
Dubbo的实现原理
怎么理解RESTful
如何设计一个良好的API
如何理解RESTful的幂等性
如何保证接口的幂等性
CAP定理、BASE理论
怎么考虑数据一致性问题
说说最终一致性的解决方案
怎么看待微服务、微服务与SOA的区别
如何拆分服务
微服务如何进行数据库管理
如何应对微服务链式调用异常
对于快速追踪与定位问题
微服务的安全
分布式
谈谈业务中使用分布式的场景
Session分布式解决方案
分布式锁的场景及实现
分布式事务
集群与负载均衡的算法与实现
分布式主键、数据存储方案
分库分表设计及带来的分布式困境与应对
安全问题
安全要素与 STRIDE 威胁 <br>
防范常见的 Web 攻击 <br>
服务端通信安全攻防 <br>
Https原理剖析、降级攻击
授权与认证 <br>
基于角色的访问控制
基于数据的访问控制
性能优化
性能指标有哪些
如何发现性能瓶颈
性能调优的常见手段
项目中如何进行调优的