**
**
1、RocketMQ消息可靠性怎么保证?
To:消息丢失可能发生在生产者发送消息、MQ本身丢失消息、消费者丢失消息三个方面
生产者丢失:
可能发生在程序发送异常了没有重试处理、或者发送成功但是网络出现问题导致MQ没有收到.这个时候消息就丢失了
处理方法:可以通过异步发送+回调通知+本地消息表的形式处理;
比如:
1.下单后先保存本地数据和MQ消息表,这个时候消息的状态是发送中,如果本地事物失败,那么下单失败,事物回滚
2.下单成功,直接返回客户端成功,异步发送MQ消息
3.MQ回调通知消息发送结果,对应更新数据库MQ发送状态
4.JOB轮询超过一定时间还未成功发送,就去重试
5.在监控平台JOB程序处理一定次数一直发送不成功,就告警,人工处理
MQ本身丢失:
可能发生在MQ收到消息后还在内存中,这时候宕机了又没来得及同步给节点,这时候导致消息丢失
处理方法:进行刷盘的处理,RocketMQ分为同步刷盘和异步刷盘两种方式,默认的是异步刷盘,就有可能导致消息还未刷到硬盘上就丢失了,可以通过设置为同步刷盘的方式来保证消息可靠性,这样即使MQ挂了,恢复的时候也可以从磁盘中去恢复消息.
消费者丢失:
可能发生在消费者刚收到消息,此时服务器宕机,MQ认为消费者已经消费,不会重复发送消息,消息丢失.
处理方法:RocketMQ默认是需要消费者回复ack确认,消费方不返回ack确认,重发的机制根据MQ类型的不同发送时间间隔、次数都不尽相同,如果重试超过次数之后会进入死信队列,需要手工来处理了.
2、如果消费者一直消费失败,消息积压怎么处理?
To:
1、消费者出错,肯定是程序或者其他问题导致,如果容易修复,先把问题修复,让消费者(consumer)恢复正常消费
2、做转发处理,写一个临时的消费方案,先把消息消费,然后转发到新的topic和MQ资源,这个topic单独申请,要能承载当时积压的消息
3、处理完积压后,修复consumer,去消费新的MQ和现有的MQ数据,新的MQ消费完成后恢复原状
3、RocketMQ实现原理?
To:RocketMQ由NameServer注册中心集群、Producer生产者集群、Consumer消费者集群和若干Broker(RocketMQ进程)组成
架构原理:
1、Broker在启动的时候去向所有的NameServer注册,并保持长连接,每30s发送一次心跳
2、Producer在发送消息的时候从NameServer获取Broker服务器地址,根据负载均衡算法选择一台服务器来发送消息
3、Conusmer消费消息的时候同样从NameServer获取Broker地址,然后主动拉取消息来消费
4、Broker是怎么保存数据的?
To:Broker在收到消息之后,会把消息保存到commitlog的文件中
5、Master和Slave之间是怎么同步数据的?
To:
1、在broker收到消息之后,会被标记为uncommitted状态
2、然后会把消息发送给所有slave
3、slave在收到消息之后返回ack响应给master
4、master在收到超过半数的ack之后,把消息标记为committed
5、发送committed消息给所有slave,slave也修改状态为committed
6、Elasticsearch 与 Solr 的比较总结
To:
1、Solr利用Zookeeper进行分布式管理,而Elasticsearch自身带有分布式协调管理功能
2、Solr支持更多的数据,而Elasticsearch仅支持json文件格式
3、Solr在传统的搜索应用中表现好于Elasticsearch,但在处理实时应用时效率明显低于Elasticsearch
7、为什么用自增列作为主键?
To: 如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页
如果使用非自增主键,由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现在索引页的中间某个位置
此时,MySQL不得不移动数据,甚至每次把缓存清掉后,又重新从磁盘上读取出来,这增加了很多开销
8、为什么使用数据索引能提高效率?
To:
1、数据索引是有序的存储
2、在有序的情况下,通过索引查询一个数据是无需遍历索引记录的
3、极端情况下,数据索引的查询效率为二分法查询效率,趋近于log2(N)
9、B+树索引和哈希索引的区别?
To:
B+树是一个平衡的多叉树,从根节点到每个叶子节点的高度差值不超过1,而且同层级的节点间有指针相互链接,是有序的
哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需要一次哈希算法即可,是无序的
10、哈希索引的优势是什么?
To:
等级查询,哈希索引具有绝对优势(前提是:没有大量重复键值,如果大量重复键值时,哈希索引的效率很低,因为存在所谓的哈希碰撞问题)
11、哈希索引不适用的场景有哪些?
To:
1、不支持范围查询
2、不支持索引完成排序
3、不支持联合索引的最左前缀匹配规则
通常,B+树索引结构适用于绝大多数的场景,像下面这种场景用哈希索引才更有优势:
如果存储的数据重复度很低(也就是说基数很大),对该列数据以等值查询为主,没有范围查询、没有排序的时候,特别适合采用哈希索引
12、B树和B+树的区别是什么?
To:
B树,每个节点都存储key和data,所有节点组成这棵树,并且叶子节点指针为null,叶子节点不包含任何关键字信息
B+树,所有的叶子节点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子节点本身依关键字的大小自小而大的顺序链接,所有的非终端节点可以看成是索引部分
13、什么情况下应不建或者少建索引?
To:
1、表记录太少
2、经常插入、删除、修改的表
3、数据重复且分布平均的表字段
4、经常和主字段一块查询但主字段索引值比较多的表字段
14、什么是表分区?
To:
表分区,是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理的部分.从逻辑上看,只有一张表,但是底层却是由多个物理分区组成
15、MySql四种隔离级别是什么?
To:
1、串行化:可避免脏读、不可重复读、幻读的发生
2、可重复读:可避免脏读、不可重复读的发生
3、读已提交:可避免脏读的发生
4、读未提交:最低级别,任何情况都无法保证
16、MySQL的行级锁定的优点是什么?
To:
1、当在许多线程中访问不同的行时只存在少量锁定冲突
2、回滚时只有少量的更改
3、可以长时间锁定单一的行
17、MySQL的行级锁定的缺点是什么?
To:
1、比页级或表级锁定占用更多的内存
2、当在表的大部分中使用时,比页级或者表级锁定速度慢,因为你必须获取更多的锁
3、如果你在大部分数据上经常进行GROUP BY操作或者必须经常扫描整个表,比其它锁定明显慢很多
4、用高级别锁定,通过支持不同的类型锁定,你可以很容易地调节应用程序,因为其锁成本小于行级锁定
18、MySQL的优化方式?
To:
1、开启查询缓存,优化查询
2、当只要一行数据时使用limit 1
3、为搜索字段建索引
4、垂直分表
19、MySQL的水平分表和垂直分表的区别是什么?
To:
1、水平分表:比如(QQ的登录表。假设QQ的用户有100亿,如果只有一张表,每个用户登录的时候数据库都要从这100亿中查找,会很慢很慢。如果将这一张表分成100份,每张表有1亿条,就小了很多)这就是水平分表
2、垂直分表:表的记录并不多,但是字段却很长,表占用空间很大,检索表的时候需要执行大量的IO,严重降低了性能。这时需要把大的字段拆分到另一个表,并且该表与原表是一对一的关系。
20、java中如何解决哈希冲突?
To:
1、再哈希发:又叫双哈希法,有多个不同的hash函数,出现冲突后采用其他的哈希函数计算,直到不再冲突为止
2、拉链法:又叫链地址法,将具有相同哈希地址的记录链成一个单链表,m个哈希地址就设m个单链表,然后用一个数组将m个单链表的表头指针存储起来,形成一个动态的结构
(拉链法优点:
1、拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短
2、由于拉链法中各链表上的节点空间是动态申请的,故它更适合于造表前无法确定表长的情况)
21、spring security的认证流程是怎么样的?
To:
1、用户发起表单登陆请求,首先进入UsernamePasswordAuthenticationFilter,在UsernamePasswordAuthenticationFilter中根据用户输入的用户名、密码构建了UsernamePasswordAuthenticationToken 并将其交给AuthenticationManager来进行认证处理
2、接着跳转到ProviderManager,该类是AuthenticationManager的实现类
3、AuthenticationManager跳转到AbstractUserDetailsAuthenticationProvider来进行处理
4、再次调用UserDetailsService类里面的UserDetails方法,将我们的用户存入UserDetails,最后进行Authentication认证
22、使用JWT认证原因是什么?
To:
支持用户通过用户名和密码登录,登录后通过http header返回token,每次请求,客户端需要通过header将token带回,用于权限校验;服务端负责token的定时刷新
23、spring中bean的生命周期?
To:
1、spring容器从XML文件中读取bean的定义,并实例化bean
2、spring根据bean的定义填充所有的属性
3、如果bean实现了BeanNameAware接口,Spring传递bean的ID到setBeanName方法
4、如果bean实现了BeanFactoryAware接口,Spring传递beanfactory给setBeanFactory方法
5、如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法调用它们
6、如果bean实现IntializingBean了,调用它的afterPropertySet方法,如果bean声明了初始化方法,调用此初始化方法
7、如果有BeanPostProcessors和bean关联,这些bean的postProcessAfterInitialization()方法将被调用
8、如果bean实现了DisposableBean,它将调用destroy()方法
24、spring事务管理的方式有几种?
To:
1、编程式事物:在代码中硬编码
2、声明式事物额:在配置文件中配置,分为基于XML的声明式事物和基于注解的声明式事物
25、spring事物中的隔离级别有哪几种?事物特性有哪几种?
To:
事物特性(4种):
1、原子性:强调事物的不可分割
2、一致性:事物的执行的前后数据的完整性保持一致
3、隔离性:一个事物执行的过程中,不应该受到其他事物的干扰
4、持久性:事物一旦结束,数据就持久到数据库
事物的隔离级别(5种):
1、default默认的隔离级别,使用数据库默认的事物隔离级别(可重复读)
2、未提交读:脏读,不可重复读,虚读都有可能发生
3、已提交读:避免脏读.但是不可重复读和虚读有可能发生
4、可重复读:避免脏读和不可重复读,但是虚读有可能发生
5、串行化的:避免以上所有读问题
26、Redis中两种持久化机制是什么?
To:
RDB和AOF
RDB机制:RDB其实就是把数据以快照的形式保存在磁盘上;RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘.也是默认的持久化方式,这种方式是将内存中数据以快照的方式写入到二进制文件中.
它的触发机制为:
1、save触发方式:该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止
2、bgsave触发方式:执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求
3、自动触发:自动触发是由我们的配置文件来完成的
RDB的优势和劣势:
优势:
(1)、RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复
(2)、RDB在恢复大数据集时的速度比AOF的恢复速度要快
劣势:
可能会丢失数据(因为它存储的是内存数据的二进制序列化形式,存储上非常紧凑)
AOF机制:redis会将每一个收到的写命令都通过write函数追加到文件中(简称日志记录)
它的触发机制为:
1、每修改同步always:同步持久化每次发生数据变更会被立即记录到磁盘,性能较差,但数据完整性比较好
2、每秒同步eversec:异步操作,每秒记录,如果一秒内宕机,有数据丢失
3、不通no: 从不同步
AOF的优势和劣势:
优势:
(1)、AOF可以更好的保护数据不丢失
(2)、AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损
(3)、AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写
劣势:
(1)、对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大
(2)、出现bug,进行数据恢复,没有恢复出一摸一样的数据出来
总结:
RDB:在指定的时间间隔能对你的数据进行快照存储
AOF:记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据
27、为什么非主键索引结构叶子节点存储的是主键值?
To:
一是保证一致性,更新数据的时候只需要更新主键索引树,二是节省存储空间
28、为什么推荐使用整型的自增主键?
To:
一是方便查找比较,二是新增数据的时候只需要在最后加入,不会大规模调整树结构,如果是UUID的话,大小不好比较,新增的时候也极有可能在中间插入数据,会导致树结构大规模调整,造成插入数据变慢
29、索引引擎InnoDB的索引结构是什么?
To:
有两个索引结构:主键ID索引和普通索引.主键索引的叶子节点存储的是行数据的内容,普通索引的叶子节点存储的是主键的值
主键索引和普通索引的区别在于,主键索引查询语句的时候,只需要一次主键索引树的查找记录行即可返回数据行;普通索引查找时需要查找两个索引树的结构,先查找记录的主键值,然后再根据主键索引查找对应的记录行返回数据
30、最左前缀匹配规则是什么?
To:
在MySQL建立联合索引时会遵守最左前缀匹配原则,即最左优先,在检索数据时从联合索引(联合索引就是可以以一定顺序引用多列)的最左边开始匹配
由于索引的底层是一颗B+树,那么联合索引的底层也是一颗B+树,只不过联合索引的B+树节点中存储的是键值.由于构建一颗B+树只能根据一个值来确定索引关系,所以数据库依赖联合索引最左的字段来构建
31、如何将spring bean默认的单例变成多例?
To:
在bean上的scope属性值定为prototype
32、Spring注解@Resource和@Autowired区别对比是什么?
To:
@Autowired注解是按照类型(byType)装配依赖对象;@Resource默认是按照byName自动注入
@Resource装配顺序:
1⃣️:如果同时指定了name和type,则从spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
2⃣️:如果指定了name,则从上下文中查找名称匹配的bean进行装配,找不到则抛出异常
3⃣️:如果指定了type,则从上下文中找到类似匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常
4⃣️:如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配
33、如何保证消息不被重复消费?(如何保证消息消费时的幂等性)
To:
如果你拿个数据要写库,你先根据主键查一下,如果这个数据都有了,就别插入,就update一下
如果你拿到这个消息做Redis的Set的操作,无论set几次,结果都一样,set操作本就算是幂等性
如果都不是上面这两种,那就准备一个第三方介质,来做消费记录.以Redis为例,需要让生产者发送每条数据的时候,里面加上一个全局唯一的id,只要消费过该消息,就将id和消息数据写入redis,消费者开始消费前,先根据这个id去查redis中有没有消费记录,消费过了,就别处理,保证别重复处理相同的消息即可
34、Spring AOP代理是什么?
To:
SPring Aop默认为AOP代理使用标准的JDK动态代理.这使得任何接口可以被代理.Spring AOP也可以使用CGLIB代理,如果业务对象没有实现任何接口,那么默认使用CGLIB
AOP(面向切面编程)主要的实现技术有Spring AOP和AspectJ
AspectJ的底层技术就是静态代理,用一种AspectJ支持的特定语言编写切面,通过一个命令来编译,生成一个新的代理类,该代理类增强了业务类,这是在编译时增强
JDK动态代理模式只能代理接口而不能代理类
35、mysql一级缓存存在哪里,Mysql中一级缓存二级缓存区别?
To:
一级缓存:也被称为本地缓存,一级缓存一直是开启的;与数据库同一次会话期间查询到的数据会放在本地缓存中,如果需要获取相同的数据,直接从缓存中获取,不会再查数据库
二级缓存:也被称为全局缓存,基于namespace级别的缓存,一个namespace对应一个二级缓存
工作机制: 1、一个会话,查询一条数据,这个数据会被放在当前会话的一级缓存只中
2、如果会话关闭了,一级缓存中的数据会被保存带到二级缓存.新的会话查询信息就会参照二级缓存
36、Redis常见的数据结构以及使用场景是什么?
To:
1、String:String数据结构时简单的key-value类型,value其实不仅可以是String,也可以是数字.常规key-value缓存应用
2、Hash:Hash是一个String类型的field和value的映射表,hash特别适合用于存储对象,后续操作的时候,可以直接仅仅修改这个对象中的某个字段的值,比如我们可以Hash数据结构用来存储用户信息,商品信息等等
3、List:List就是链表,Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如微博的关注列表,粉丝列表,消息列表等功能都可以用Redis的list结构来实现
4、Set:Set对外提供的功能与list类似一个列表的功能,特殊之处在于set是可以自动排重的
5、Sorted Set:和set相比,sorted set增加了一个权重参数score,使得集合中的元素能够按照score进行有序排列
37、Redis 如何保证缓存与数据库双写时的数据一致性?
To:
解决方式:
1、如果是强一致性,读请求和写请求串行化,串到一个内存队列里面去,这样就保证一定不会出现不一致的情况(效率极低)
2、先更新数据库,再删除缓存(可能会暂时产生不一致的情况,但是发生的几率特别小);解决方案,首先给缓存设置有效时间是一个方案.其次,采用异步延时删除策略,保证读请求完成之后,再进行删除操作
38、SpringClound和Dubbo有哪些区别?
To:
dubbo是二进制传输,占用带宽少一点.SpringClound是http传输,带宽会多一点,同时使用http协议一般会使用JSON报文,消耗会更大
dubbp开发难度较大,所依赖的jar包有很多问题大型工程无法解决.SpringClound对第三方的继承可以一键式生成,天然集成
SpringClound接口协议约定比较松散,需要强有力的行政措施来限制接口无序升级
最大的区别:
SpringClound抛弃了Dubbo的RPC通信,采用的是基于HTTP和REST方式
39、SpringBoot和SpringClound之间的关系?
To:
SpringBoot专注于快速方便的开发单个个体微服务;SpringClound关注全局的微服务协调治理框架,将SpringBoot开发的一个个单体微服务组合并管理起来
SpringBoot可以离开SpringClound独立使用,但是SpringClound不可以离开SpringBoot,属于依赖关系.
40、什么是熔断?什么是服务降级?
To:
服务熔断的作用类似于家用的保险丝,当服务出现不可用或者响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用
服务降级时从整个系统的负荷情况出发和考虑的,对某些负荷会比较高的情况,为了防止某些功能出现负荷过载或者响应慢的情况,在其内部暂时舍弃对一些非核心的接口和数据的请求,而直接返回一个提前准备好的fallback错误处理信息.这样,虽然提供的是一个有损的服务,但是却保证了整个系统的稳定性和可用性
41、eureka和zookeeper的区别是什么?
To:
zookeeper是CP原则,强一致性和分区容错性
eureka是AP原则,可用性和分区容错性
zookeeper当主节点故障时,zk会在剩余节点重新选择主节点,耗时过长,虽然最终能够恢复,但是选取主节点期间会导致服务不可用,这是不能容忍的
eureka各个节点时平等的,一个节点挂掉,其他节点仍会正常保证服务
42、什么情况下索引会失效?
To:
1、如果条件中有or会导致索引失效
2、like查询是以%开头
43、为什么Redis是单线程的?
To:
因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络宽带.Redis线程是安全的
44、Redis单线程为什么还能那么快?
To:
因为Redis是基于内存的,内存的读写速度非常快;Redis是单线程的,避免了不必要的上下文切换和竞争条件;Redis使用多路复用技术,可以处理并发的连接.
45、Hystrix的使用方式?
To:
Hystrix翻译过来就是“豪猪”的意思.它的设计目的:
1⃣️:通过第三方客户端的库来访问依赖服务时的潜在故障提供保护和控制
2⃣️:防止在复杂分布式系统中出现级联故障
3⃣️:快速失败和迅速恢复
4⃣️:在允许的情况下,提供退路对服务进行优雅降级
5⃣️:提供近实时的监控、报警和操作控制
使用方式:
现在pom文件引入依赖;再修改启动类,在启动类上加伤@EnableCircuitBreaker注解,也可以直接使用@SpringCloundApplication注解来代替@SpringBootApplication(或者@EnableEurekaServer)、@EnableDiscoveryClient、@EnableCircuitBreaker这三个注解。在进行修改Controlle,在方法上面增加断路器功能(注解 @HystrixCommand(fallbackMethod = “getMsgFallback”)fallbackMethod(退回的方法名)
)
Feign结合Hystrix:通过配置@FeignClient注解的fallback属性来指定fallback处理类
修改yml配置,Feign默认是关闭Hystrix的支持的
46、JWT的token是怎么解析的?
To:
获取token之后,使用jwts.parse的climes方法进行解析,因为解析数据存放在climes里面,从climes里面或取数据即可
47、如何让用sql语句实现乐观锁和悲观锁?
To:
乐观锁实现:
select (value, version) from task where id = #{id}
update task set value = new value,version=versionValue+1 where id=#{id} and version=versionValue
悲观锁实现:
start transaction;//开启事物(手动)
select status from t_goods where id = 1 for update;
insert into t_orders(id,goods_id)values(null,i);
update t_goods set status=2;
commit;//提交事物
48、spring的五种通知类型是什么,使用场景是什么?
To:
前置通知:记录日志(方法将被调用)
环绕通知:控制事物,权限控制
后置通知:记录日志(方法已经成功调用)
异常通知:异常处理,控制事务
最终通知:记录日志(方法已经调用,但不一定成功)
49、springAop的jdk代理和cglib的代理是怎么选择的?
To:
默认使用JDK动态代理,这样便可以代理所有的接口类型;如果被代理对象没有实现任何接口,就默认的是使用CGLIB代理.如果需要强制使用CGLIB,就指定proxy-target-class=“true”或者基于注解@EnableAspectJAutoProxy(proxyTargetClass=true)
50、Feign的原理是什么?
To:
Feign远程调用,核心就是通过一系列的封装和处理,将以JAVA注解的方式定义的远程调用API接口,最终转换成HTTP的请求形式,然后将HTTP的请求的响应结果,解码成JAVA Bean,返回给调用者.
51、什么是redis的雪崩、穿透和击穿?
To:
雪崩:缓存机器意外发生了全盘宕机.缓存挂了,数据请求全部落数据库,数据库扛不住,它会报警一下,然后就挂了.这就是缓存雪崩
解决方案如下:
事前:redis高可用,主从+哨兵,redis cluster,避免全盘崩溃
事中:本地ehcache缓存+hystrix限流&降级,避免MySQL被打死
事后:redis持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据
穿透:缓存中查不到,每次去数据库里查,也查不到(视缓存于无物)
解决方案如下:
每次系统从数据库中只要没查到,就写一个空值到缓存里去
击穿:就是说某个key非常热点,访问非常频繁,处于集中式高并发访问的情况,当这个key在失效的瞬间,大量的请求就击穿了缓存,直接请求数据库
解决方案如下:
可以将热点数据设置为永不过期;或者基于redis or zookeeper实现互斥锁,等待第一个请求构建完缓存后,在释放锁,进而其它请求才能通过该key访问数据
52、redis的过期策略是什么?
To:
定时删除:redis会将每个设置了过期时间的key放入到一个独立的字典中,以后会定期遍历这个字典来删除到期的key
懒惰删除:所谓懒惰策略就是在客户端访问这个key的时候,redis对key的过期时间进行检查,如果过期了就立即删除,不会给你返回任何东西
53、Spring 如何解决循环依赖的问题?
To:
即2个或以上bean互相持有对方,最终形成闭环,这就是循环依赖
Spring的循环依赖的场景:构造器的循环依赖;setter的循环依赖
如何检测是否有循环依赖?可以Bean在创建的时候给其打个标记,如果递归调用回来发现正在创建中的话,即可说明循环依赖
解决循环依赖如下:使用三级缓存,调整配置文件,将构造函数注入方式改为属性注入方式即可
这三级缓存分别指:
singIetonFactories:单例对象工厂的cache
earlySingletonObjects:提前曝光的单例对象的Cache
singLetonObjects:单例对象的cache
54、Spring事务失效的原因有哪些?
To:
数据库引擎不支持事务、没有被Spring管理、方法不是public、自身调用、异常被吃、异常抛出类型不对
55、Spring Bean的作用域:
singleton:在Spring Ioc容器中仅存在一个Bean实例,Bean以单例方式存在
prototype:每次从容器中调用Bean时,都返回一个新的实例
request:每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境
session:同一个HTTP Session共享一个Bean,不同Session使用不同Bean,仅适用于WebApplicationContext环境
56、synchronized 和Lock区别?
To:
synchronized存在jvm层面上,lock是一个类; synchronized性能少量同步,lock大量同步; synchronized锁状态无法判断,lock可以判断
57、什么是SQL注入?
To:
SQL注入是通过把SQL命令插入到web表单提交或通过页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL指令。
58、mybatis中的#{} 为什么能防止sql注入,${}不能防止sql注入?
To:
#{}在mybatis中的底层是运用了PreparedStatement 预编译,传入的参数会以 ? 形式显示,因为sql的输入只有在sql编译的时候起作用,当sql预编译完后,传入的参数就仅仅是参数,不会参与sql语句的生成,而${}则没有使用预编译,传入的参数直接和sql
进行拼接,由此会产生sql注入的漏洞。
59、redis的缺点是什么?
To:
是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
60、父类的静态方法能否被子类重写?
To:
不能,因为重写的定义是重写父类的虚函数,虚函数式动态绑定的,而静态方法是静态绑定的,所以静态必然不是虚函数,就不存在重写之说了
61、mysql行锁和表锁的区别是什么?
To:
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;
62、JVM加载class文件的原理机制是什么?
To:
JVM中的类装载是由类加载器(类加载器包括:根加载器、扩展加载器、系统加载器和用户自定义加载器)和它的子类来实现的.当java程序需要使用某个类时,JVM会确保这个类已经被加载、连接和初始化.类的加载是指把.class文件中的数据读入到内存中,通常创建一个字节数组读入.class文件,然后产生与所加载对应的class对象.加载完成后,class对象还不完整,所以此时的类还不能用.当类加载后进入连接阶段,这一阶段包括验证、准备和解析三个步骤,最后JVM对类进行初始化.
63、Java对象创建过程
To:
1、JVM遇到一个新建的对象时,首先会先去常量池中检查是否有该定义的符号引用.然后加载这个类
2、然后再给对象分配空间
3、将空间初始化为0
4、对对象头进行必要的设置
64、类的生命周期
To:
加载----->连接---->初始化----->使用----->卸载
65、spring boot的启动原理?
To:
springBoot整个启动流程分为两个步骤:初始化一个springApplication、执行该对象的run方法.
1、springBoot初始化,通过springFactoriesLoader找到spring.factories文件中配置的ApplicationContextInitializer和ApplicationListener两个接口的实现类名称,以便后期构建相应的实例
2、springBoot启动流程都封装在springApplication.run方法中,本质上其实就是在spring的基础之上做了封装,做了大量的扩张.通过springFactoriesLoader查找并加载所有的SpringApplicationRunListeners,通过调用starting()方法通知所有的SpringApplicationRunListeners;应用开始启动.
3、创建ApplicationContext容器
4、初始化ApplicationContext容器
5、调用ApplicationContext的refresh()方法,刷新容器
66、MySQL 的索引实现原理是------->聚簇索引与非聚簇索引(区别)
To:
聚簇索引和数据是一起以idb文件的形式进行存储的,非聚簇索引和数据是分开存储的;在访问速度上,聚簇索引比非聚簇索引快;非聚簇索引需要查询一遍索引文件,得到索引,根据索引获取数据,而聚簇索引的索引树的叶子节点的直接指向要查找的数据行
67、spring的ioc和aop的原理
To:
Ioc(控制反转):把创建对象交给Spring进行配置
通过Spring配置来创建对象,而不是new的方式,底层原理:xml配置文件、dom4j解析、工厂设计模式、Class.forName反射
DI(依赖注入):向类里面的属性中设置值
两者的关系:DI不能单独存在,要在Ioc基础上来完成操作,即要先创建对象才能注入属性值
AOP(面向切面):面向切面,扩展功能时不通过源代码,横向抽取机制.
底层使用动态代理方式----增强方法
具体分两种情况:
1):有接口的情况:创建接口的实现类的代理对象,jdk动态代理
2):没有接口的情况:创建User类的子类的代理对象,cglib动态代理,子类可以通过super的方法调用父类方法
68、redis分布式锁原理
To :
分布式锁,是控制分布式系统之间同步访问共享资源的一种方式.在分布式系统中,常常需要协调他们的动作.如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要互斥来防止彼此干扰来保证一致性.
69、深拷贝和浅拷贝的区别
To:
欠拷贝只复制指向某个对象的指针,而不是复制对象本身,新旧对象还是共享同一块内存;深拷贝会另外创建一个一摸一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象