MySQL八股文
问:Mysql的存储引擎有理解过吗?
我比较了解就是 Innodb,myisam,Memory。
Innodb:现在的mysql默认存储引擎就是innodb,主要就是因为它是唯一一个支持事务的存储引擎,支持表级锁和行级锁,其索引的底层结构使用的是B+树,在数据,索引,表结构都存储到.idb中。
Myisam:其不支持事务,仅支持表级锁,其索引的底层结构为B+树,表结构存储到.sdi中,索引存储到.myi,数据存储到.myd中。
Memory:基础内存进行存储的,主要就是用sdi存储表结构。
问:如何定位慢查询?
在我们的项目中,在上线时使用skywalking来定位慢的查询,如果发现是某个SQL执行速度慢,我们就可以使用skywalking的追踪功能,来确定SQL语句。
而在测试环境中,我们使用MySQL提供的慢日志来确定慢查询的位置。mysql是默认没有开启慢日志的,需要通过配置文件开启并设置快查询的最大时间,超过这个时间就认为其为慢查询,我们就可以在慢日志中找到慢查询的sql,在我们的项目中设置最大的时间为2秒。
-
#开启慢日志
-
slow_query_log=1
-
#设置快查询的最大时间
-
long_query_time=2
问:一个SQL语句执行很慢,应该如何分析呢?
我们可以借助Mysql提供的关键值 explain来展示出某个SQL语句的状态。
在该状态中包含属性 key和key_lenSQL中使用到的索引,如果提供我们的索引出现失效的情况就可以修改和SQL和添加索引。属性type表示SQL的性能,通常其值为const,提供type判断是否存在全索引扫描或全盘扫描。属性extra表示建议属性,提供该属性判断是否出现回表的情况。
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记【点击此处即可】免费获取
问:有了解过索引吗?
1.索引是帮助Mysql高效查询数据的数据结构。
2.索引提高检索效率,大大降低IO成本。
3.通过索引列对数据排序,大大降低了排序的成本。
问:B+树和B树的区别?
- B+树作将数据存放在叶子节点上,非叶子节点就可以组织更宽的结构,就会变的更矮更胖,提高查询速度。
- B+树中叶子节点使用双向链表进行存储的,并且按顺序进行存储的,不同于B树,查询范围数据的时候进行多次的从根节点进行查询,而B+树在查询范围数据的时候只需要从根节点查询一次即可。且排序的性能更好。(B+树在做范围查询的时候只需要从根节点遍历一次,二B树则需要遍历对应数量的个数)
问:什么是聚簇索引和非聚簇索引?
聚簇索引:索引结构和数据是存放在一起的,也就是在B+树的叶子节点中存放整行的数据。
非聚簇索引(也叫二级索引):索引结构和数据不是存放在一起的,也就是在B+树的叶子节点上存放对应的主键且是不唯一的。我们为字段添加索引通常就是二级索引。
问:知道什么是回表操作吗?
通过二级索引查到的主键再去聚簇索引中查询数据行的过程就是回表。而直接查询聚簇索引则不会出现回表的情况。
问:有了过覆盖索引吗?
查询数据通过索引进行查询,返回列都可以在索引的数据中找到(包含在其中),就是覆盖查询。
使用id主键进行查询就是覆盖索引查询,因为聚簇索引的数据中包含id主键,性能高。
在做查询的时候如果返回列吧全部存在于索引中就会回表查询,所以尽量避免使用select *。
问:Mysql超大分页查询怎么进行优化?
Mysql做limit分页查询的时候,需要做排序,这个过程非常耗时。
优化方案:覆盖索引 + 子查询。先通过子查询出分页排序完后的id主键,因为是主键所以会直接进行覆盖索引查询。通过子查询的id关联表中的id查询出分页后的数据。
-
select * from table t
-
(select id from table limit 0 10 order by id) s
-
where t.id = s.id
问:索引的创建原则有哪些?
1.数据量大于十万且查询的频率表较高的表我们才会考虑创建索引。
2.如果一个表需要添加索引,我们应该选择作为查询字段,排序字段,分组字段的字段作为索引,且字段的区分度要高。
3.在添加索引的时候都使用复合索引来创建,尽量使用覆盖查询,降低回表的概率。
4.如果需要对长字符串添加索引我们可以使用前缀索引。
5.控制索引的数量,并不是越多越快,在增删改的时候我们也需要消耗时间来维护索引。
问:什么情况下索引会失效?
复合索引
1.在使用复合索引的时候不遵循最左前缀法则。在做条件查询的时候跳跃某一列字段导致索引失效。
2.在条件查询中的范围查询的右遍的列不能使用索引,使用也会失效。(如果三个都有效的话 key_len应该为六百多,说明此时address字段失效)
3.不能在索引列进行运算操作,这会导致索引失效。
4.在条件查询的时候如果没有加单引号也会导致索引失效。(就比如:0和'0',会进行类型转换,导致索引失效)
5. 在模糊查询的时候,如果字符串中是以%开头的就会导致索引失效。(就比如: "%abc")
在我遇到的随影失效问题就是没有遵循最左前缀原则,只要实在测试的时候通过explain查询SQL语句的执行状态来判断的。
问:谈谈你对SQL的优化经验?
在做SQL优化的时候主要从:建表时,使用索引时,sql语句编写,主从复制,读写分离的方面进行考虑,当数据量过大的时候考虑使用分库分表。
问:创建表的时候你是怎么优化的?
我们主要遵循阿里的开发手册,就比如在使用整数类型的时候就考虑使用:tinyInt,Int,bigInt,如果是逻辑字段就使用tinyInt,在使用字符串是考虑使用:char,varchar,text。
问:那在使用索引的时候如何进行优化?
讲出索引失效的五种情况,再使用SQL的时候避免使用select *,使用覆盖索引减少回表的操作。
问:你平时SQL语句是怎么优化的?
select 指明字段,不要使用select * from防止回表的操作。在使用聚合查询的时候尽量使用union all而不是union,union会多一次过滤,在效率上比较低。使用inner join 而不使用 left join/right join,如果必须使用的,一定要以小表为驱动。
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记【点击此处即可】免费获取
问:事务的特性是什么?可以详细说一下?
这里你可以取钱的例子来引导模式官。
原子性:在事务中的语句要么都成功要么都失败。
一致性:在事务中数据的总量不会变。
持久性: 提交和会滚的数据都会持久化到数据库。
隔离性:事务中间是是相互隔离的,是不会相互影响的。
问:并发事务带来了哪些问题?
并发事务可能会出现三种问题。
1.脏读:事务1读取到事务2未提交的数据。
2.不可重复读:事务2先后读取事务1中的某合个数据,两次的结果不一样。
3.幻读:一个事务在按条件查询数据时没有查到数据吗,但是插入操作时,又发现该数据已经存在。因为其他事务在这个过程中插入数据(选答)
怎么解决解决这些问题?
通过设置过隔离级别来解决。隔离级别包括:
1.读取未提交,无法解决并发事务带来的问题。
2.读取已提交,可以解决脏读。
3.可重复读,可以解决脏读,不可重复读。
4.串行化,事务只能一个一个执行,可以解决脏读,不可重复读,幻读,隔离级别最高,效率最低。
MySQL默认的隔离级别是什么?
Mysql默认使用的隔离级别是:可重复读。
问:undo log和rado log有什么区别?
redo log:用于记录数据页的物理变化,当服务宕机的时候进行数据同步操作。保证了事务的持久性。
undo log:记录逻辑日志,就比如:当做插入操作时会在日志中记录逆向的操作也即是删除,在事务回滚的时候会执行逻辑日志中的指令。保证了事务的持久性和原子性。
问:隔离级别是怎么实现的?
排他锁+MVCC实现的。
问:说说你对MVCC的理解吧?
多版本并发控制。维护一个数据的多个版本,使得读写操作没有冲突。
mvcc主要有三个重点:
1.隐藏字段:trx_id(事务id):记录当前事务的id,其为自增的。 roll-pointer:指向上一个版本的事务记录地址。
2.undo log:回滚日志,存储老版本的数据,版本链:多个同时修改某条记录,产生多版本的数据,通过rool-pointer指针形成链表。
3.readview:解决一个事务查询选择版本的问题。
根据readView的匹配规则和当前事务id找到对应的版本信息。(问规则时答:1.判断是事务id是否为当前事务的id。2.是否是活跃事务id。3.判断事务是否是在readview创建后开启的,也就是事务id大于当前事务。4.判断事务中的数据是否已提交,事务id小于最小的事务id。)
不同的隔离级别快照读是不一样的,最终的访问结果也是不一样的。(问时答:当前读:读取的是最新的数据并且会加锁。快照读:读取的是记录数据的可见版本,不会加锁。)
读已提交:在每次快照读的时候都会生成readview。
可重复读:在有在第一次快照读的时候才会生成readview,后续的快照读都是使用该readview的复制,保证数据的一致性。
问:隔离级别中可重复读有什么缺点呢?
1.无法解决幻读的问题,当我们事务去读取一定范围的数据,且在该过程中其他的事务修改了该范围的数据,此时两次读取就会出现查询结果不一致的情况,最终导致幻读。
2.无法读取到最新的数据,因为可重复读在每次读取的时候都使用同一个readView,且readView并非当前最新的数据,最终导致无法读取到新的数据。
问:MySQL的主从同步有了解过吗?
Mysql主从同步的核心就是bin log(二进制日志),这个日志中主要记录 DDL(表的操作),DML(表中数据的操作)。
1.master中事务提交数据后,会将修改的数据保存到bin log中。
2.slave有个iothread线程会监控的bin log的变化,并将变化写入relay log中。
3.slave有个SQLthread线程会监控relay log,将改变的数据写入slave中。
问:你在项目中有使用过分库分表吗?
在物流项目中的订单服务的数据非常庞大,请求数多且业务累计大。差不多单表的数据有100w条,这时我们就使用分库分表。
分库分表有四种策略:
1.水平分库:通过将一个库中的数据拆分到多个库中,解决海量数据存储和高并发的问题。主要通过sharing-sphere和mtycat实现。
2.水平分表:解决单表存储和性能的问题。
3.垂直分库:根据业务来拆分库中的表,在高并发的情况下提高磁盘IO和网络连接数。每个微服务都有自己的表。
4.垂直分表:冷热数据分离,多表不会相互影响。就比如:表中字段为id,name,des,将id,name和des分离,id和name都是热数据而des为冷数据,访问频率较低。
框架八股文
问:Spring中的设计模式有哪些?
我们目前主要了解的就是工厂模式,代理模式,单例模式,策略模式,责任链模式。
工厂模式:常见的工厂模式主要就是BeanFactory(延迟注入)和ApplicationContext(完全注入),我们无需知道类如何创建,直接从工厂中获取即可。
单例模式:ioc默认情况下就是一个单例模式,每次获取相同恶的类的时候,获取的对象是同一个。不会就行多次的创建。单例模式还分为饿汉式(主动创建单例)及懒汉式(需要时再创建单例)。
代理模式 :aop就是采用代理模式来实现的。当要代理的对象实现接口的时候,我们就会使用JDK Proxy来生成代理对象。如果代理的对象没有实现接口的话,我们就回使用CGLIB生成一个被代理对象的子类作为代理对象。
策略模式:在我们编写项目的时候就有使用到策略模式,因为我要控制分布式锁的失败策略,我们会在枚举类编写一个抽象方法,编写多个内部方法去重新该方法,不同的内部方法就是不同的策略。
责任链模式:stram流就是使用该模式的,按照对应的顺序去执行方法,并向下传递对象。起到解耦合的作用。
问:spring框架的单例bean是线程安全的吗?
在spring框架中有个注解叫@Scope可以设置bean的状态,默认就是singleton也就是单例。
bean进行注入的时都是无状态的,其不会被修改的。所以没有线程安全的问题。但是如果bean中有成员变量时就可能会有线程安全的问题,因为该成员变量可能会被多个线程修改,为了解决这个问题我们可以加锁或将bean设置为多例。(@Scope设置为prototype)
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记【点击此处即可】免费获取
问:什么是AOP?
面向切面编程,将那些于业务无关的复用性比较高的代码快抽取出来,较低代码的耦合度。
问:在你的项目中有使用过AOP吗?
在我的云盘项目中就使用到AOP,在记录日志的时候,我创建有个自定义注解,aop的切面就是这个注解,使用环绕通知在方法中,我们通过传入的参数(joinPoint)获取对应的类和方法,从而获取前端传来的参数和其他主要信息,实现记录日志的效果。
问:Spring中的事务是怎么实现的?
本质就是通过AOP实现的,通过环绕通知对应方法进行前后拦截,在方法执行前开启事务,在执行后提交事务,会对此过程进行try/catch,如果报错直接回滚。(就是@transactional)
问:spring中事务失效场景有哪些?
1.在出现异常后,方法中try/catch了该异常并且没有主动抛出异常,这时候就会导致事务失效。解决方法:在方法try/catch异常后手动的抛出异常。(就会导致事务不知道出现异常了)
2.抛出检查异常时会导致事务失效,spring中的事务只会对runtime异常进行回滚。就比如:Not found Exception就是检查异常。解决方法:在@transactional中设置属性 rollbackFor = Exception.class。使得事务会对所有的异常进行回滚。
3.非public方法会导致事务失效。解决方法:将方法的作用域该为public。
4.在非事务方法中调用了事务的方法,此时就会导致事务失效。(就比如某给没有加事务注解的方法调用了加了事务注解的方法)
5.回滚异常类型不匹配。(我们可能会设置需要进行回滚的异常,就是rollback的值,如果抛出的异常类型不匹配就会导致事务失效)
6.事务的传播行为错误。(就比如在事务方法中调用了其他的事务方法,初始化如果其他的时候方法设置开启新事务的话,在其事务成功后,就不会参与外部事务的回滚操作)
问:事务的传播性有哪些?
主要就是三个:Propagation_Required,Propagation_Required_new,Propagation_nested。
- Propagation_Required:如果B为A的子方法,并且都为该传播类型,那么它们都会在同一个事务中。如果主方法中没有开启事务的话就会开启新事务。
- Propagation_Required_new:如果B为A子方法,B会创建一个独立的事务,B不会受A事务的影响。
- Propagation_nested:如果B为A子方法,B会创建一个事务内嵌到A的事务中,如果A中没有事务的话,就单独开启一个事务。
问:@Transactional的原理有了解过嘛?
事务注解是基于AOP来实现的,也就是在执行方法前开启事务,如果try/cath捕获到异常的话就会进行回滚,在方法执行完成后就会进行提交。那AOP实现涉及到动态代理的流程。如果被代理目标对象实现了接口的话,就会使用JDK Proxy生成代理对象。如果代理对象没有实现接口的话,就会使用CGLIB Proxy生成被代理对象的子类作为代理对象。
问:说说CGLIB的执行流程?
问:spring中bean的生命周期有了解过吗?
结构图:
生命周期的流程为下:
1.通过BeanDefinition获取bean的定义信息。
2.通过构造函数创建bean,可以将当前的bean理解为一个空壳。
3.进行依赖注入,对bean中的属性进行赋值。
4.处理Aware接口,也就是一些以Aware结尾的接口,就比如:beanNameAware,beanFactoryAware,applicationContextAware。如果实现了个接口的话,我们需要重写一些方法。
5加载BeanPostProcessor对象,并执行处理器的前置初始化方法(PostProcessorAfterInitiazilation方法)。
6.执行初始化方法,包括 IntializingBean和自定义的初始化方法。
7.加载BeanPostProcessor对象,并执行处理器的后置初始化方法(PostProcessorBeforeInitiazilation方法)。在此后置处理器中我们可以通过aop对原始的bean做增强也就是进行代理,代理就包括 JVM代理和CGLIB代理。
8.将bean进行销毁。
问:说说CGLIB动态代理的执行流程吧?
aop就是采用代理模式来实现的。当要代理的对象实现接口的时候,我们就会使用JDK Proxy来生成代理对象。如果代理的对象没有实现接口的话,我们就回使用CGLIB生成一个被代理对象的子类作为代理对象。
问:有了解过bean的循环依赖吗?
循环依赖也就是循环引用,两个或以上的bean同时相互依赖对方,最终形成闭环。就比如:A依赖B,B依赖A。
spring提供了解决方案:三级缓存。
1.一级缓存:单例池,存储已经初始化完成的单例bean。
2.二级缓存:缓存早期的bean单例对象,就bean只完成到执行构造方法。
3.三级缓存:缓存创建bean的factory,这些factory用于创建代理对象和普通对象。
三级缓存的解决流程(当前问题为A,B相互依赖):
实例化A,并将生成的A的objectFacttory将其存入三级缓存,因为A依赖B,B也会去实例化,创建对应的objectFactory存入三级缓存。
此时B依赖A,就会通过三级缓存中A的objectFactory生成早期A实例,并将该A实例存储到二级缓存中,将这个早期的A注入B中,此时B就创建完成了,将B实例存储到一级缓存中。
将完整的B注入A中,将A实例存储到一级缓存中,并将二级缓存中A的实例删除。
问:构造方法中出现循环依赖怎么办?
在构造函数中如果存在循环依赖我们在函数的参数上添加@Lazy就可以解决循环依赖的问题,保证bean在需要的时候才去加载。
问:可以只使用二级缓存来解决循环依赖吗?
在没有Aop的时候就可以使用一级和三级缓存来解决依赖。但是呢,如果存在aop的问题,那就必须使用三级缓存,因为在二级缓存中可以保证即使存在多个半成品bean的引用时,始终会返回相同的代理对象。避免Bean有多个代理对象。
问:除了使用三级缓存解决循环依赖,还有什么方法吗?
使用@Lazy就行懒加载,就比如A,B相互依赖。但是呢A添加了@Lazy注解,此时会创建一个B的代理对象,而非B对象,会将这个代理对象注入到A中,完成A的创建。之后会做B的初始化和实例化,会将创建好的A注入到B,最终完成B的创建。
问:SpringMVC的执行流程有了解过吗?
jsp版本:
1.用户发送请求到DispatchServlet。
2.dispatchServlet调用处理器映射器HandlerMappering,处理器就会去Controller中找到对应的方法通过映射的路径,然后将处理器执行链返回给dispatchServlet。
3.dispatchServlet调用处理器适配器HandlerAdaptor找到对应的处理器,该处理器就会处理对应的参数和处理返回值,最终会返回ModelAndView给DispatchServlet。
4.Dispatch调用ViewResolver视图解析器,并将ModelAndView传入,最终返回View给dispatchServlet,通过View渲染视图。(就比如:JSP)
前后端分离版本:
1.用户发送请求搭配DispatchServlet。
2.DispatchServlet调用处理器映射器HandlerMappering,会去Controller中找到对应的方法,最终处理器返回执行链给DispatchServlet。
3.DispatchServlet会调用处理器适配器HandlerAdaptor找到对应的处理器,该处理器就会处理对应的方法的参数和处理返回值,在方法上添加了@ReponseBody。
4.通过HttpMessageConverter将数据转为Json返回。
问:有了解过springboot的自动装配原理吗?
在启动类上有个注解的叫@SpringbootApplication,在该注解中包含springbootConfiguration表示该类为配置类,还有个注解叫@EnableAutoConfiguration,这个就是实现自动装配的核心注解。
在@EnableAutoConfiguration中使用注解@Import引入了一个自动自动装配的选择器。
该选择器会到jar中的 /META-INF/spring.factories中按照条件加载对应的类,并将该类配置到ioc中。这里面添加的注解就包括:@ConditionOnClass表示当某个类存在时才进行类加载。@ConditionOnMissingBean表示当某个bean不存在的时候才进行类加载。
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记【点击此处即可】免费获取
问:spring中有那些常见的注解?
在Spring中主要注解有:@Componment,@Controller,@Service,@Repository将类配置到ioc中,@AutoWired(根据class),@Qualifier(根据名字)实现依赖注入。@scope设置bean的作用范围。@Configration设置配置类。@ComponetScan主键扫描。@Bean将某个方法的返回值配置到ioc中。@Import将某类导入ioc中。@Before,@After,@Aspecr,@Around,@Pointcut切面编程的注解。
在SpringMVC中就是一些关于请求的注解,@RequestMappering,@ReponseBody,@RestController,已经参数的注解 @RequestParam,@PathViriable,@RequestHeader。
在springboot的注解中就包括:@SpringBootConfiguration,@EnableAutoConfiguration自动装配注解,@ComponentScan之间扫描。
问:能说说你对Mybatis的执行流程的理解吗?
1.读取mybatis-config.xml文件,里面就是数据库的配置和mapper的地址。
2.创建SqlSessionFactory。
3.通过SqlSessionFactory创建对应的SqlSession,就是项目和数据库的会话,SqlSession包含执行sql语句的所有方法。
4.执行操作数据库的接口,Executor执行器,同时负责缓存的维护。
5.在Executor执行器中的MapperStatement对象,当操作数据库的时候会将Java的类型转为数据库的类型,当输出结果的时候会将数据库的类型转为Java的类型。
问:Mybatis支持延迟加载吗?
1.延迟加载就是当需要使用数据的时候才去加载数据,不用数据得时候不会主动加载。
2.Mybatis支持一对一关联对象和一对多关联集合的延迟加载。
3.在mybatis的配置文配置文件中的LazyloadEnabled设置为true就开启了全局延迟加载。
问:Mybatis延迟加载的底层有了解过吗?
1.通过GCLIB的代理实现的。
2.当调用目标函数的时候,会调用拦截器的invoke方法,如果发现目标方法中的值为null,则进行sql查询,在获取数据后通过set设置属性值,在后续调用目标方法时就有值了。
问:有了解过Mybatis的一级缓存和二级缓存吗?
一级缓存:基于PrepetualCache的HashMap的本地缓存,是默认开启的,其作用域就是Session,当Session进行了Close,Flush后该Session中的缓存会被全部清空。
二级缓存:其作用域是namespace和mapper,其默认是不开启的,是基于prepetualCache,hashmap存储的。通过在mybatis的配置文件中设置CacheEnabled设置为true,在对应的mapper中添加标签Cache。
问:Mybtis的二级缓存什么时候会清理?
当某个作用域(一级缓存(session)/二级缓存(namespace))中进行了增删改操作时就会清除掉select中的缓存。
问:Mybtis中#{}和${}的区别?
- #{}主要就是做占位符的替换的,在mybatis中会使用?占位,而${}主要就是做文本替换的。替换${}中的文本。
- #{}数据的替换发生在DBAS之中,而${}数据替换发生在DBAS之外。
- #{}在做数据替换的时候会自动添加'',而${}数据替换的时候不会自动添加''。
- #{}可以防止SQL的注入,而${}不可以。
微服务
问:springCloud的五大主件有了解过吗?
springCloud:
注册中心:Eureka。
远程调用:Feign。
负载均衡:Ribbon。
服务保护:Hystrix。
网关:Gateway。
springCloud alibaba:
注册中心:Nacos。
远程调用:Feign。
负载均衡:Ribbon。
服务保护:Sentinel。
网关:Gateway。
问:服务的注册与发现是什么意思?SpringCloud是如何实现服务的注册和发现的?
在我的项目中使用nacos实现服务的注册与发现。那我就以eureka为例吧。
服务的注册:每一个服务的提供者会将自己的信息注册到eureka中, eureka会储存提供者的信息,包括:服务名,ip,端口等等。
服务的发现:消费者会通过eureka拉取对应的服务列表,服务可能会搭建集群,所以会存在多个服务,这时候消费者会根据负载均衡的算法选择一个服务并进行调用。
服务的监控:服务者会每隔30秒发送心跳,保证自己的健康状态,当注册中心发现某个服务90秒都没有发送心跳,则会将该微服务移除。
问:我看你项目中使用nacos,你能说说nacos和eureka的区别吗?
相同点:
1.都支持服务的注册和发现,整个流程也是非常相似的。
2.都支持服务者向注册中心发送心跳,监控监控状态。
不同点:
1.nacos的注册中心支持自动查询服务者的状态,如果服务者是临时实例时则使用心跳模式,如果服务者是非临时实例时就采用自动检测模式。
2.临时实例如果发现心跳不正常时就会移除对应的服务,而非临时实例即使有异常也不会被移除。
3.nacos的注册中心支持向消费者发送更新后的服务列表,更新更及时。
4.nacos的临时实例使用的AP模式(高可用),eureka页使用AP模式,非临时实例使用CP模式(强一致)。
5.nacos还支持作为配置中心,而eureka则不支持。
问:你们项目中的负载均衡是怎么实现的?
通过Ribbon实现的,在我们feign调用服务时的负载均衡就通过Ribbon实现的。
问:Ribbon的负载均衡策略有哪些?
1.轮询策略。
2.权重策略:按照权重的大小选择服务器,响应的时间越长其权重就越小。
3.随机策略。
4.区域敏感策略:根据消费者区域按照就近原则选择服务器,如果没有区域这个概念,其效果就和轮询策略效果一样。
问:如何自定义负载均衡的策略?
1.通过实现接口IRule设置对应策略并设置到ioc中 ,其的作用域是全局的。
2.通过yml配置文件进行配置,需要指定对应的服务者的名字,其作用域是局部的。
篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记【点击此处即可】免费获取
问:什么是服务的雪崩呢?怎么解决这个问题呢?
服务的雪崩:当某个服务调用失败后,导致后续调用的服务全部失败,造成服务雪崩发生。
解决方案
服务的降级:如果某个服务调用失败后直接返回自定义的降级信息。通过实现Feign接口,并在Feign接口的@FeignClient中设置fallBack为实现类。
服务熔断:可以通过Hytrix或Sentinel实现服务熔断,那我就以Hytrix为例吧,其默认是没有开启的,需要我们在启动类上添加注解@EnableCircuitBreaker进行开启。当调用某个服务10s时,发现有50%以上的调用失败就会触发熔断机制(开启),每隔5秒会放行一个请求去请求服务(半开),当发现服务调用失败了就会继续熔断,如果请求成功则会解除熔断(关闭)。
问:你们微服务是怎么做监控的?
在我们的项目中主要是用Skywalking完成监控的。
Skywalking主要监控监控,服务的状态。特别是在做压力测试的时候就能够找到对应的慢接口,并对接口进行修改。在Skywlaking中还有服务间调用的拓扑图,方便我去理清调用关系。
我们可以在Skywalking中设置警告规则,当我们的项目上线后,发生错误就会向我们设置的管理者发送短信和邮箱信息,保证第一时间进行修改。