数据库篇
MySQL数据库相关:
1.MySQL有哪些常见的存储引擎?
innoDB,myISAM,MEMORY
2.索引的原理是什么?
innoDB和myISAM对应 B+tree, memory对应hash
3.MySQL三种日志分别起到什么作用?(redoLog,undoLog,binLog)
redolog\undolog\binlog
mysql中有缓存池机制 减少io开销
redo log:是InnoDB存储引擎独有的,它让MySQL拥有了崩溃恢复能力
刷盘时机:redolog有三种机制:
0 :设表示每次事务提交时不进行刷盘操作,通过定时任务触发
1 :表示每次事务提交时都将进行刷盘操作(默认值)
2 :表示每次事务提交时都只把 redo log buffer 内容写入 page cache
binlog: 按顺序记录表操作,可以说MySQL数据库的数据备份、主备、主主、主从都离不开binlog,需要依靠binlog来同步数据,保证数据一致性
刷盘时机:write和fsync的时机,可以由参数sync_binlog控制,默认是0。
为0的时候,表示每次提交事务都只write,由系统自行判断什么时候执行fsync。
为1的时候,表示每次提交事务都会执行fsync,就如同 redo log 日志刷盘流程 一样。
为N的时候,表示累计的提交事务达到N时才进行刷盘流程
undo log :保证事务的原子性,所有事务进行的修改都会先记录到这个回滚日志中,然后再执行相关的操作
为什么选择B+树索引?
我的理解简单来说就是:
1.因为B+tree中间节点置存储索引,只有在叶子结点存储了数据以及指向该数据的索引,所以减少了io次数,相当于每次搜索只需读取一次磁盘
2.叶子结点的元素也是有序排列的
什么情况下会出现索引失效?
1.若语句使用复合索引查询,不符合最左原则的查询
2.where条件中使用到了计算、函数、类型转换 ( 自动或手动 ) 。
3.is null 可以使用索引,is not null 无法使用索引。
4.使用or切前后存在非索引的列
5.like以%开头的
6.不同字符集的比较,不同类型的比较
如何查看执行计划?
explain语句:
id:id相同从上倒下执行,id不同越大的越先执行
select_type:查询类型-SIMPLE(简单的单句查询),PRIMARY-(包含复杂子查询的最外层查询),SUBQUERY-(子查询),DERIVED-(在from列表中包含的子查询被标记为derived(衍生)不是很懂)UNION-(union关联的后一个语句)UNION RESULT-(从union表获取最终结果的语句)
type:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
possible_keys:查询涉及到的字段上存在的索引
key:实际使用的索引
。。。。。。。key_len,ref,rows,extra
如何优化SQL查询?
1:避免使用select * 进行查询,需要哪些字段查询哪些字段,insert的时候明确插入的字段;
2:在where条件的字段、order by的字段、表关联的字段,建立合适的索引;
3:通过explain查看执行计划,查看是否走索引,是全表扫描、范围扫描,还是根据索引查找等;
4:如果是组合索引,则进行最左匹配原则。
5:减少模糊查询的使用,如果需要使用like查询,则使用 like ’test%‘,避免使用 like ’%test‘,%在前,会导致索引失效;
6:如果对数据实时性要求不高且含有复杂计算逻辑的查询,可以定时将计算好的数据刷新到临时表,这样可以提高查询效率;
7:建立索引的时候,选择基数比较大的字段,像状态字段之类的,可能只有两三种值,则没必要建立索引,建立索引反而会影响删除和插入的性能;
8:当只需要查询一条数据的时候,加上limit 1;
9:减少not in 的使用,如果需要使用,则使用not exists,因为not in 不会走索引;
10:尽可能的避免or的使用,因为这会放弃索引,从而进行全表查询,可以使用 union all
MySQL主从复制原理?
数据库死锁的原因?如何快速定位并解决?
事务之间对资源访问顺序的交替
并发修改同一个记录
索引不当导致全部扫描
事务封锁范围大且相互等待
事务隔离级别
事务有哪些隔离级别?
由低到高分别为Read uncommitted 、Read committed 、Repeatable read 、Serializable
读未提交 . 读提交. 重复读(就是在开始读取数据(事务开启)时,不再允许修改操作). 序列化.
每种隔离级别会导致什么问题?
脏读:读到未提交的事务
不可重复读:同一个事务两次读取不一致
幻读:同一事务两次读取到的数量不一致
三范式?1.保每列保持原子性,2.确保表中的每列都和主键相关,3.确保每列都和主键列直接相关,而不是间接相关
mysql 和 oracle默认情况下分别采用哪种隔离级别?
mysql默认rr oracle默认rc
mysql如何解决幻读的?
加间隙锁,对数据区间加锁
mvcc多版本并发控制
中间件篇
MQ的相关问题
你用过消息队列吗?用了哪个消息队列?
用过,rabbitmq
在使用MQ的时候怎么确保消息 100% 不丢失?
从两个层面出发,消息生产者,队列持久化,消息消费者
消息生产者开启发送确认,获取交换机接收成功标识
队列持久化
消费者开启手动确认消费机制
other :还可以使用死信队列处理消费失败的数据
怎么解决消息的重复消费问题?
出现的原因,可能同一条消息,生产者重复发送(由于网络延迟等不可控因素)
应从消费者端解决:
消费端处理消息的业务逻辑保持幂等性
可以用redis的set存储消息唯一id
也可以使用数据库的排他锁
如何实现顺序消息?
1.可以仅使用一个消费者自然实现顺序消费
2.版本号的方式实现
3.分组且加版本号
如何解决引入消息后的事务问题?
如果问到就反问一下什么是引入消息后的事务问题,因为一般引入事务业务上一个消息就是一个原子的操作,如果涉及多dml操作或者多个微服务,只要在消费者方法上加事务控制或者引入分布式事务seta
分库分表相关问题
你用过分库分表吗?
用过,mycat,shardingsphare-JDBC
如何实现单个维度的非sharding-key 的查询问题
?比如通过userID 作为 sharding-key,那么如何实现基于userName进行查询?(映射法、基因法)
一般我们是不建议这样设计的,如果一定会出现这种场景且使用较频繁的话,可以建个中间表的方式先通过userName找到userID
如何实现多个维度的多个字段非 sharding-key 如何查询?时间、用户名、类别等...
没做过,一般都是尽全力配合分表规则在业务上规避掉这些情况
多维度查询需要配合其他查询引擎,那么如何实现数据同步?如何保证双写的一致性?
1.根据常见查询场景,增加相应字段的组合索引
2.引入ES,写操作通过同步机制如canal同步到es,查询是es支持多维度查询
很多情况下并不是一开始就实现分库分表,等我们需要分库分表的时候如何进行数据迁移?
1.本次我做的分表分库是通过跑代码的方式分表分库的
Redis
用过Redis吗?Redis支持哪些常见的数据结构?
用过 ,redis实现多种结构底层是使用了redisObject,包含三个重要属性
type(String,List,Hash,Set,Zset),encoding(value的底层编码),ptr
Redis的线程模型
6.0前单线程,6.0后多线程,main线负责分发支线负责返回客户端结果
Redis如何保证数据不丢失的(如何实现持久化)?
RDB 持久化机制,是对 Redis 中的数据执行周期性的持久化
AOF 机制对每条写入命令作为日志
AOF 和 RDB的实现原理?
AOF:日志的方式同步,每一秒会有一个线程同步数据,追加的方式,丢失风险小,文件会偏大
RDB:通过快照的形式5分钟甚至更久时间同步一次数据,性能影响小,丢失风险大
Redis如何实现高可用?
高可用:一是数据尽量不丢失,二是保证服务尽可能可用
1,不丢失:RDB,AOF
- 可用:主从模式,哨兵模式,集群模式
什么是缓存穿透,缓存击穿,缓存雪崩?分别如何预防解决?
穿透:缓存,数据库都没有数据,导致用户误解不断发起请求---缓存空对象,布隆过滤器
击穿:大量缓存同时过期,同时大量访问io操作打入数据库---热点数据,使用互斥锁排队
雪崩:与雪崩类似--互斥锁,缓存预热(提前加载),缓存屏障
分布式锁相关问题
用过分布式锁吗?用什么实现的分布式锁?
没用过,但是知道可以使用
a.基于数据库,b.redis,c.zookeeper,了解过redis实现的分布式锁,主要是setnx命令的排他特性,获取锁的操作关键词:同步,设置超时时间
有没有用过基于redis分布式锁?有没有用过基于Zookeeper的分布式锁?
如何给锁设置合理的加锁时间?锁超时了怎么办?Redisson看门狗的原理?
加锁时间应当超过业务执行时间,若业务未完但锁以过期,可能会释放其他线程的锁,所以可以使用lockwatchdogtime,只要占用锁成功,就会另起一个线程每单位时间延长一次锁过期时间。
Redis如何解决集群情况下分布式锁的可靠性?
自动续航,
RedLock算法的原理?
1.redis集群的场景下,只要半数结点返回获取锁成功则本次获取锁成功,类似选举算法
2.锁记录结构为 哈希表,lockname-(uuid,计数器)
并发编程篇
锁相关
说一下synchronized 底层实现原理?
被该关键词标注的代码块,线程在执行前必须先获取对象锁,而释放锁的动作会由jvm完成
说一下synchronized、volatile、CAS 的区别?
1、synchronized 是悲观锁,属于抢占式,会引起其他线程阻塞。
2、volatile 提供多线程共享变量可见性和禁止指令重排序优化。
3、CAS自旋锁, 是基于冲突检测(版本控制)的乐观锁(非阻塞
synchronized 和 Lock 有什么区别?
1.作用位置:sync加在代码块,方法上,Lock用在方法中
2.解锁方式:sync由jvm自动解锁,Lock需要在finally中手动解锁
3.锁原理:sync使用悲观锁机制,cas使用自旋锁,属于乐观锁机制
什么是CAS,CAS的原理?
CAS:Compare and Swap,即比较再交换CAS 操作包含三个操作数 -- 内存位置、预期数值和新值。CAS 的实现逻辑是将内存位置处的数值与预期数值想比较,若相等,则将内存位置处的值替换为新值。若不相等,则不做任何操作。
CAS有什么缺点?如何解决CAS中常见的ABA问题?
ABA问题:增加了预期值来解决更新前后版本不一致的问题
循环时间长,开销大;
只能对单共享变量的场景
AQS的原理,AQS的实现过程是什么?
AQS:抽闲队列同步器
实现过程:关键参数--volatiel修饰的state和NodeCLH队列,ConditionObject条件变量
有没有用过读写锁ReentrantReadWriteLock,说一下ReentrantReadWriteLock的原理?
读写锁可以说有两个锁(读,写锁)组成,读锁可多次获取,写锁是独占锁
线程池相关
有哪几类线程池?如何创建线程池?
答:1.newCachedThreadPool 可缓存的线程池,任务增加时可以自动添加新线程,线程池的容量不限制。比较适合处理执行时间比较小的任务
2.newFixedThreadPool 固定数目,任务失败时自动补充,可以用于已知并发压力的情况下,对线程数做限制。
3.newScheduledThreadPool 创建一个支持定时及周期性的任务执行的线程池。适用于需要多个后台线程执行周期任务的场景。
4.newSingleThreadExecutor. 创建一个单线程化的Executor,线程异常结束,会创建一个新的线程,能确保任务按指定顺序(FIFO,LIFO,优先级)执行。可以用于需要保证顺序执行的场景,并且只有一个线程在执行
解释一下线程池的核心参数,线程池的执行过程?
核心参数:corepoolsize 核心线程数
maximunpoolsize 线程池最大数量
keepalivetime 多余空闲线程的存活时间
unitime 时间单位
workQueue 工作队列
threadFactory 线程工厂
handler. 拒绝策略
执行过程:1.提交任务后先与核心线程数对比,
2.小于核心线程数创建核心线程
3.大于核心线程数判断阻塞队列是否已满
4.阻塞队列未满将任务添加到阻塞队列中
5.阻塞队列满创建非核心线程执行任务
6.若非核心线程创建失败,--拒绝任务
如果提交任务时,线程池队列已满,这时候会发生什么?
线程池线上参数如何优化?
1.首先需要知道,功能最大并发量,单任务处理时长,系统允许任务最大的响应时长
2.然后每个核心参数都有个计算公式,具体网上可以查到。
分布式篇
分布式理论
说说你对CAP理论的理解?
1.一致性,可用性,分区容忍性。
说说你用过的注册中心,分别使用了什么模型?(AP,CP)
eureka--AP模型 zookeeper--CP模型
说说你对BASE理论的理解?
我觉得就是保证p的情况下,根据功能业务的特点来补全A或C,属于非百分百保证的措施
分布式事务相关
如何解决分布式事务问题?你用过哪些解决分布式事务的方案?
说一下对2PC,3PC协议的理解?
有没有用过SEATA,SEATA的实现过程是什么?
如何基于MQ实现最终一致性?
实战篇
如何设计接口并保证他们的安全?
如何快速定位CPU溢出?
如何设计实现一个限流组件?
如何让系统能抗住预约抢购活动的流量压力?
histrix的实现原理
hystrix实现的功能有 熔断,降级处理,资源隔离,缓存,常用的为前三个,
资源隔离:分布式系统中,不同服务的线程隔离和信号量隔离,同一个调用链中某一个服务调用问题不会影响其他服务的调用
降级机制:资源不足时和超时时调用降级处理方法,返回托底数据。
熔断:请求连续失败大于阈值时,断路器开启,指定时间后断路器转为半开状态,半开状态下,若请求成功数大于阈值,断路器关闭
缓存:返回结果缓存,后续相同请求时,直接返回缓存数据
隔离模式:线程池隔离和信号量隔离
histrix openfegin rebbon超时的配置方案?
feign的调用超时时间和ribbon的超时时间只会有一个生效,feign优先,ribbon的超时时间时默认1s
由于connection的时间一般很短,所以忽略只要 ribbon的重试次数*读取时间小于hystrix的超时时间就可以了
(1 + MaxAutoRetries) * (1 + MaxAutoRetriesNextServer)* ReadTimeOut < hystrix 的 *timeoutInMilliseconds
如何指定服务的调用超时时间?
feign.client.config.default(课替换成指定服务名称).xxxTimeout
如果出现cpu内存告警,如何定位问题并解决
使用top指令找出cpu占用最高的pid
可以用 jmap -heap PID 查看是否内存分配过小
jmap -histo:live PID | more查看最占内存的对象
有没有用过线程池处理多线程的场景
动态代理的原理及常见应用
原理:分为(JDK 动态代理 和 cglib 动态代理)
jdk动态代理:实现了 invocationHandler接口 通过调用invoke方法访问目标方法 本质就是反射机制的应用
常见应用:AOP 的实现、RPC 远程调用、Java 注解对象获取、日志框架、全局性异常处理、事务处理
eureka:服务注册中心,同一管理注册的服务,
服务注册:分布式场景下,一个服务有多个ip+端口,交给nginx管理会频繁修改配置文件,而且不灵活,引入注册中心,将统一服务的不同ip用服务名管理起来
服务发现:当有服务启动后,服务会自动向注册中心发起注册请求
幂等的实现?高并发下?防止超卖
1.每次更新数据库之前查询数据库,并启用cas乐观锁的方式(查询的时候查一个版本号,更新的时候也更新版本+1)
arrayList底层和 扩容机制
实现自 Collection下的List类 底层由数组组成,扩容时一般以1.5倍创建新数组,在将原数组复制到心数组,原数组交由gc自动回收。
springmvc工作流程
dispatcherServlet-》handlerMapping-handleExcutorChain->HandleAdpter-Handler-ModleAndView->试图解析器-view->渲染视图-返回用户
jvm:
jvm分区?
1.线程私有内存区:程序计数器,java虚拟机栈(线程私有的存放栈帧),本地方法栈(为非java方法提供服务)
2.线程共享内存区:堆(新生代,老年代),方法区(存放静态变量,常量,类名等)
项目中遇到的困难?
消息队列的消息丢失-》在项目首次用到消息队列处理大量数据接收的时候,我们使用了消息队列来对消息解析和消息入库做了一个解藕的操作,但是运行一段时间后,发现了生产环境存在数据丢失的情况,我们紧急定位,联系了数据上层推送房,发现每次丢失的数据都是在迭代发布,也就是服务重启的时候,猜测是消息消费时,由于服务重启,导致消息丢失,而且也没有相应日志报错,
做了如下措施,
1,开启应用的优雅停机模式,设置间隔时间为30s。
2,服务生产者队列开启持久化,
3,并开启消息消费确认机制,
4,再设置上死信队列,
5,并且开启一个另一个消费者,消费死信队列的消息
6,失败的消息存放到数据库中
7,定时任务定时调用生产者将消息重新推送至消息队列
新技术的应用分表分库-》在数据源切换的过程中,使用到了新技术shardingspherejdbc,相同部门没有其他人使用过,只能通过查询官方文档尝试使用,在调试的过程中,出现了如何在一个服务中兼容 shardingsphere和mycat两个数据源?如何设置默认访问的库?如何自定义多个分裤规则并灵活应用在不同的表中?如何配置读写分离?最终都是通过查询官方文档,(像默认的库,读写分离配置,自定义多个芬片规则并灵活应用等问题,官方文档都没有给出解答,是在自己的猜测尝试,查看源码和查询网上其他人的解决方案来解决的)
nginx:
线程的阻塞方式?
线程由五种生命状态:创建、就绪、运行、阻塞、死亡
三种阻塞方式?
sleep在等待指定时间后,会重新进入等待状态继续争抢资源,sleep在等待期间不会释放锁资源
wait,会释放锁,只有在持有锁资源的线程调用notify或notifyAll才会让wait的线程继续就绪状态
同步阻塞。当多个线程想获取同一个锁资源,且锁资源正在被占用的情况下,其他线程会被JVM放入锁池中等待
sleep和wait的区别?
sleep等待一定时间后自动进入运行状态,期间不会释放锁,而wait是会释放🔒进入等待状态,只有当被notify或notifyAll时才会进入就绪状态
- HashMap什么时候分配内存空间
第一次put的时候。
- HashMap内部的bucket数组长度为什么一直都是2的整数次幂
寻址的方式是(table.length - 1) & key.hash();而hash中的算法为(h = key.hashCode()) ^ (h >>> 16)
最终减少了hash碰撞,而且通过位运算符寻址效率更高,table的长度一般时2的整数幂类似000100000这样的数-1后变成了000011111
- HashMap默认的bucket数组是多大
- HashMap什么时候开辟bucket数组占用内存
- HashMap何时扩容?
- 桶中的元素链表何时转换为红黑树,什么时候转回链表,为什么要这么设计?
- Java 8中为什么要引进红黑树,是为了解决什么场景的问题?
- HashMap如何处理key为null的键值对?
hashmap的扩容机制?
1.当HashMap中存储的元素大小等于桶数组大小乘以负载因子的时候整个HashMap就要扩容
2.
mysql主从同步的方式?
数据库的悲观锁是行还是表锁?
线程执行过程中出现异常会做什么操作?
所有设计模式的实现方式?
jdk1.8lamd表达式常见应用?
自旋锁的原理?
基于cas实现的一种锁,包含
aop和ioc的理解?
aop是动态代理模式,ioc是工厂模式,底层都用到了反射机制
aop是一种编程理念,面向切面编程,ioc时spring的bean管理机制
aop有几个重要概念:连接点,切入点,通知,切面,引入
@bean的生命周期?
分为6个阶段:bean定义,实例化,属性赋值,初始化,生存期,销毁
自动注入的原理?
核心注解EnableAutoConfiguration,通过读取spring。factory文件加载xxxAutoConfig,来自动加载对应的业务类
而我们定义的@Service,@Controller@Component类都是由ComponentScan扫描加载。
springboot启动流程?
一 springApplication构造函数的工作
1.确定应用类型 WebApplicationType.deduceFromClasspath
2.加载所有初始化器从 META-INF/spring.factories,也可以自己实现ApplicationContextInitializer接口自定义初始化器
3.加载所有监听器
4.deduceMainApplicationClass();确定main方法所在类为后续包扫描做准备。
二run方法
1.开启计时器(用于打印出启动耗时)
2.获取并启用监听器
3.设置启动参数
4.准备环境变量
5.忽略bean信息configureIgnoreBeanInfo()
6.打印banner
7.创建应用程序上下文 createApplicationContext() 反射的方式创建context
8.准备上下文环境(实力化beanname生成器,执行初始化器,注册启动参数至容器中)
springcloudgateway的过滤器实现方式?执行顺序?
可以实现globalgatewayfilter和自定义gatewayfilter
order越小越靠前,没有order全局优先,安配置文件配置顺序
了解过网络编程吗?
定时任务怎么实现?
可以使用enableschaule然后用注解schaule定义定是任务方法,可以呀单独写一个服务通过linux的cron实现
了解雪花算法吗?
由1+41+5+5+12 组成 分别为 0+时间戳+机器id+服务id+序号组成
令牌桶限流原理?
关联参数,桶长,令牌产生速率,过滤
springboot的循环依赖?
容器在启动的时候出现a依赖bb依赖cc依赖a的情况
使用懒加载
或者使用setter注入,使用时注入
对自旋锁的季节?
线程问题1:哲学家就餐问题?
使用面向对象的思维,先构建两个对象,筷子:编号,哲学家:左手筷子,右手筷子,编号。然后创建线程的时候混入一个左撇子,或者混入一半左撇子。
线程问题2:线程交替问题,两个线程(字母,数字),循环输出A1B2C3......Z26;
可以采用juc包中的 lockSupport类实现。
使用transferQueue同步队列实现
最重要:使用syncronized单锁wait和notify实现,,若要制定先打印的顺序可以使用,countdownLatch
如果需要打印类似Aa1Bb2,可以使用reentryLock ,lock.newCondition,或者用lockSupport.park
线程问题3:生产者消费者问题,实现一个队列,同步队列,实现线程安全的put get方法
线程问题4:异步回调回滚问题(分布式事务)
线程问题5:底层同步问题(乱序和屏障)