1.分布式锁的实现?
- RLock lock = redissonClient.getLock()生成一个锁,调用lock.lock()方法实现加锁,在业务处理完成之后调用lock.unlock();放开锁。
2.Spring cloud 常用组件?以及作用?
- Eureka——服务注册与发现;
- Ribbon——负载均衡配置,均匀的把请求分发到各个服务器上;
- Feign——Feign Client 会在底层根据你的注解,跟你指定的服务建立连接、构造请求、发起请求、获取响应、解析响应,等等;
- Hystrix——熔断机制,避免某一微服务出现错误导致整个项目宕机;
- Gateway——负责网络路由,可以做统一的降级、限流、认证授权、安全,等等;
3.MQ分布式事务实现思路?
- A服务发布事务消息到mq。
- mq持久化存储事务消息。
- A服务本地执行持久化操作。
- mq回调查询事务状态(commit/rollback)。
- commit时B服务执行持久化操作。rollback时mq删除事务消息
4.InnoDb特性?
- InnoDB支持事务和外键。
- InnoDB需要手动指定。
- 清空整个表时,InnoDB是一行一行的删除
- InnoDB支持行锁(某些情况下还是锁整表,如 update table set a=1 where user like '%lee%')
- InnoDB中不保存表的行数,如select count(*) from table时,InnoDB需要扫描一遍整个表来计算有多少行
- InnoDB不支持FULLTEXT类型的索引
5.spring boot常用注解?
- @SpringBootApplication;@Repository;@Service;@RestController;@ResponseBody。
6.spring boot bean生命周期?
- Bean的定义
- Bean的初始化
- Bean的生存期
- Bean的销毁
7.mysql优化?
- 恰当地使用索引
- 对查询进行优化,尽可能避免全表扫描,不返回不需要的列/行。
- 字段冗余,拆分字段,保证单条记录的数据量很小
- 减少SQL中函数运算与其它计算
- 服务器性能优化
8.Redis有哪些数据类型?
- 字符串,链表,哈希,集合,有序集合
9.多线程的使用方式和主要用途?
用途:
- 完成重复性的工作
- 并发执行的运行效果(一个进程多个线程)以实现更复杂的功能
实现方式:
- 继承Thread类,实现Runnable接口。重写run()方法。
10.IOC和AOP是什么?
- IOC:控制反转,依赖注入,在Spring中声明一个类:A,告诉Spring,A需要B
- AOP:面向切面编程,通过预编译方 式和运行期动态代理实现程序功能的统一维护的一种技术,利用AOP可以对业务逻辑 的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高 了开发的效率。
11.线程有哪些状态?
- 新建(NEW):新创建了一个线程对象。
- 可运行(RUNNABLE):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权 。
- 运行(RUNNING):可运行状态(runnable)的线程获得了cpu 时间片(timeslice) ,执行程序代码。
-
阻塞(BLOCKED):阻塞状态是指线程因为某种原因放弃了cpu 使用权,也即让出了cpu timeslice,暂时停止运行。直到线程进入可运行(runnable)状态,才有机会再次获得cpu timeslice 转到运行(running)状态。阻塞的情况分三种:
(一). 等待阻塞:运行(running)的线程执行o.wait()方法,JVM会把该线程放入等待队列(waitting queue)中。
(二). 同步阻塞:运行(running)的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池(lock pool)中。
(三). 其他阻塞:运行(running)的线程执行Thread.sleep(long ms)或t.join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行(runnable)状态。 -
死亡(DEAD):线程run()、main() 方法执行结束,或者因异常退出了run()方法,则该线程结束生命周期。死亡的线程不可再次复生。
12.spring mvc 工作流程?
- 客户端(浏览器)发送请求,直接请求到DispatcherServlet。
- DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler。
- HandlerAdapter会根据Handler来调用真正的处理器来处理请求和执行相对应的业务逻辑。
- 处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是逻辑上的View。
- ViewResolver会根据逻辑View去查找实际的View。
- DispatcherServlet把返回的Model传给View(视图渲染)。
- 把View返回给请求者(浏览器)。
13.如何保证线程安全?
- 限制数据共享。
- 将可变数据类型改为Immutable类型。
- 共享线程安全的可变数据,使用线程安全的数据类型(HashTable、Vector.....)
- 使用synchronized同步代码块,或者用Lock锁
14.MySQL如何确定索引是否生效?
- 在select前标注explain即可,其中key字段中显示的内容就是使用的索引(possible_keys字段显示的只是可能使用的,最终还是看key字段。
15.常用的设计模式?
- 工厂模式、抽象工厂模式、单例模式、建造者模式、原型模式、代理模式等等
16.Spring Boot启动类的常用注解?
- @ComponentScan, 默认扫描@SpringBootApplication所在类的同级目录和它的子目录,注册 bean 实例到容器中。
- @EnableAutoConfiguration,启动自动配置,该注解会使Spring Boot根据项目中配置的依赖,自动配置所需的依赖jar包
- @SpringBootApplication,此注解是一个复合注解,包括@ComponentScan,和@SpringBootConfiguration,@EnableAutoConfiguration
- @EnableFeignClients,用于标注需要跨服务链接的微服务列表
17.集合常见面试题
18.谈谈Redis持久化?
- RDB持久化,原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化。
劣势:
如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。
- AOF持久化,原理是将Reids的操作日志以追加的方式写入文件。
劣势:
对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
根据同步策略的不同,AOF在运行效率上往往会慢于RDB
19.事务的特性?隔离级别?
事务的四大特性:
- 原子性;一致性;隔离性;持久性;
事务隔离级别 脏读 不可重复读 幻读 读未提交(read-uncommitted):事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据 是 是 是 不可重复读(read-committed):事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果 不一致。 否 是 是 可重复读(repeatable-read) 否 否 是 串行化(serializable):有效解决了脏读,不可重复读,可重复读,幻读 否 否 否
20.创建线程池传入的参数有哪些?
- corePoolSize:线程池核心线程数量,核心线程不会被回收,即使没有任务执行,也会保持空闲状态。如果线程池中的线程少于此数目,则在执行任务时创建。
- maximumPoolSize:池允许最大的线程数,当线程数量达到corePoolSize,且workQueue队列塞满任务了之后,继续创建线程。
- keepAliveTime:超过corePoolSize之后的“临时线程”的存活时间。
- unit:keepAliveTime的单位。
- workQueue:当前线程数超过corePoolSize时,新的任务会处在等待状态,并存在workQueue中,BlockingQueue是一个先进先出的阻塞式队列实现,底层实现会涉及Java并发的AQS机制,有关于AQS的相关知识,我会单独写一篇,敬请期待。
- threadFactory:创建线程的工厂类,通常我们会自顶一个threadFactory设置线程的名称,这样我们就可以知道线程是由哪个工厂类创建的,可以快速定位。
- handler:线程池执行拒绝策略,当线数量达到maximumPoolSize大小,并且workQueue也已经塞满了任务的情况下,线程池会调用handler拒绝策略来处理请求。
21.MySQL有多少种索引?
-
普通索引:是最基本的索引,它没有任何限制。
-
唯一索引:与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
-
主键索引:是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。
-
组合索引:指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。
-
全文索引:主要用来查找文本中的关键字,而不是直接与索引中的值相比较。(FULLTEXT)
22.spring的注入方式?
-
构造器注入:构造器注入依赖于构造方法的实现,构造方法可以是有参数的,也可以是无参数的 。
-
setter注入:首先将构造方法设置为无参的构造方法,然后利用setter注入为其设置新的值。
-
基于注解注入:
- @Component:可以用于注册所有bean
- @Repository:主要用于注册dao层的bean
- @Controller:主要用于注册控制层的bean
- @Service:主要用于注册服务层的bean
23.负载均衡的方式?
-
DNS:DNS轮询是最简单的负载均衡方式。以域名作为访问入口,通过配置多条DNS A记录使得请求可以分配到不同的服务器。
-
CDN(Content Delivery Network,内容分发网络):通过发布机制将内容同步到大量的缓存节点,并在DNS服务器上进行扩展,找到里用户最近的缓存节点作为服务提供节点。
-
IP负载均衡:基于特定的TCP/IP技术实现的负载均衡。比如NAT、DR、Turning等。是最经常使用的方式。IP负载均衡可以使用硬件设备,也可以使用软件实现。硬件设备的主要产品是F5-BIG-IP-GTM(简称F5),软件产品主要有LVS、HAProxy、NginX。
24.声明式事务和编程式事务?
- 编程式事务:使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。
- 声明式事务:是建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式)。
25.什么是动态SQL?
- 是基于OGNL表达式,通过if,choose,when,otherwise,trim,where,set,foreach标签,对SQL语句进行灵活拼接、组装。从而实现对SQL语句的灵活操作。
26.事务传播机制?
required | 如果当前存在事务,就加入该事务。 如果当前没有事务,就创建一个新事务。 这是最常用的设置。 | |
requires_new | 不管是否存在事务,都创建一个新的事务。 老事务 先挂起,再创建 新事务, 新事务 执行完并提交, 接着,继续执行 老事务,最后提交。 | 1、每次都创建一个新的事务。 2、创建 新事务 前,老事务 先挂起。 3、先执行的方法后提交事务,后执行的方法先提交事务。 4、老事务 的回滚,不会影响 新事务 的提交。 |
nested | 如果当前存在事务,则在嵌套事务内执行。 如果当前没有事务,则执行与 required 类似的操作。 | nested 创建事务。 |
supports | 支持当前事务。 如果当前存在事务,就加入该事务, 如果当前不存在事务,就以非事务执行。 | supports 不会创建事务。 |
not_supported | 不支持事务。 如果当前存在事务,就把当前事务 挂起。 如果当前没有事务,就以非事务执行。 | |
mandatory | 强制、必须使用事务。 如果当前 已经存在事务,就加入该事务, 如果当前不存在事务,就 抛出异常。 | 1、mandatory 不会创建事务。 2、mandatory 执行的前提是已经存在事务。 |