面试题
2024-04-11 09:37:47 0 举报
AI智能生成
登录查看完整内容
面试宝典
作者其他创作
大纲/内容
2.NEW是初始化状态,实例化线程时候产生的状态new Thread
3.READY是就绪状态,线程调用start方法时候等待CPU调用产生
4.RUNNING是运行状态,CPU调度运行状态
4.WAITING是等待状态,TIME_WAITING是超时等待,等待某个线程的特定操作才会被唤醒
5.BLOCKED是阻塞状态,只有 Synchronized 同步锁等待才会存在这个状态
6.TERMINATED是终止状态
线程有几种状态?
1.实例化线程NEW状态->等待CPU调用READY状态->Synchronized抢锁 失败BLOCKED状态->抢锁成功RUNNING状态->主动/被动执行结束TERMINATED状态
各种状态之间如何切换?
Thread.stop 强制终止线程,会使执行中断,不推荐
Thread.currentThread.isInterupted(),推荐使用,发送信号终止执行
如何终止一个线程
线程状态
1.synchronized是java 关键字实现对 对象/方法上加锁
2.底层是由JMM自己实现的
3.底层是对Object对象头上 存储字段锁标记位进行修改来实现,由MonitorEnter 加锁/MonitorExit 释放锁实现
实现原理是什么?
synchronized
1.Lock 底层是由AQS实现,抢锁是通过CAS修改共享变量state实现
如何抢锁?
2.未抢占到锁线程,通过park()方法挂起线程,挂起的线程会存储到AQS的双向链表队列等待被唤醒
抢锁失败如何处理?
3.RUNING线程执行结束 会调用unlock方法 unlock会通过unpark()方法会将链表中线程唤醒
如何唤醒等待线程?
非公平锁会在CAS失败后 再执行一次tryAcquire抢锁操作
公平锁与非公平锁区别?
写写互斥/读写互斥/读读不互斥 能够实现并发读
ReadWriteLock作用
阻塞当前线程 保存到Condition队列
释放AQS锁
await
将condition队列 第一个线程移动到AQS队列
唤醒condition队列中的线程
signal
condition有什么作用?
AQS中维护着一个Condition单向链表
await方法阻塞当前线程,存储到Condition队列,并唤醒处于阻塞状态下AQS线程
将condition队列移动到AQS队列,并且唤醒线程
简叙下condition的实现原理?
Condition
Lock
锁
AQS中内部维护了一个volatile int state=0 状态为和一个FIFO的队列state 抢占锁 通过CAS操作改成 1,后续线程抢锁失败会保存到FIFO的队列,通过locksupport.pack()挂起当前线程线程执行结束 通过CAS操作修改state=0 同时 通过locksupport.unpack()唤醒FIFO队列里面的线程继续操作。
简叙下AQS流程
AQS
ThreadLocal实现原理是什么
内存泄漏,因为弱引用关系,要通过调用ThreadLocal.remove 删除弱引用
ThreadLocal存在什么问题?如何解决?
寻址法解决哈希冲突问题,即哈希到位置 不为空 则寻找下一个位置插入
ThreadLocal如何解决哈希冲突的
ThreadLocal
保证可见性
保证有序性
volatile有什么作用
volatile
关键字
多任务并行处理 主任务等待处理结果
Countdownlatch使用场景是什么
AQS 初始化 state=N 通过countDown 减1,直到state=0 退出循环 唤醒AQS队列主线程
CountDownLatch如何实现的
Countdownlatch
限流:定义同时只能有N个线程同时访问,类似限流,其他线程等待线程执行完成
Semaphore使用场景是什么
2.acquire 获得令牌 state-1 失败加入AQS队列
3.release 释放令牌 state+1 唤醒AQS队列中线程
Semaphore如何实现的
Semaphore
生产者 消费者模型 可循环使用的屏障
CyclicBarrier使用场景是什么
condition.await
到达指定N个线程 condition.signalAll
reset 重新初始化
state=n
初始化
CyclicBarrier如何实现的
1.CyclicBarrier基于Lock+condition实现的,CountDownLatch继承AQS实现的
2.CyclicBarrier可以重复使用;而CountDownLatch是一次性的,不可重复使用
3.CyclicBarrier中操作计数和阻塞的是同一个线程,调用方法只有一个await方法;而CountDownLatch中操作计数和阻塞等待是N个线程,控制计数调用方法countDown
CyclicBarrier与CountDownLatch有什么区别
CyclicBarrier
功能:异步执行、链式操作、任务编排 默认线程池ForkJoinPool.commonPool()
CompletableFuture有何作用,与Future区别是什么
CompletableFuture
addWait:保存当前线程到waitNode 单项链表
park:挂起当前线程
未完成<=COMPLETING
report
已完成
get
调用callable.call方法执行线程获取返回结果
result=Callable.call()
CAS操作 将返回结果赋值共享变量
finishCompletion:遍历waiters链表 unpark 唤醒线程
outcome=set(result)
run
Future如何实现的
Future
创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
newFixedThreadPool
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务
newSingleThreadExecutor
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newCachedThreadPool
创建一个定长线程池,支持定时及周期性任务执行
newScheduledThreadPool
线程池有几种
corePoolSize(核心线程数)
maximumPoolSize(最大线程数)
workQueue(任务队列)
keepAliveTime(线程存活时间)
threadFactory(线程工厂)
rejectedExecutionHandler(拒绝策略)
线程池各个参数代表含义
阻塞队列有哪几种
runWork执行线程
addWork(**,true)创建线程
corePoolSize未满
执行rejectedExecutionHandler拒绝策略
线程池已满
addWork(**,false)创建线程
线程池未满
workQueue队列已满
任务work存储队列
workQueue队列未满
corePoolSize已满
execute提交执行任务
线程池设计原理是什么
ThreadPoolExecutor
任务拆分窃取
ForkJoin使用场景
无返回结果的ForkJoinTask
RecursiveAction
有返回结果的ForkJoinTask
RecursiveTask
ForkJoin可以初始化几种Task任务
向当前任务所运行的线程池中提交任务
fork
获取任务的执行结果。阻塞当前线程直到对应的子任务完成
join
ForkJoin中fork/join的作用
ForkJoin
阻塞队列BlockingQueue
线程组件
多线程之间 互相竞争对象资源,互相等待对方资源的释放造成一直死循环等待的现象
什么是死锁
可重入锁,是指获得当前锁的线程,再次获得当前锁资源时候不需要获得锁
什么是可重入锁/不可重入锁
2. 锁顺序一致性 例如 线程A,B均是锁Obj1 然后锁Obj2
1.增大锁范围 全局锁
死锁怎么解决
死锁
内存比较修改法,如果内存地址V的值=A,则修改成B,否则失败
什么是CAS
1.ABA问题,将A改成B再改成A 此时 无法判断内存里面值是否被修改
3.只能修改一个变量值
CAS缺陷
CAS
子主题
多线程
2.innoDb是Mysql默认存储引擎,支持事务ACID,行锁,MVVC综合性能较好,索引跟数据存储在一个文件里面
3.MyIsam 不支持事务,表锁,读写性能高,更新删除性能差,适合做报表展示类 ,索引跟数据单独存储
4.Memory 数据存放内存,读写性能最高,数据不安全,重启崩溃都会丢失数据,适合做临时表,支持哈希索引
5.CSV 数据存放CSV文件 不支持索引 适合数据导入类场景
mysql 存储引擎有哪些?有什么特点
innoDb: 支持事务 行锁 MVVC 综合性能高 索引跟数据存储在同一个文件 适合做业务表
MyIsam: 不支持事务 表锁 读写性能高 更新删除效率低 索引跟数据单独存储 适合做报表查询
innoDb与MyIsam的区别
innoDb采用B+tree做索引
BTree和B+Tree 对比与AVL树,他解决了AVL 每个Page存储数据量太少,IO次数过多的问题
B+Tree对比于BTree 因为B+Tree的特性是叶子节点存储数据,非叶子节点存储索引。所以B+Tree 建立索引空间占用更小
B+Tree 因为叶子节点数据是排序且连续的,所以对于排序查询效率比较好,而BTree 由于非叶子节点也存储数据,所以直接查询效率会比B+Tree高
innoDb采取什么结构作为索引?他的优势劣势?
哈希索引查询效率高 因为是KV结构
哈希索引不支持条件,范围查询
只有Memory引擎建立的表才支持hash索引
innoDb的哈希索引有什么优势?使用场景是什么
如何优化索引
innoDb通过双写BufferPool与log_buffer保证数据的可靠性
log_buffer默认通过定时任务1s 写入本地磁盘,因为是顺序IO 所以效率高
理论上还是会丢失数据 可以设置刷盘策略innodb_flush_log_at_trx_commit 提交刷盘保证可靠性
innoDb如何保证数据的可靠性
1.innoDb通过undo_log保证原子性,undo_log记录更新之前的数据
2.undo_log 提交事务之前写入
innoDb如何保证原子性,undolog什么时候写入的
1.读写内存提高innoDb的读写效率
2.通过异步刷脏来保证数据的可靠性
innoDb中buff_pool作用是什么
1.innoDb 采用LRU 最近至少使用算法淘汰内存
2.innoDb对LRU算法做了改进,防止访问大量冷门数据造成热数据缓存失效
3.innoDb改进后的LRU算法 将BuffPool中数据按照5:3比例分成young区 old区
4.访问不存在的数据会放到Old区,按照策略选择移动到Young区或者保留在Old区
5.Old区在链表尾部,被淘汰优先级别较高
innoDb内存如何淘汰
1.先从Buffer_pool里面加载数据
2.buff_pool 查找到记录 直接返回
3.buff_pool 未查找到记录,从磁盘中加载 数据到buff_pool 然后返回数据
简叙一条select语句执行过程
1.加载数据,执行select 操作
2.更新server执行器数据
3.记录undo_log 更新前数据
4.记录redo_log更新后数据
5.更新buffer_pool数据
6.server执行器记录bin_log
7.提交事务,异步刷脏
简叙一条update语句执行过程
1.innoDb事务隔离级别有4中 1.RU 未提交读 2.RC 已提交读 3.RR 可重复读 4.SZ串行化
2.RU 级别未解决任何问题 存在脏读,幻读 ,不可重复读 问题
3. RC 已提交读 解决了脏读 ,未解决不可重复读问题
4.RR 解决不可重复读问题 innoDb通过行锁解决了幻读问题
5.SZ串行化解决了所有问题
innoDb事务隔离级别有哪些
1.RR解决了不可重复问题 RC未解决不可重复读问题
2.RR是加行锁 RC未加行锁 所以RC效率更高
3.RR 通过记录第一次查询的ReadView保证不可重复读问题,而RC每次查询都是一个新的ReadView
事务隔离级别RR与RC区别是什么
1.innoDb mvvc实现原理是undo_log多版本快照读实现的
2.每次增删改 都会产生新的的View 每个View上保存了行ID,事务ID,回滚指针
innoDb MVVC实现原理是什么
1.innoDb RR模式下行锁算法有3中 分别是记录锁 间隙锁 临间锁
2.记录锁--触发条件 主键查询并且命中记录
3.间隙锁--触发条件 主键查询并且未命中记录
4. 临间锁--触发条件 范围查询 ( ] 左开右闭
innoDb 行锁算法有哪些?
1.定位慢sql 可以修改配置文件(/etc/my.cnf),mysql开启慢sql监控
2.慢sql 可通过执行计划排除未走索引字段
多个事务之前相互争抢资源,锁定资源相互等待造成死锁
解决死锁从以下几个方面考虑
1.顺序访问,排序,锁定资源顺序一致
2.申请全局锁,扩大锁范围
3.事务拆分,避免大事务
4.避免条件范围过大
死锁问题原因?如何解决死锁问题
mysql
1.初始化Environment
2.加载解析XML,生成BeanDefintions
3.缓存BeanDefintions
4.初始化BeanFactory
简叙下Spring IOC初始化流程
BeanFactory 是IOC容器接口,FactoryBean是创建Bean接口
BeanFactory与FactoryBean区别是什么
IOC
1.doGetBean开始
2.缓存是否存在Bean 缓存中获取Bean
3.不存在 创建Bean 加入缓存factoryBeanObjectCach
简叙下Spring DI流程
一级缓存完整的Bean对象
二级缓存未创建完成的Bean
三级缓存beanFactory.getObject()
三级缓存
Spring 如何解决循环依赖问题
DI
如果类实现了接口默认采用JDK动态代理实现
如果类未实现接口则采用CGLIB实现AOP
Spring 中采取何种方式实现AOP
CGLIB 实现方式是通过编写字节码继承实现
JDK是通过反射调用接口实现
CGLib与JDK动态代理区别是什么
CGLIB代理是需要JVM动态加载类信息的,如果滥用容易造成OOM
Spring为什么默认采用JDK
AOP
1.初始化HandlerMapping
2.初始化HandlerAdapter
3.初始化ViewReslovers
1.初始化DispatchServlet
1.http请求->拦截->dispatchServlet
2.HandlerMapping->匹配->Controller与拦截器(HandlerExecutionChain)
3.HandlerAdapter->执行->Controller方法->生成->ModelAndView
4.ViewResolver->解析->ModelAndView->生成->View->HttpResponse
2.运行阶段
简叙下Spring Mvc流程
MVC
SpringFactoriesLoader.loadFactoryNames
AutoConfigurationImportSelector
@Import
@EnableAutoConfiguration
@SpringBootConfiguration
简叙下Spring boot自动装配原理
Spring boot中如何实现配置加载的
Spring Boot
spring
在代码上添加@LoadBalanced注解 可以实现负载均衡远程调用
Ribbon作用是什么?
1.自定义类继承AbstractLoadBalancerRule 重写choose方法
2.配置文件指定负载均衡策略NFLoadBalancerRuleClassName
如何自定义负载均衡策略?
1.Spring Cloud 里面定义@LoadBalanced注解 本质上是个@Qualifier注解
2.Spring Cloud里面LoadBalancerAutoConfiguration自定装配类会扫描加载所有加了@LoadBalanced注解的RestTemplate
3.给这些RestTemplate添加了一个拦截器LoadBalancerInterceptor,这个拦截器使用LoadBalancerClient 执行http请求
4.RibbonAutoConfiguration 会初始化LoadBalancerClient实现类RibbonLoadBalancerClient
5.RibbonLoadBalancerClient 定义了负载均衡算法
Ribbon 的负载均衡是如何实现的?
Ribbon
在一定时间内超过一定比例的客户端心跳请求失败 Eureka进入自我保护机制
自我保护机制下 Eureka 不会剔除过期服务,可以接收新增和查询请求 但是不会同步到其他节点
什么是Eureka的自我保护机制
AP模式
Eureka的自我保护机制是AP还是CP模型
Eureka
OpenFeign 声明式伪RPC的Rest接口,可以向调用RPC一样调用Rest接口
OpenFeign有什么作用
1.OpenFeign通过@FeignClient 定义一个Feign接口对象
2.Spring Cloud 初始化@EnableFeignClients 通过实现ImportBeanDefinitionRegistrar导入Bean到IOC容器
3.ImportBeanDefinitionRegistrar 会扫描@FeignClient 类 通过FactoryBean动态生成一个AOP代理对象加载到IOC容器
4.这个代理对象 实现了远程调用功能
OpenFeign实现原理?
OpenFeign
Hystrix 可以实现服务 熔断、降级策略 有效防止系统崩盘
Hystrix有什么作用
Hystrix 熔断的隔离有2中 1.信号量隔离 2.线程池隔离
1.信号量是记录多少时间内有多少个请求,计数器实现
2.线程池是记录并发线程处理多少请求 默认是采用线程池隔离
3.信号量隔离 同步单线程调用 支持熔断 不支持超时 会一直阻塞
4.线程池隔离 多线程支持异步调用 支持熔断 支持超时解除阻塞 多线程会造成CPU负载高
Hystrix 熔断的隔离机制有几种?优缺点?
Hystrix 熔断算法 是基于滑动窗口算法实现的
Hystrix 熔断算法是什么
Hystrix 同注解@HystrixCommand定义服务降级,可以实现某个方法服务降级,可以自定义全局服务降级逻辑
Hystrix如何实现服务降级?有几种方式?
Hystrix
Gateway 可以拦截过滤请求,可以实现鉴权,限流,日志,缓存等功能
Gateway有什么作用,使用场景是什么
GateWay三大核心概念 有 路由 断言 过滤器
路由定义转发的路径 路由包含了断言 过滤器
断言 相当于条件判断逻辑 匹配上则执行路由逻辑
过滤器 分为两种 1全局过滤器 2网关过滤器 可以修改或者增强http请求
GateWay三大核心概念是什么?分别作用
Gateway
Nacos 可以做动态配置中心与注册中心
Nacos有什么作用?
NacosConfigService 初始化会启动一个线程 检查本地缓存MD5与服务MD5是否一致
不一致请求最新配置,保存到cachData
cachData发布一个Event ,这个Event 会刷新Environment 将最新配置加载到Environment中实现类自动刷新
Nacos如何实现配置自动刷新
Nacos
与hystrix一致
Sentinel有什么作用
集成Nacos
Sentinel如何实现动态规则
Sentinel
seata提供了微服务框架下 分布式事务解决方案
Seata有什么作用
seata 提供了4种事务模式 1.XA事务 2.AT事务 默认 3.TCC事务 4.SEAGA
1.XA事务 强一致性 需要数据库支持XA协议 性能不稳定
2.AT 事务 弱一致性 有脏读问题,性能较好,基于BIN_LOG补偿性事务
思路:执行方法check事务日志表status,校验Confirm/Cancel是否已执行
重复调用Confirm/Cancel方法
幂等问题
悬挂问题
try未执行/执行异常 调用了Cancel方法
空回滚
3.TCC 事务 弱一致性 需要写 try confirm cancel 三个接口,代码冗余,性能较高,存在幂等,空回滚,悬挂等问题 可以通过本地事务表记录XID判断解决这些问题
4.SAGA模式 最终一致性 依据调用链路依次补偿,恢复模式有2种 1.向前恢复 重试保证成功 2.向后恢复 补偿失败请求 性能高 代码冗余
Seata提供了几种事务模式?以及各个事务模式优缺点
通过@GlobalTransactional 串行化保证写隔离
通过@GlobalLock+select for update 保证写隔离
脏写问题
默认未解决,可以通过select for upate 解决
脏读问题
AT模式下脏写,脏读问题如何解决
1.存储在DB中 可靠性高 不会丢失数据,需要初始化表,性能有一定瓶颈
2.存储在文件 可靠性差,部署简单,性能好
3.存储在Redis 性能高 存在丢失数据风险 因为redis 数据存储在内存,定时任务备份Rdb
Seata存储模式有哪些?优缺点是什么
1.TM向TC申请全局事务,TC 创建全局事务
2.TC将全局事务XID返回给TM,RM注册分支事务到TC,并且绑定XID
4.TC 提交/回滚命令RM RM提交/回滚事务
Seata AT模式执行流程
Seata
spring cloud
git
jenkens
docker
k8s
DevOps
1.List 非固定长度,数组固定长度
2.ArrayList 底层实现基于数组,不支持非引用类型
3.List 插入 删除效率低于数组,功能比数组强大
List与数组的区别
1.jdk7 数组+链表
2.jdk8 数据+链表/红黑树 解决树不均衡问题
底层数据结构?
链表法,将相同的hashCode值放在链表存储
解决哈希冲突?
当Map中的元素个数超过了数组长度*0.75开始扩容,扩容容量=原容量*2
如何扩容?
过大哈希冲突过多 导致性能问题。过小 空间浪费问题
为何负载因子0.75?
HashMap
数组+链表/红黑树实现。头部节点加锁,锁粒度更小,是通过 CAS 或 synchronized 来实现线程安全的
如何保证线程安全
流程
是否需要加锁
put
Concurrenthashmap
HashTable
本质上基于HashMap实现
Hashset
基于红黑树实现的 Key 不能为null
如何实现 的?
底层实现方式不同 2.TreeMap可以实现自定义排序 3.TreeMap key 不能为Null
对比hashMap区别
TreeMap
底层基于TreeMap实现的 是一个有序的Set集合
如何实现的
1.底层实现不同 HashSet 基于HashMap实现的 Treeset 是基于TreeMap实现的
2.Treeset 不能添加Null 是个有序的Set 集合 而hashSet 是无序的 可以添加NuLl
对比HashSet区别
Treeset
优点:执行效率高 无锁 缺点:浪费内存
1.饿汉式单例
优点:节省内存 缺点:非线程安全
2.懒汉式单例·
优点:节省内存 线程安全 缺点:效率低下
3.双写检查懒汉式单例
Spring IOC
4.容器式单例
实现方式有哪些,优缺点
IOC容器式单例
实际框架应用
单例模式
1.工厂模式 主要分2种 1 简单工厂 2.抽象工厂
2.简单工厂 可以通过传入简单参数动态创建对象 抽象工厂 可以动态创建复杂对象
3.Spring 中 FactoryBean 就是工厂模式的体现
工厂模式
1.原型模式主要用于对象拷贝复制,对象拷贝 分为深拷贝跟浅拷贝
2.浅拷贝 拷贝的是对象的引用 深拷贝 是 生成全新对象 可以使用序列化来实现
原型模式
1.代理模式有2种 1.jdk动态代理 2 cglib代理
2.jdk 动态代理是通过反射实现的 被代理类必须要实现接口 cglib是通过编码继承类实现的,不需要实现接口
3.Spring AOP就是使用了代理模式
代理模式
1.装饰模式 主要是增强对象的方法
2.Spring 中BeanWrapper就是装饰器模式体现/dubbo中wrapper
装饰器模式
1.观察者模式 分为2种角色 1.被观察者/主题通知 2. 观察者 常用于方法回调
2. 被观察者 维护了观察者列表,被观察者触发观察者 回调update事件
3.观察者通过register注册到观察者列表 ,同时观察者定义了回调事件逻辑
5.消息通知,回调函数可以用观察者模式
观察者模式
spring 中动态加载Resource
动态选择算法或者实现类时候可以应用
策略模式
MyBatis插件Plugins应用
Netty中Pipeline
动态指定一组对象处理请求
责任链模式
Mybatis Cache
Springmvc dispatchServlet
委派模式
设计模式
serverSocket.accept() 服务端等待客户端链接时候是阻塞的
IO数据的读取写入必须阻塞在一个线程内等待其完成
BIO阻塞在哪
并发量高 开辟多个线程 CPU切换消耗资源过大,如果线程池 处理线程过小无法应对高并发
多线程BIO有什么问题
什么是BIO
IO多路复用 多个IO请求注册到Seletor上 linux监控所有注册的Seletor请求,数据准备好了就返回 可读 可拷贝
简叙下NIO多路复用
poll是linux 轮询selector请求 支持连接数有限 同时性能也不如epoll
epoll 是注册fd事件的callBack方式 支持连接数远超poll 同时不用轮询selector
poll与epoll区别?
什么是NIO
IO
不需要内核空间到用户空间的拷贝
什么是零拷贝
1.实现方式主要有2种 1.sendFile 2.mmap
2.sendFile 是用户发送指令,内核DMA拷贝到网卡,不经过用户缓冲区
3.mmap是用户缓冲区与内核缓冲区建立共享内存,用户可以操作共享内存
4.sendFile 适用用大文件 mmap 适用于小文件 有文件大小限制
5.kafka用的是sendFile零拷贝 rocketMq用的是mmap技术
实现方式哪有些
零拷贝
1.写入数据>套接字缓冲区大小
2.发送的数据>tcp协议传输数据大小
1.拆包问题产生的原因有2个
1.写入数据<小于缓冲区大小
2.接收方读取操作不及时 造成缓冲区数据堆积
2.粘包的原因有2个
拆包粘包问题产生的原因是什么?
FixedLengthFrameDecoder
1.定长协议 不够补空格
DelimiterBasedFrameDecoder/LineBasedFrameDecoder
2.特定字符分割协议
LengthFieldBasedFrameDecoder 消息头+消息体
3.变长协议
采用协议解决
如何解决拆包粘包问题
Netty
Https 如何实现数据安全的
Https
序列化
java基础
分布式ID
缓存
分布式锁
1.String
2.Hash
3.List
4.Set
5.ZSet
Redis数据结构有几种
redis 数据结构有哪些?应用场景?
1.redis 采用定期过期+惰性过期淘汰已过期的Key
2.定期过期就是 定时拉取一定数量的Key淘汰
3.惰性过期就是Get时候判断Key是否过期,过期删除
4.redis 内存淘汰策略有4中 1.Random 随机淘汰 2.LRU 最近最少使用 3 LFU 最不经常使用 4 ttl 优先淘汰最早过期的Key
5.redis 可以通过maxmemory-policy 设置淘汰策略
redis 内存淘汰机制
1.redis 持久化策略有2种 1.rdb 文件 2.aof文件
2.rdb是redis快照文件 每隔一段时间后台线程会生成一份rdb快照 优点是不影响主操作 缺点是 丢失数据
3.aof 存储是redis操作指令,redis 每次操作命令都会存储到redis aof缓存,aof 内容定时/实时存入磁盘 默认1s一次 优点是 安全性高,可做到不丢失数据 缺点是性能低 会影响主线程操作
redis持久化策略有哪些?有什么优缺点?
1.redis 主从复制分为全量复制 和增量复制 2种情况
2.首次复制是全量复制 首先 slave 发送命令给master master接到命令 开启bg线程 生成rdb快照,同时缓冲后续请求, slave接收到rdb快照 清空数据 执行复制
3.master 将建立长连接将后续请求发送给slave slave 执行命令
4.增量复制 slave与master 断开连接时候产生,此时slave 连接master 请求带上offset,master根据offset 将后续命令同步给slave
简叙下redis主从复制流程
1.redis 哨兵 是通过哨兵节点监听主节点 哨兵节点每隔一段时间会向master 发送心跳请求,如果超时 就会认为master 主观down
2.主观下线后,哨兵节点会发送命令给其他哨兵节点,其他哨兵节点会给master 发送心跳包,如果超时过半,此时master 就会被认为客观下线,哨兵节点就会发起Master 选举 ,选举算法采用的是raft算法
3.影响成为master 因素有 1.网络 断开连接时长 2.配置优先级 3.offset 最大 数据最全 4.进程ID
简叙下redis 哨兵模式原理
redis 集群算法
请求一个不存在的数据 导致跳过缓存不停的请求数据库
布隆过滤器缓存所有数据
解决思路:通过缓存快速验证数据是否存在
什么是缓存穿透?如何解决?
搭建集群,主从
redis 挂了
设置不同过期时间
ttltime一致
大量缓存同时失效
什么是缓存雪崩?如何解决?
某个时间段 缓存失效,大量并发请求
解决思路:锁
什么是缓存击穿?如何解决?
redis
效率问题
1.发送事务消息
单挑发送
数目问题,过大失败,过小效率
批量发送
推荐 效率高,通过异步回调实现
异步发送
2.ACK消息
发送消息的可靠性
队列持久化、消息持久化和交换器持久化。
1.消息持久化
2.高可用 集群
接收消息的可靠性
消费者应答机制 默认自动应答 改成ACK手动应答
消费消息的可靠性
rabbitMQ
1.kafka 为了保证效率是通过批量发送到Page cache,异步刷盘来实现高性能
1.发后即忘 无返回值发送 效率高 可靠性差
2.同步发送 Future 获取返回结果 效率低 可靠性高
3.异步发送 Callback 获取返回结果 综合性能好
2.kafka发送消息方式有三种
log.flush.interval.messages
多少条消息刷盘1次
log.flush.interval.ms
多久刷盘一次
log.flush.scheduler.interval.ms
周期性刷盘时间
3 kafka flush刷盘 策略
不需要服务端Ack 效率快 可靠性不高
Ack=0
leader落盘Ack 有丢消息风险
Ack=1
所有Follower 全部落地Ack
开启幂等性enable.idempotence=true
重复消费消息问题
Ack=-1
1.kafka接收消息服务端Ack机制 分为三种
索引文件
xx.index
消息
xx.log
xx.timeindex
Segment
文件夹:<topic_name>-<partition_id>
配置log.dirs
2.本地存储
commitSync
同步发送
commitAsync
消费消息提交offset
kafka
当前线程等待 broker 响应 发送结果
线程池异步回调,返回结果
不保证可靠性
单向发送
消息重试机制
同步发送+消息重试机制 保证可靠性
选择
发送消息可靠性
同步刷盘:写入PageCache立即刷盘CommitLog 保证了可靠性,但是性能低
异步刷盘:写入PageCache 定时写入CommitLog 可靠性低 性能高
rocketMq接收到消息写入PageCache 刷盘方式有2种
同步复制:主从均写入成功返回消息接受成功
异步复制:主写入成功就返回消息接收成功
主从同步的可靠性
消费消息返回CONSUME_SUCCESS 确保消息被消费
异常返回CONSUME_LATER 消息会被重试
rocketMq
如何保证消息的可靠性
单消费者单线程消费
rabbitMq
只能保证一个partion内单线程消费的有序性
指定唯一队列发送
全局有序
相同业务流程指定同一个队列
局部有序
发送消息的有序性
多线程+锁MessageListenerOrderly顺序消费
消费消息的有序性
如何保证消息的有序性
1.MQ服务器内存局限性,无法及时有效淘汰内存
2.MQ服务器down机导致后续大量请求失败
3.如果加快消费效率 ,让消息不再堆积
1.堆积会产生什么问题?
1.如何淘汰有效内存·
2.淘汰内存如何处理
2.如何解决这些问题
解题思路
内存到达一定比例,将一部分内存中数据刷盘,然后淘汰掉
1 如何淘汰有效内存
连接池技术,让后续链接排队获取连接请求
2.大并发访问MQ链接不可用怎么办
1.多线程消费
2.多消费者消费
3.如何增加消费速率
解决方案
消息堆积如何处理?
生成唯一消息ID redis setnx
如何保证消息的幂等性,不被重复消费
采用插件rabbitmq_delayed_message_exchange
延迟消息如何实现
过期的消息ttl
消息超长
消费者拒绝reject/nack 并且requeue=false
死信队列
不能保证高可用,数据分散分布
普通集群
高可用,性能低
镜像模式
集群模式哪几种?有什么优缺点
改写Topic 头,保存原有Topic到Properties中 写入commitlog
1.发送half消息
2.执行本地事务
3.commit事务
删除commitLog
4.rollback事务
什么是half消息
与half消息一直 发送延迟消息 改写Topic头,定时器扫描延迟队列,改写Topic实现消息投递
延迟队列的实现原理是什么?
消费失败重试达到最大重试次数后进入队列
死信队列的触发条件
ConsumeQueue->offset->commitLog->message
如何存储检索数据的?
1.定时器 slave链接master 发送拉取请求 以及自己的commitLog的offset
2.master 接收请求,与master offset比较,生成要同步commitLog buffer,发送给slave
3.slave接收到master请求,写入本地commitLog
commitLog复制
定时任务处理
元数据的复制
主从同步流程
mq
1.JVM运行时数据区 分为 1.方法区 2 堆 3 栈 4 本地方法栈 5程序计数器
2.方法区 属于堆上一种 方法区存放类的描叙信息,常量,静态变量,方法区内存溢出会触发OOM 线程公有
3.堆 存放对象,数组 内存溢出会触发OOM 线程公有
4.栈 线程私有 生命周期跟线程一致 栈由N个栈帧组成,栈溢出会触发StackOverflowError
5.本地方法栈 java 中native 方法
6.程序计数器 线程私有的,记录线程执行位置
JVM 运行时数据如何存放
JVM 内存总体分成2部分 1.老年代 2.新生代
1.新生代 又划分了三个区域 edem区 s0 s1区
2.新创建的对象会分配到新生代的edem区 新生代的GC称为youngGC
3.经过young GC 如果对象还存活 便会进入S区
4.如果young 区分配不下的对象或者young gc 15次以上还没有被回收的对象 会进入Old区
5.old区达到一定比例会触发Full GC
6.old区也放不下的对象 会触发OOM
JVM内存结构有哪些?
JVM 通过GCRoot引用不可达判断垃圾
如何确定对象为垃圾
1.JVM 垃圾回收算法有3种 1.标记清除 2 复制 3 标记整理
2.标记清除算法有内存空间不连续问题
3.复制算法有空间浪费问题
4.标记整理有效率低下问题
JVM垃圾回收算法有哪些?特点是什么?
1.垃圾回收器主要有5种 1Serial 2 ParNew 3.Parallel4.CMS 5.G1
Jvm垃圾回收器有哪些?
1.Serial 是单线程垃圾收集器 他有适用于新生代和老年代版本 新生代采用的是复制算法 老年代Serial Old 采用的是 标记整理算法,
2.ParNew与Parallel 是多线程垃圾收集器 Parallel更加关注吞吐量 新生代版本采用复制算法 老年代采用标记整理算法
3.CMS 适用于old区垃圾收集器 采用标记清除算法,关注停顿时间,适用于后端任务的垃圾处理器
4.G1 适用于新老年代垃圾收集器 采用标记整理算法 可以自设置停顿时间 适用于web交互场景
JVM各个垃圾回收器特点以及使用场景
CMS垃圾收集器垃圾回收可分4步
对GCRoot能直接关联的对象打标 会STW 速度快
1.初始标记
对关联对象开始遍历整个对象图,多线程处理 不会终止用户线程
2.并发标记
修正用户线程产生变化的标记 会STW
3.重新标记
多线程 处理垃圾回收 不会终止用户线程
4.并发处理
CMS垃圾收集器流程
G1垃圾收集器可以分4步
标记GCROOT直接关联的对象
2.并发标记(不会终止用户线程)
3.最终标记
4.筛选回收(有选择性回收垃圾,重复回收)
G1垃圾收集器流程
JVM 常用调优明细有 jps jinfo jstat jstack jmap jhat
jps 查询java 进程信息 获取进程ID
jinfo 查询JVM参数 堆内存大小 垃圾收集器
jstat 查看jvm运行时状态信息, 包括内存状态、垃圾回收
jstack 查看jvm线程快照的命令
jmap 生成dump文件,查询堆内对象示例的统计信息、查看classLoader的信息以及finalizer队列
jhat 分析dump文件 用于离线分析
常用堆分析工具有jvisualvm mat arthas
常用 GC log分析工具有GCViewer gceasy.io
Jvm调优常用命令有哪些?作用是什么?
方法区太小?
类加载太多?
1.方法区FullGC
大对象?
内存泄漏未回收?
空间碎片问题?
高并发问题?
程序效率问题?对象长时间得不到释放?
堆过小问题?
2.堆上FullGC
分析FULL GC可能产生的原因
1.jstat 打印gc日志,查询内存空间大小
2.jmap 查询内存使用情况
3.jstack 查询线程,cpu请求情况
4.dump堆文件,mat工具分析
5.高并发问题?增大S区
6.空间碎片问题?切换垃圾收集器
解决问题
Full GC频繁如何解决
1.堆内存空间不足
2.edm区域太小,频繁ygc 大量对象进入old区
3.代码问题 大对象
分析原因
2.minor gc/major gc 工具gceasy查看
3.jmap 查询内存使用情况
GC频繁如何解决
方法区/堆上OOM?
cglib
动态生成类 加载类?
方法区分配太小?
方法区OOM 原因?
死循环添加对象?
程序慢 大对象不能释放?
内存太小?
高并发?瞬时大量请求 创建大量对象?
内存泄漏?
堆上OOM原因?
1.确定是堆上OOM还是方法区/元空间上OOM
增大元空间大小,配置参数-XX:MaxMetaspaceSize=xx
2.方法区OOM java.lang.OutOfMemoryError: MetaSpace
jmap dump 堆上内存信息。mat 分析有没有大对象
3.堆上OOM OutOfMemoryError: Java heap space
4.jinfo 查询堆内存大小,比例情况。元空间大小。垃圾收集器的选择。
OOM如何排查问题
1.高并发 访问过多?
2.多线程 死锁?
3.消耗CPU的计算任务?
4.FullGC过多?
1.top查询cpu使用率高的应用ID
1.查明哪个进程导致CPU飙升
2.jstack 查询线程使用情况,排除死锁问题
3.jinfo 查询JVM参数信息,jmap查询堆内存使用情况
4.jstat 统计FullGC情况
CPU飙升如何解决
JVM
分布式ID生成有哪些
需要数据库支持
性能差
XA协议
强一致性
try confirm cancel 补偿型事务·
TCC
支持 AT TCC SEAGA XA4种模式
弱一致性
分布式事务解决方案
选举算法有哪些
临界值问题
计数器
缩小范围
滑动窗口
无法应对瞬时高并发场景
漏桶算法
解决高并发场景
令牌桶算法
限流算法有哪些
一致性哈希算法原理?如何解决数据倾斜问题?
使用一组哈希函数,将元素映射成一组位数组中的索引位置
布隆过滤器原理?
1.高并发
2.读多写少
3.无效请求多
秒杀特点
1.流量过大导致服务端挂掉
2.数据库链接问题
3.缓存问题
4.库存问题
5.消息丢失
6.限流
秒杀问题
分析问题
动静分离
客户端缓存静态资源
1.减少静态资源占带宽IO资源
缓存击穿
布隆过滤器
缓存穿透
redis缓存信息
2.数据库读问题
1.加锁性能问题
2.不加锁,读取与更新非原子性 造成库存超卖
3.乐观锁高并发带来死锁问题
数据库扣减库存
2.lua 脚本扣减库存
redis扣减库存
1.生成订单
2.发送延迟消息 回查订单是否扣费
发送下单Mq
存在伪造IP可能
1.IP限流
2.验证码
限流控制
3.库存问题
设计思路
秒杀如何设计?
大文件导入导出如何设计?
缓存一致性如何解决?
分布式
变长协议,适用于高并发 小数据传输,消费者比提供者个数多
dubbo协议(默认)
传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件
hession协议
thrift协议
grpc协议
rest协议·
rmi协议
http协议
webService协议
memcached 协议
dubbo 支持哪些协议?各个协议使用场景
dubbo 支持哪些序列化方式?使用场景?
⽅法级优先,接⼝级次之,全局配置再次之
如果级别⼀样,则消费⽅优先,提供⽅次之
dubbo 配置优先级
接口添加@SPI注解,配置文件需放置在 META-INF/dubbo,通过键值对的方式进行配置
根据名称扩展
getExtension
根据url参数动态扩展
getAdaptiveExtension
根据条件扩展
getActivateExtension
扩展点ExtensionLoader
dubbo SPI
dubbo 注册流程
dubbo
zk
1.倒排索引设计 ,通过各种压缩算法,缓存算法将索引存在内存 从而实现内存索引查找
es为什么查询快
乐观锁
if_seq_no(自增号)+if_primary_term(分片号) 实现乐观锁
version 主分片写入成功,备份分片还未同步,主分片down机会有问题,版本号还未+1
es用的是悲观锁还是乐观锁?如何实现的?
master 性能问题导致超时重新选举master
原因
如何发现
Master与Data节点不能为同一个,否则容易导致负载过高
增加主节点的响应时间discovery.zen.ping_timeout 默认是3s
避免超时
es 脑裂问题的原因是什么?如何发现?如何解决?
shard = hash(routing)%分片数
es 路由算法
写入数据->memory buffer(不可查询)->refresh File system cache(1s 可查询)->flush 磁盘(30m)
事务日志translog->commit point 记录最后刷盘位置->异常恢复数据
es 为什么是近实时的?说说存储流程?
es
中间件
面试题
0 条评论
回复 删除
下一页