面试
2021-11-03 18:13:03 0 举报
AI智能生成
Java面试题总结,持续更新
作者其他创作
大纲/内容
mq
Rabbitmq
高可用
单机
demo级别
普通集群
不是分布式
有消息拉取开销
存放queue的实例宕机了,需要开启消息持久化,等这台机器重启才能获取消息
镜像集群
优点
高可用
每台机器都存放queue
缺点
每台机器同步完整消息,对网络带宽压力和消耗很重
不是分布式,没有扩展性
kafaka
天然分布式
redis
redis和memcached区别
redis 支持复杂的数据结构
redis 原生支持集群模式
为啥 redis 单线程模型也能效率这么高?
纯内存操作
核心是基于非阻塞的 IO (epoll)多路复用机制
C 语言实现,一般来说,C 语言实现的程序“距离”操作系统更近,执行速度相对会更快
单线程反而避免了多线程的频繁上下文切换问题,预防了多线程可能产生的竞争问题
redis数据类型
string
hash
list
sorted set
过期策略
定期删除
惰性删除
定期删除漏掉了大量过期key
内存淘汰机制
手写LRU算法
高可用
主从架构
哨兵集群
缺点
单机key过多导致数据RDB备份时间过长影响redis性能
分片集群
解决单主Redis压力,数据分散在多个Shard上
主从复制原理
持久化方式
RDB
优点
冷备
保持高性能
恢复更快
缺点
数据丢失
fork快照数据文件过大可能导致客户端暂停数秒
AOF
优点
数据不丢失
误删紧急恢复
缺点
同一数据AOF占用空间更大
写QPS降低
如何选择AOF还是RDB
两种都选取
缓存问题
缓存雪崩
原因
缓存服务器挂了,大量请求到数据库导致数据库挂
解决
事前
redis 高可用,主从+哨兵,redis cluster,避免全盘崩溃
事中
本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死
事后
redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据
缓存穿透
原因
黑客攻击故意请求不存在缓存中的数据,让所有请求到数据库
解决
查询不到的数据缓存空值
缓存击穿
热点key突然失效,大量请求直接到数据库
解决
缓存数据基本不会更新
将热点数据设置为永不过期
缓存数据更新不频繁且缓存刷新流程耗时较少
缓存数据频繁更新或者缓存刷新流程耗时较长
定时线程延迟缓存过期时间或刷新缓存
缓存与数据库双写一致性
解决
读请求和写请求串行化
读
先读缓存,缓存没有,就读数据库,然后取出数据放入缓存
更新
先更新数据库,后删除缓存
分布式锁
单机分布式锁
原理
Setnx
缺点
锁超时时间过长过短都有影响
基于看门狗策略来延长锁
集群分布式锁
Redission
mysql
索引
索引分类
主键索引
唯一索引
普通索引
组合索引
全文索引
索引分类
聚簇索引
非主键索引
实现原理
innordb
B+数
hash
适合等值查询
不适合范围查询
如何建索引
索引优化
定位慢查询
explain
table
哪个表
type
all
全表扫描
const
读常量,最多一条记录匹配
eq_ref
走主键
index
扫描全部索引
range
扫描部分索引
possible_keys
显示可能使用的索引
key
实际使用的索引
key_len
使用索引的长度
ref
联合索引的哪一列被用了
rows
一共扫描和返回了多少行
extra
using filesort
需要额外进行排序
using temporary
构建了临时表
using where
对索引扫出来的数据再次根据where来过滤
MVCC
解决问题
解决MySql脏读,幻读问题
实现原理
分库分表
Sharding-jdbc
分库分表策略
根据业务自定义
优点
无需部署额外服务,对业务零侵入
已升级为Apache顶级项目
MyCat
缺点
需要保证Mycat服务的高可用
搜索引擎
Elasticsearch
深度分页问题
多节点加载大量数据内存聚合导致CPU飙升
解决方式
子主题
子主题
网络
TCP/IP
四层协议
物理层
类似光纤、海底光缆
数据链路层
以太网协议
必须有网卡,网卡包括mac地址
广播一个子网
网络层
ip协议
三次握手
第一次握手
Client
Server
确认Client发送正常
第二次握手
Client
Client 发送、接收正常,Server发送正常
Server
Server发送,接收正常,Client发送正常
第三次握手
Client
CLient、server发送接收正常
Server
CLient、server发送接收正常
四次挥手
输入www.baidu.com
1. DNS解析
2. TCP连接
3. 发送HTTP请求
4. 服务器处理请求并返回HTTP报文
5.. 浏览器解析渲染页面
6. 连接结束
常用状态码
1XX
接收请求正在处理
2XX
请求正常处理完毕
3XX
需要进行附加操作完成请求
4XX
服务器无法处理请求,客户端出错
5XX
服务器处理请求出错,服务器出错
数据结构
数组
链表
树
二叉树
排序二叉树
红黑树
特点
每个节点要么是红色,要么是黑色
根节点永远是黑色的
所有的叶子节点都是空节点(即null),并且是黑色的
每个红色节点的两个子节点都是黑色
从任一节点到其子树中每个叶子节点的路径都包含相同数量的黑色节点
算法
设计模式
常用设计模式
单例模式
模板模式
策略模式
建造模式
原型模式
责任链模式
原型模式
基础
==和equals
子主题
throw和throws
throw使用在方法内部
throws使用在方法上面
集合
List
ArrayList
线程不安全
数组
查询效率高
插入、删除效率低
初始容量
0
添加第一个元素变为10
扩容
1.5倍
LinkedList
线程不安全
双向循环链表
插入、删除效率高
查询效率低
去重
Set
对象
重写hashcode,equals
java8:Steam
Map
HashMap
数据结构
1.7以前
数组+链表
1.8
数组+链表+红黑树
线程不安全
扩容
翻倍
负载因子
0.75
数组大小
默认大小
16
自定义
必须是2的N次幂
减少hash冲突
链表转红黑树
8
如何保证数组不越界
n-1 & hash
ConcurrentHashMap
线程安全
锁实现
1.7
多个数组,一个数组一个锁
1.8
一个数组,每个元素pull进行CAS
CAS失败使用synchronized对数组元素加锁,数组+红黑树插入
Set
多线程
线程状态
NEW
新建
调用start()进入可运行状态,获取cpu才会到RUNNABLE状态
RUNNABLE
运行
BLOCKED
阻塞
WAITING
永久等待
TIMED_WAITING
临时等待
TERMINATED
结束
实现方式
1.继承Thread,重写Run函数
2. 实现Runnable接口,实现run方法
实现Callable接口,实现call方法
线程池
核心运行原理
1. 当前池中线程比核心数少,新建一个线程执行任务
创建后不会被销毁
2.核心池已满,但任务队列未满,添加到队列中
3. 核心池已满,队列已满,试着创建一个新线程
非核心线程存活时间由keepAliveTime决定
4. 新建线程数超过maximumPoolSize
任务被拒接
调用阻塞策略
执行任务
execute()
没返回值
submit()
返回一个Future
核心构造函数
ThreadPollExecutor
参数
corePoolSize
核心线程池的大小
maximumPoolSize
线程池最大数量
keepAliveTime
非核心线程能够空闲的最长时间
TimeUnit
时间单位和keepAliveTime一起使用
BlockingQueue<Runnable>
缓存队列,用来存放等待被执行的任务
ThreadFactory
用于设置创建线程的工厂
RejectedExecutionHandler
饱和策略,线程数量大于最大线程数就会采用饱和策略
java提供的几种线程池
newCachedThreadPool
corePollSize
0
maximumPoolSize
无界
keepAliveTime
60
newFixedThreadPool
corePollSize=maximumPoolSize
keepAliveTime
0
newScheduledThreadPool
maximumPoolSize
无界
可延时执行
newSingleThreadExecutor
corePollSize
1
maximumPoolSize
1
如果线上机器突然宕机,线程池的阻塞队列中的请求怎么办
将提交的任务写入数据库,完成后更新状态
后台起一个线程扫描重新提交
使用无界队列阻塞队列问题
调用超时,cpu飙升,oom
锁
死锁
避免死锁条件
破坏互斥
破坏请求与保持
破坏不剥夺
破坏循环等待
synchronized
实现原理
对象关联一个monitor
加锁一次monitor+1
可重入锁
ReentrantLock
公平锁
按队列执行
非公平锁
不按队列
实现原理
AQS
队列
CAS
state
0
未加锁
1
加锁
volatile
ThreadLoacl
内存泄漏
原子类
所属包
java.util.concurrent.atomic
基本类型
AtomicInteger
整形原子类
常用方法
public final int get() //获取当前的值
public final int getAndSet(int newValue)//获取当前的值,并设置新的值
public final int getAndIncrement()//获取当前的值,并自增
public final int getAndDecrement() //获取当前的值,并自减
public final int getAndAdd(int delta) //获取当前的值,并加上预期的值
boolean compareAndSet(int expect, int update) //如果输入的数值等于预期值,则以原子方式将该值设置为输入值(update)
public final void lazySet(int newValue)//最终设置为newValue,使用 lazySet 设置之后可能导致其他线程在之后的一小段时间内还是可以读到旧的值。
AtomicLong
长整型原子类
AtomicBoolean
布尔型原子类
数组类型
AtomicReference
引用类型原子类
实现原理
CAS
乐观锁
AQS
实现原理
CAS +链表
API
休眠
sleep()
不释放锁
自动苏醒
wait()
释放锁
需要调用notify()或notifyAll()
nginx
负载均衡算法
轮询
默认方式
weight
权重方式
ip_hash
依据ip分配方式 (ip绑定)
least_conn
最少连接方式
fair(第三方)
响应时间方式
url_hash(第三方)
依据URL分配方式
负载均衡
软负载
硬负载
Spring
bean
类别
Singleton
线程不安全
prototype
request
session
globalSession
Bean生命周期
Spring循环依赖
核心为三级缓存
SpringMVC
核心原理
JVM
内存模型
原子性
可见性
有序性
volatile
保证可见性
微服务
SpringCloud
注册中心
ZooKeeper
Eureka
Nacos
Apollp
RPC调用
Rest
Fegin
接口+注解
核心实现原理
动态代理
熔断限流
Hysteria
保护策略
多服务线程隔离访问
Dubbo
优点
透明化的远程方法调用
软负载均衡及容错机制
服务注册中心自动注册 & 配置管理
服务接口监控与治理
缺点
只支持java
解决问题
服务治理
注册中心
注册中心
Multicast
ZooKeeper
Redis
Simple
实现原理
消费者Consumer
远程RPC调用
注册中心Registry
ZooKeeper
节点变化都会通知消费者
生产者Provider
持久节点存放服务基本信息
临时节点存放服务地址信息
服务地址可能改变
监控中心Monitor
底层基于netty
可视化监控平台
DubboAdmin
ZooKeeper
应用场景
节点类型
临时节点
连接关闭节点删除
持久节点
节点持久化到硬盘
事件通知
节点改变都可以通知
Dubbo服务发现
创建父节点members
子节点:192.168.1.1 8080
临时节点
子节点:192.168.1.2 8080
临时节点
持久节点
服务新增
事件通知加入最新服务地址
服务宕机
事件监听读取最新节点
本地负载均衡算法
请求数量%服务
分布式session解决
NGINX ip绑定
Session缓存在Redis中
token替换session
网关
Zull
GatWay
分布式事务
一致性
强一致性
在任意时刻,所有节点中的数据是一样的
弱一致性
最终一致性
CAP原则
Base理论
解决方式
Seata
MQ
Netty
四种IO模型
同步阻塞
同步非阻塞
IO多路复用
异步IO
粘包问题
产生原因
操作系统底层缓冲的数据有容量限制
数据包较大会拆分成多个ByteBuf进行发送
造成半包
TCP底层缓冲的数据较小,一次复制多个内核缓冲包
粘包
解决方式
拆包
编解码
解码器
默认解码器
DelimiterBasedFrameDecode
自定义对分隔符解码
LineBasedFrameDecoder
按行处理粘包拆包
FixedLengthFrameDecoder
固定长度解码器
自定义解码器
编码器(Ebcider)
MessageToByteEncoder
MessageToMessageEncoder
编解码算法
Java序列化
缺点
无法跨语言
序列化后的码流过大
性能低
Google-Protobuf
优点
高效
语言无关、平台无关、扩展性好
缺点
可读性差
Faceboo-Thrift
JBoss-Marshalling
MessagePack
优点
高效
夸语言
开发流程
1. 创建ServerBootstrap实例
2. 设置并绑定Reactor线程池(EventLoopGroup)
3. 设置并绑定服务端Channel
4. TPC链路建立是创建CHannelPipeline
5. 添加并设置ChannelHandler
6. 绑定监听端口并启动服务端
7. Selector轮训
8. 网络事件通知
9. 执行Netty系统和业务HandlerChannel
0 条评论
下一页