java工程师面试题总结

java工程师面试题总结:

java基础面试题,Mybatis面试题,spring面试题,springMVC面试题,springboot,Redis面试题,dubbo和zookeeper做分布式的面试题,高并发处理面试题,RocketMQ和RabbitMQ消息队列面试题,Nginx面试题Java语言的反射机制与动态代理机制

Java基础
1.String和StringBuffer的区别?StringBuffe和StringBuilder的区别?
String 字符串常量(final修饰,不可被继承),String是常量,当创建之后即不能更改。(可以通过StringBuffer和StringBuilder创建String对象(常用的两个字符串操作类)。)
==StringBuffer 字符串变量(线程安全),==其也是final类别的,不允许被继承,其中的绝大多数方法都进行了同步处理,包括常用的Append方法也做了同步处理(synchronized修饰)。其自jdk1.0起就已经出现。其toString方法会进行对象缓存,以减少元素复制开销。 ==StringBuilder 字符串变量(非线程安全)==其自jdk1.5起开始出现。与StringBuffer一样都继承和实现了同样的接口和类,方法除了没使用synch修饰以外基本一致,不同之处在于最后toString的时候,会直接返回一个新对象。

2.hashMap和Hashtable的区别?底层是怎么实现的?数据结构是什么?
②HashMap和Hashtable的区别
HashMap和Hashtable都实现了Map接口,但决定用哪一个之前先要弄清楚它们之间的分别。主要的区别有:线程安全性,同步(synchronization),以及速度。
HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
HashMap不能保证随着时间的推移Map中的元素次序是不变的。

3.ArrayList和LinkedList的区别?底层是怎么实现的?数据结构是什么?
ArrayList和LinkedList都实现了List接口,有以下的不同点:
1、ArrayList是基于索引的数据接口,它的底层是数组。它可以以O(1)时间复杂度对元素进行随机访问。与此对应,LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。
2、相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引。
3、LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素。

4.什么是单线程?什么是多线程?线程的生命周期?实现线程的几种方式?
(1)生命周期的五种状态
新建(new Thread)
当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。
例如:Thread t1=new Thread();
就绪(runnable)
线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。例如:t1.start();
运行(running)
线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。
死亡(dead)
当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。
自然终止:正常运行run()方法后终止
异常终止:调用stop()方法让一个线程终止运行
堵塞(blocked)
由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。
正在睡眠:用sleep(long t) 方法可使线程进入睡眠方式。一个睡眠着的线程在指定的时间过去可进入就绪状态。
正在等待:调用wait()方法。(调用motify()方法回到就绪状态)
被另一个线程所阻塞:调用suspend()方法。(调用resume()方法恢复)
2.线程创建有几种方式
1)继承Thread类创建线程
2)实现Runnable接口创建线程
3)使用Callable和Future创建线程
实现Runnable和实现Callable接口的方式基本相同,不过是后者执行call()方法有返回值,后者线程执行体run()方法无返回值,因此可以把这两种方式归为一种这种方式与继承Thread类的方法之间的差别如下:
1、线程只是实现Runnable或实现Callable接口,还可以继承其他类。
2、这种方式下,多个线程可以共享一个target对象,非常适合多线程处理同一份资源的情形。
3、但是编程稍微复杂,如果需要访问当前线程,必须调用Thread.currentThread()方法。
4、继承Thread类的线程类不能再继承其他父类(Java单继承决定)。
注:一般推荐采用实现接口的方式来创建多线程 https://www.cnblogs.com/ideal-20/p/11205147.html

进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。
IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。其中 Socket和Streams支持不同主机上的两个进程IPC。
1.管道:速度慢,容量有限,只有父子进程能通讯
2.FIFO:任何进程间都能通讯,但速度慢
3.消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题
4.信号量:不能传递复杂消息,只能用来同步
5.共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存
8、套接字( socket ) : 套解字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。

5.HashSet
除开HashMap和Hashtable外,还有一个hash集合HashSet,有所区别的是HashSet不是key value结构,仅仅是存储不重复的元素,相当于简化版的HashMap,只是包含HashMap中的key而已
通过查看源码也证实了这一点,HashSet内部就是使用HashMap实现,只不过HashSet里面的HashMap所有的value都是同一个Object而已,因此HashSet也是非线程安全的,至于HashSet和Hashtable的区别,HashSet就是个简化的HashMap的,所以你懂的

6.设计模式有哪些?分别在什么地方有用到?
设计bai模式主要分三个类型:创建型、结构du型和行为型。
其中zhi创建型有:
一、Singleton,单例模式:保证一个dao类只有一个实例,并提供一个访问它的全局访问点
二、Abstract Factory,抽象工厂:提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们的具体类。
三、Factory Method,工厂方法:定义一个用于创建对象的接口,让子类决定实例化哪一个类,Factory Method使一个类的实例化延迟到了子类。
四、Builder,建造模式:将一个复杂对象的构建与他的表示相分离,使得同样的构建过程可以创建不同的表示。
五、Prototype,原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型来创建新的对象。
行为型有:
六、Iterator,迭代器模式:提供一个方法顺序访问一个聚合对象的各个元素,而又不需要暴露该对象的内部表示。
七、Observer,观察者模式:定义对象间一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知自动更新。
八、Template Method,模板方法:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,TemplateMethod使得子类可以不改变一个算法的结构即可以重定义该算法得某些特定步骤。
九、Command,命令模式:将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队和记录请求日志,以及支持可撤销的操作。
十、State,状态模式:允许对象在其内部状态改变时改变他的行为。对象看起来似乎改变了他的类。
十一、Strategy,策略模式:定义一系列的算法,把他们一个个封装起来,并使他们可以互相替换,本模式使得算法可以独立于使用它们的客户。
十二、China of Responsibility,职责链模式:使多个对象都有机会处理请求,从而避免请求的送发者和接收者之间的耦合关系
十三、Mediator,中介者模式:用一个中介对象封装一些列的对象交互。
十四、Visitor,访问者模式:表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这个元素的新操作。
十五、Interpreter,解释器模式:给定一个语言,定义他的文法的一个表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
十六、Memento,备忘录模式:在不破坏对象的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。
结构型有:
十七、Composite,组合模式:将对象组合成树形结构以表示部分整体的关系,Composite使得用户对单个对象和组合对象的使用具有一致性。
十八、Facade,外观模式:为子系统中的一组接口提供一致的界面,fa?ade提供了一高层接口,这个接口使得子系统更容易使用。
十九、Proxy,代理模式:为其他对象提供一种代理以控制对这个对象的访问
二十、Adapter,适配器模式:将一类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能一起工作那些类可以一起工作。
二十一、Decrator,装饰模式:动态地给一个对象增加一些额外的职责,就增加的功能来说,Decorator模式相比生成子类更加灵活。
二十二、Bridge,桥模式:将抽象部分与它的实现部分相分离,使他们可以独立的变化。
二十三、Flyweight,享元模式使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于当大量物件只是重复因而导致无法令人接受的使用大量内存

7.拦截器和过滤器的区别?分别怎么实现?
过滤器和拦截器的区别:
  ①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
  ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
  ③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
  ④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
  ⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
过滤器是依赖于servlet容器(struts),在实现上基于函数回调,可以对几乎所有的请求进行过滤。但缺点是一个过滤器实例只能在容器初始化时调用一次,来进行过滤操作,获得我们想要的数据。
拦截器是依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于java的反射机制,属于面向切面编程(AOP)的一种应用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作。同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理。
https://blog.csdn.net/dancer_one/article/details/81011675?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.nonecase

Mybatis面试题
1.#{}和KaTeX parse error: Expected 'EOF', got '#' at position 120: …些参数的时候,可以使用两种方式#̲{parameterName}…{parameterName}。
#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。
KaTeX parse error: Expected 'EOF', got '#' at position 20: …数据直接显示生成在sql中。 #̲方式能够很大程度防止sql注入…方式无法防止Sql注入。
$方式一般用于传入数据库对象,例如传入表名。
从安全性上考虑,能使用#尽量使用#来传参,因为这样可以有效防止SQL注入的问题
建议:接受从用户输出的内容并提供给语句中不变的字符串,这样做是不安全的。
这会导致潜在的SQL注入攻击,因此你不应该允许用户输入这些字段,或者通常自行转义并检查。

2.mybatis的优点缺点。
原理详解:
MyBatis应用程序根据XML配置文件创建SqlSessionFactory,SqlSessionFactory在根据配置,配置来源于两个地方,一处是配置文件,一处是Java代码的注解,获取一个SqlSession。SqlSession包含了执行sql所需要的所有方法,可以通过SqlSession实例直接运行映射的sql语句,完成对数据的增删改查和事务提交等,用完之后关闭SqlSession。
优点:
1、简单易学
mybatis本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
2、灵活
mybatis不会对应用程序或者数据库的现有设计强加任何影响。 sql写在xml里,便于统一管理和优化。通过sql基本上可以实现我们不使用数据访问框架可以实现的所有功能,或许更多。
3、解除sql与程序代码的耦合
通过提供DAL层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
4、提供映射标签,支持对象与数据库的orm字段关系映射
5、提供对象关系映射标签,支持对象关系组建维护
6、提供xml标签,支持编写动态sql。
缺点:
1、编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
2、SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
3、框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
4、二级缓存机制不佳

3.Xml映射文件中 常用标签有哪些
SQL 映射文件只有很少的几个顶级元素(按照应被定义的顺序列出):
cache – 对给定命名空间的缓存配置。
cache-ref – 对其他命名空间缓存配置的引用。
resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
parameterMap – 已被废弃!老式风格的参数映射。更好的办法是使用内联参数,此元素可能在将来被移除。
sql – 可被其他语句引用的可重用语句块。
insert – 映射插入语句
update – 映射更新语句
delete – 映射删除语句
select – 映射查询语句
动态SQL
Mybatis 动态 SQL ,可以让我们在 XML 映射文件内,以 XML 标签的形式编写动态 SQL ,完成逻辑判断和动态拼接 SQL 的功能。
Mybatis 提供了 9 种动态 SQL 标签:、、、、、、、、 。
其执行原理为,使用 OGNL 的表达式,从 SQL 参数对象中计算表达式的值,根据表达式的值动态拼接 SQL ,以此来完成动态 SQL 的功能。

4.Mybatis是如何进行分页的?

  1. 使用Map来进行包装数据实现分页功能
    1),在SQL语句映射的ResultType返回的是你要查询得到的实体类
    2),穿进去的参数parameterType是你自己包装的Map类型
    3),首先你传进来的参数要和SQL语句中的字段名要保持一致
    4),在实体DAO层还需要把查询数据的起始下标,和查询多少条数据都put进Map中
  2. 使用RowBounds来实现分页
    1),只需要设置一个返回值为User实体类型
    2),RowBounds rowBounds= newRowBounds((currentPage-1)*pageSize,pageSize);
    3),就是上一步多了一个创建一个RowBounds对象,然后需要传入SQL语句中需要的参数就行了
    4),然后sqlSession在执行selectList的时候把那个rowBounds对象直接传进去就可以了

5.Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不?
Mybatis的动态sql的作用:
动态sql就是(在进行sql操作的时候)动态的根据属性值(所匹配的条件)来拼接数据库执行的sql语句,也就是多次查询或变更操作,根据传入的属性值不同,动态拼接出不同的可执行sql。包含判断为空、循环等;

Mybatis动态sql(有哪些)标签:
1、:
if是为了判断传入的值是否符合某种规则,比如是否不为空;
2、:
where标签可以用来做动态拼接查询条件,当和if标签配合的时候,不用显示的声明类似where 1=1这种无用的条件;
3、:
这是一组组合标签,他们的作用类似于 Java 中的 switch、case、default。只有一个条件生效,也就是只执行满足的条件 when,没有满足的条件就执行 otherwise,表示默认条件;
4、:
foreach标签可以把传入的集合对象进行遍历,然后把每一项的内容作为参数传到sql语句中,里面涉及到 item(具体的每一个对象), index(序号), open(开始符), close(结束符), separator(分隔符);
5、:
include可以把大量重复的代码整理起来,当使用的时候直接include即可,减少重复代码的编写;
6、:
适用于更新中,当匹配某个条件后,才会对该字段进行更新操作
7、:
是一个格式化标签,主要有4个参数:
prefix(前缀);
prefixOverrides(去掉第一个标记);
suffix(后缀);
suffixOverrides(去掉最后一个标记);

动态sql的执行原理:
第一部分:在启动加载解析xml配置文件的时候进行解析,根据关键标签封装成对应的handler处理对象,封装成sqlSource对象存在mappedStatement。
调用流程:
I、SqlSessionFactoryBuilder对builder对象的时候,调用XMLConfigBuilder解析sqlMapConfig.xml配置文件,在解析过程中使用到了私有的mapperElement(XNode parent)方法
II、上面方法中通过构建XMLMapperBuilder,获取到所有的配置mapper配置,
在调用private void configurationElement(XNode context)方法进行解析mapper.xml,通过void buildStatementFromContext(List list, String requiredDatabaseId)方法解析mapper.xml内的每一个标签
III、循环中构建XMLStatementBuilder对象,调用parseStatementNode()方法来封装mappedStatment对象,
IIII、在过程中需要构建sqlSource对象,通过XMLLanguageDriver对象进行处理,在XMLLanguageDriver中构建解析动态标签对象XMLScriptBuilder
第二部分:在执行过程中获取sqlSource中获取bondSql对象时,执行相应的标签handler
调用查询执行到BaseExecutor的query方法时候会去getBoundSql并且将参数传进去,
在sqlSource接口DynamicSqlSource实现类中,调用getBoundSql方法执行过程共创建DynamicContext对象进行判定解析封装成SqlSource对象返回。

6.Mybatis一级缓存和二级缓存是什么?
当我们大量执行重复的查询SQL语句的时候,会频繁的和数据库进行通信,会增加查询时间等影响用户体验的问题,可以通过缓存,以降低网络流量,使网站加载速度更快.
默认情况下,MyBatis只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。这也就是大家常说的MyBatis一级缓存,一级缓存的作用域是SqlSession。
MyBatis一级缓存的运行过程是这样的:执行SQL语句的过程中,首次执行它时从数据库获取的所有数据会被存储在一段高速缓存中,今后执行这条语句时就会从高速缓存中读取结果,而不是再次查询数据库。MyBatis提供了默认下基于Java HashMap的缓存实现。
重点是要明白:MyBatis执行SQL语句之后,这条语句的执行结果被缓存,以后再执行这条语句的时候,会直接从缓存中拿结果,而不是再次执行SQL。但是一旦执行新增或更新或删除操作,缓存就会被清除。
MyBatis 一级缓存最大的共享范围就是一个SqlSession内部,那么如果多个 SqlSession 需要共享缓存,则需要开启二级缓存.
当二级缓存开启后,同一个命名空间(namespace) 所有的操作语句,都影响着一个共同的 cache,也就是二级缓存被多个 SqlSession 共享,是一个全局的变量。当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。

7.Mybatis怎么实现一对多和多对多的查询?
.









SELECT
B.BLOG_ID,
B.TITLE,
B.AUTHOR_ID AS BLOG_AUTHOR_ID
FROM LOULUAN.BLOG B
where B.BLOG_ID = #{blogId,jdbcType=DECIMAL}

1、一对一 关键字:association 作用:针对pojo对象属性的映射 property:pojo的属性名 javaType:pojo类名 (1) 嵌套结果: 使用嵌套结果映射来处理重复的联合结果的子集
  
      
    
      
      
  
select p.id as personId,p.name,p.sex,p.age,c.* from tbl_person p,tbl_card c where p.card_id=c.id; select * from student select * from student s where s.major=#{major} select * from studentmajor select * from studentmajor where id=#{id}

https://www.cnblogs.com/lvchengda/p/12598148.html

8.Mybatis和Hibernate的比较
相同点
Hibernate与MyBatis都可以是通过SessionFactoryBuider由XML配置文件生成SessionFactory,然后由SessionFactory 生成Session,最后由Session来开启执行事务和SQL语句。
其中SessionFactoryBuider,SessionFactory,Session的生命周期都是差不多的。Hibernate和MyBatis都支持JDBC和JTA事务处理。
不同点
(1)hibernate是全自动,而mybatis是半自动
(2)hibernate数据库移植性远大于mybatis
(3)hibernate拥有完整的日志系统,mybatis则欠缺一些
(4)mybatis相比hibernate需要关心很多细节
(5)sql直接优化上,mybatis要比hibernate方便很多
(6)缓存机制上,hibernate要比mybatis更好一些

spring面试题
1.spring的几大特性是什么?什么是AOP?什么是IOC?分别在项目中哪里有用到?
Spring拥有两大特性:IoC和AOP。IoC,英文全称Inversion of Control,意为控制反转。AOP,英文全称Aspect-Oriented Programming,意为面向切面编程。Spring核心容器的主要组件是Bean工厂(BeanFactory),Bean工厂使用控制反转(IoC)模式来降低程序代码之间的耦合度,并提供了面向切面编程(AOP)的实现。
简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面编程(AOP)的容器框架
控制反转,简单点说,就是创建对象的控制权,被反转到了Spring框架上。
通常,我们实例化一个对象时,都是使用类的构造方法来new一个对象,这个过程是由我们自己来控制的,而控制反转就把new对象的工交给了Spring容器。
面向切面编程(AOP)就是纵向的编程。比如业务A和业务B现在需要一个相同的操作,传统方法我们可能需要在A、B中都加入相关操作代码,而应用AOP就可以只写一遍代码,A、B共用这段代码。并且,当A、B需要增加新的操作时,可以在不改动原代码的情况下,灵活添加新的业务逻辑实现。
在实际开发中,比如商品查询、促销查询等业务,都需要记录日志、异常处理等操作,AOP把所有共用代码都剥离出来,单独放置到某个类中进行集中管理,在具体运行时,由容器进行动态织入这些公共代码。
AOP主要一般应用于签名验签、参数校验、日志记录、事务控制、权限控制、性能统计、异常处理等。

2.Spring事务管理的方式有几种?
大家所了解的事务Transaction,它是一些列严密操作动作,要么都操作完成,要么都回滚撤销。Spring事务管理基于底层数据库本身的事务处理机制。数据库事务的基础,是掌握Spring事务管理的基础。这篇总结下Spring事务。
事务是程序中一系列严密的操作,所有操作执行必须成功完成,否则在每个操作所做的更改将会被撤销,这也是事务的原子性(要么成功,要么失败)。
  数据库向用户提供保存当前程序状态的方法,叫事务提交(commit);当事务执行过程中,使数据库忽略当前的状态并回到前面保存的状态的方法叫事务回滚(rollback)

事务具备ACID四种特性,ACID是Atomic(原子性)、Consistency(一致性)、Isolation(隔离性)和Durability(持久性)的英文缩写。 
原子性(Atomicity)
    事务最基本的操作单元,要么全部成功,要么全部失败,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样。
  (2)一致性(Consistency)
    事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。
  (3)隔离性(Isolation)
    指的是在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。由并发事务所做的修改必须与任何其他并发事务所做的修改隔离。事务查看数据更新时,数据所处的状态要么是另一事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看到中间状态的数据。
  (4)持久性(Durability)
    指的是只要事务成功结束,它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。
事务几种实现方式 (编程式事务管理、编程式事务管理) 
  (1)编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中调用beginTransaction()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。
  (2)基于 TransactionProxyFactoryBean的声明式事务管理
  (3)基于 @Transactional 的声明式事务管理
  (4)基于Aspectj AOP配置事务
 注:此处侧重讲解声明式事务,编程式事务在实际开发中得不到广泛使用,仅供学习参考。

3.Spring事务中的隔离级别有哪几种?
数据库事务的隔离级别有4种,由低到高分别为Read uncommitted 、Read committed 、Repeatable read 、Serializable 。而且,在事务的并发操作中可能会出现脏读,不可重复读,幻读。下面通过事例一一阐述它们的概念与联系。
  脏读、不可重复读、幻象读概念说明:  
  脏读:指当一个事务正在访问数据,并且对数据进行了修改,而这种数据还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据还没有提交那么另外一个事务读取到的这个数据我们称之为脏数据。依据脏数据所做的操作肯能是不正确的。
  不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有执行结束,另外一个事务也访问该同一数据,那么在第一个事务中的两次读取数据之间,由于第二个事务的修改第一个事务两次读到的数据可能是不一样的,这样就发生了在一个事物内两次连续读到的数据是不一样的,这种情况被称为是不可重复读。
  幻象读:一个事务先后读取一个范围的记录,但两次读取的纪录数不同,我们称之为幻象读(两次执行同一条 select 语句会出现不同的结果,第二次读会增加一数据行,并没有说这两次执行是在同一个事务中)
读未提交 (Read uncommitted)
  读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。
  分析:实际程序员这个月的工资还是3.6万,但是程序员看到的是3.9万。他看到的是老板还没提交事务时的数据。这就是脏读。因此,在这种隔离级别下,查询是不会加锁的,也由于查询的不加锁,所以这种隔离级别的一致性是最差的,可能会产生“脏读”、“不可重复读”、“幻读”。如无特殊情况,基本是不会使用这种隔离级别的。
  那怎么解决脏读呢?Read committed!读提交,能解决脏读问题。
读提交(Read Committed)
  读提交,顾名思义,就是只能读到已经提交了的内容
可重复读(Repeated Read)
  可重复读,顾名思义,就是专门针对“不可重复读”这种情况而制定的隔离级别,自然,它就可以有效的避免“不可重复读”。而它也是MySql的默认隔离级别。
序列化 Serializable
这是数据库最高的隔离级别,这种级别下,事务“串行化顺序执行”,也就是一个一个排队执行。这种级别下,“脏读”、“不可重复读”、“幻读”都可以被避免,但是执行效率奇差,性能开销也最大,所以基本没人会用。
总结一下:
为什么会出现“脏读”?因为没有“select”操作没有规矩。
为什么会出现“不可重复读”?因为“update”操作没有规矩。
为什么会出现“幻读”?因为“insert”和“delete”操作没有规矩。
“读未提(Read Uncommitted)”能预防啥?啥都预防不了。
“读提交(Read Committed)”能预防啥?使用“快照读(Snapshot Read)”,避免“脏读”,但是可能出现“不可重复读”和“幻读”。
“可重复读(Repeated Red)”能预防啥?使用“快照读(Snapshot Read)”,锁住被读取记录,避免出现“脏读”、“不可重复读”,但是可能出现“幻读”。
“串行化(Serializable)”能预防啥?排排坐,吃果果,有效避免“脏读”、“不可重复读”、“幻读”,不过效果谁用谁知道。
spring的事务传播行为是:REQUIRED
  mysql的默认的事务处理级别是:REPEATABLE-READ, 也就是可重复读
  Oracle的默认的事务处理级别是:READ COMMITTED, 也就是读已提交
可以通过更改数据库的默认事务处理级别
https://www.cnblogs.com/myseries/p/10748912.html

4.分布式事务如何实现?
事务在单系统中的表现:多次数据库操作用事务进行管理,来保证ACID原则。
MQ事务消息
  直接基于 MQ 来实现事务,不再用本地的消息表。有一些第三方的MQ是支持事务消息的,比如RocketMQ,他们支持事务消息的方式也是类似于采用的二阶段提交,但是市面上一些主流的MQ都是不支持事务消息的,比如 RabbitMQ 和 Kafka 都不支持。
             
  实现思想为:
A 系统先发送一个 prepared 消息到 mq,如果这个 prepared 消息发送失败那么就直接取消操作别执行了;
如果这个消息发送成功过了,那么接着执行本地事务,如果成功就告诉 mq 发送确认消息,如果失败就告诉 mq 回滚消息;
如果发送了确认消息,那么此时 B 系统会接收到确认消息,然后执行本地的事务;
mq 会自动定时轮询所有 prepared 消息回调你的接口,问你,这个消息是不是本地事务处理失败了,所有没发送确认的消息,是继续重试还是回滚?一般来说这里你就可以查下数据库看之前本地事务是否执行,如果回滚了,那么这里也回滚吧。这个就是避免可能本地事务执行成功了,而确认消息却发送失败了。
这个方案里,要是系统 B 的事务失败了咋办?重试咯,自动不断重试直到成功,如果实在是不行,要么就是针对重要的资金类业务进行回滚,比如 B 系统本地回滚后,想办法通知系统 A 也回滚;或者是发送报警由人工来手工回滚和补偿。
  这种方案缺点就是实现难度大,而且主流MQ不支持。
Spring框架中用到了哪些设计模式
1.工厂设计模式:Spring使用工厂模式通过BeanFactory和ApplicationContext创建bean对象。
2.代理设计模式:Spring AOP功能的实现。
3.单例设计模式:Spring中的bean默认都是单例的。
4.模板方法模式:Spring中的jdbcTemplate、hibernateTemplate等以Template结尾的对数据库操作的类,它们就使用到了模板模式。
5.包装器设计模式:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
6.观察者模式:Spring事件驱动模型就是观察者模式很经典的一个应用。
7.适配器模式:Spring AOP的增强或通知(Advice)使用到了适配器模式、Spring MVC中也是用到了适配器模式适配Controller。

springMVC面试题
Spring面试题:https://www.cnblogs.com/yanggb/p/11004887.html
1.Springmvc 工作原理是什么?Springmvc 执行流程是什么?
图解SpringMVC执行流程:

SpringMVC执行流程:
1.用户发送请求至前端控制器DispatcherServlet
2.DispatcherServlet收到请求调用处理器映射器HandlerMapping。
3.处理器映射器根据请求url找到具体的处理器,生成处理器执行链HandlerExecutionChain(包括处理器对象和处理器拦截器)一并返回给DispatcherServlet。
4.DispatcherServlet根据处理器Handler获取处理器适配器HandlerAdapter执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作
5.执行处理器Handler(Controller,也叫页面控制器)。
6.Handler执行完成返回ModelAndView
7.HandlerAdapter将Handler执行结果ModelAndView返回到DispatcherServlet
8.DispatcherServlet将ModelAndView传给ViewReslover视图解析器
9.ViewReslover解析后返回具体View
10.DispatcherServlet对View进行渲染视图(即将模型数据model填充至视图中)。
11.DispatcherServlet响应用户。
链接:https://www.jianshu.com/p/8a20c547e245

2.Springmvc 怎么样设定重定向和转发的?
一、转发与重定向的区别
1.地址栏
转发:不变,不会显示出转向的地址
重定向:会显示转向之后的地址
2.请求
转发:一次请求
重定向:至少提交了两次请求
3.数据
转发:对request对象的信息不会丢失,因此可以在多个页面交互过程中实现请求数据的共享
重定向:request信息将丢失
4.原理
转发:是在服务器内部控制权的转移,是由服务器区请求,客户端并不知道是怎样转移的,因此客户端浏览器的地址不会显示出转向的地址。
重定向:是服务器告诉了客户端要转向哪个地址,客户端再自己去请求转向的地址,因此会显示转向后的地址,也可以理解浏览器至少进行了两次的访问请求。
二、转发 (转发到一个页面或另一个处理器)
转发:在返回值前面加"forward:"
从第一个转发到其他的处理器,是不需要写传递的数据的,因为数据共享
三、重定向
在返回值前面加"redirect:

/**
* 实现转发
*/
@RequestMapping("/hello11.action")
public String hello11(HttpServletRequest request){
request.setAttribute(“name”, “cjj”);
return “forward:hello.action”;
}

/**
 * 实现重定向
 */
@RequestMapping("/hello12.action")
public String hello12(HttpServletRequest request){
    request.setAttribute("name", "cjj");
    return "redirect:/hello.action";
}

3.Springmvc 中拦截器如何使用
SpringMVC中的拦截器(Interceptor)主要是拦截用户的请求并进行相应的处理。拦截器可以用于权限验证、解决乱码、操作日志记录、性能监控、异常处理等。可以通过继承Spring框架中的HandlerInterceptorAdapter类,然后重写preHandle:该方法在action执行前执行,可以实现对数据的预处理,比如:编码、防重复提交安全控制等。如果方法返回true,则继续执行action。返回false则拦截请求,postHandle:该方法在action执行后,生成视图前执行。在这里,我们有机会修改视图层数据。,afterCompletion:最后执行,通常用于释放资源,处理异常。我们可以根据ex是否为空,来进行相关的异常处理。三个方法,在三个方法中写我们自己要想实现的业务逻辑代码.
当有多个拦截器的时候可以写多个bean
当我们只想拦截部分指定请求时:
1
2
3
4
5 mvc:interceptors



多个拦截器
xml配置:
1
2
3
4 mvc:interceptors


当配置有多个拦截器的时候,会按拦截器顺序执行preHandle方法,然后再倒序执行postHandle和afterCompletion方法。
其他实现方式
实现接口 implements HandlerInterceptor
实现接口 implements WebRequestInterceptor
注册拦截器方法不变

1.过滤器是依赖于Servlet容器,基于回调函数,Intercepto依赖与框架,基于反射机制
2.过滤器的过滤范围更大,还可以过滤一些静态资源,拦截器只拦截请求
4、Spring MVC的优点?
Spring MVC是一个基于Java的实现了MVC设计模式的请求驱动类型的轻量级Web框架,通过把Model,View,Controller分离,将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。
Springmvc的优点:
(1)可以支持各种视图技术,而不仅仅局限于JSP;
(2)与Spring框架集成(如IoC容器、AOP等);
(3)清晰的角色分配:前端控制器(dispatcherServlet) , 请求到处理器映射(handlerMapping), 处理器适配器(HandlerAdapter), 视图解析器(ViewResolver)。
(4) 支持各种请求资源的映射策略。
优点:
一:完全基于接口编程,真正实现了视图无关。除了jsp,还可以使用Velocity和xstl或其他视图技术,甚至是自定义的视图技术–只需要简单的实现view接口
二:Spring MVC框架以DispatchServlet为核心控制器,该控制器负责拦截用户的所有请求
三:Spring MVC所有控制器都必须实现Controler接口,该接口定义了ModelAndView handleRequest(request,response)方法,通过实现该接口实现用户的业务逻辑控制。
缺点:
一:Spring与MVC 的Servlet API 耦合,难以脱离容器独立运行
二:太过于细分,开发效率低
三:过度追求完美,有过度设计的危险

4.controller注解和resetcontroller注解的区别?
这两个注解的使用位置上都是用在Controller层,作用是用来标注Controller层的组件。相当于Struts中的Action。当然,在作用上,还有@Component,@Respository和@Service这几个注解,他们在应用中是等效。
@RestController 注解相当于 @Controller + @ResponseBody 合在一起的作用。Controller类中的方法返回值,默认是json对象,也就是相当于@Controller里面的方法上添加了@ResponseBody

5.Springmvc 如何返回json数据?
1、第一种方式是spring2时代的产物,也就是每个json视图controller配置一个Jsoniew。
2、第二种使用JSON工具将对象序列化成json,常用工具Jackson,fastjson,gson。
3、第三种利用spring mvc3的注解@ResponseBody

springBoot
1.springBoot项目和传统的SSM项目有什么优缺点?
Springboot的概念:
是提供的全新框架,使用来简化Spring的初始搭建和开发过程,使用了特定的方式来进行配置,让开发人员不在需要定义样板化的配置。此框架不需要配置xml,依赖于像MAVEN这样的构建系统。
“习惯优于配置”(项目中存在大量的配置,此外还内置了一个习惯性的配置,让你无需手动进行配置)
SpringBoot帮助开发者快速启动一个Web容器;
SpringBoot继承了原有Spring框架的优秀基因;
SpringBoot简化了使用Spring的过程。
SSM框架,是三层结合所成的框架,分别是,Spring,SpringMVC,MyBatis所组成。spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。Spring依赖注入来管理各层,面向切面编程管理事务,日志和权限。SpringMVC代表了Model,View,Controller接收外部请求,进行分发和处理。Mybatis是基于jdbc的框架,主要用来操作数据库,并且将业务实体和数据表联系起来。
一、SSM优缺点应该分开来说的,比如
1)spring,核心ioc、aop技术,ioc解耦,使得代码复用,可维护性大幅度提升,aop提供切面编程,同样的增强了生产力。
2)spring mvc,是方法拦截,controller独享request response数据,采用的serlvet入口,与spring无缝对接。开发而言,spring mvc更加轻量和低入门。
3)mybatis,sql可以由开发者去掌控和调优,相对hibernate等orm框架来说,更加直观。当然缺点就是对sql不熟悉的开发者就不太友好了。
二、 SSM框架和spring boot全家桶相比有哪些优缺点? SSM是WEB应用框架,涵盖整个应用层,而spring boot你可以看做一个启动、配置、快速开发的辅助框架,本身针对的是微服务。
springboot 只是为了提高开发效率,是为了提升生产力的:
1、springboot一个应用是一个可执行jar(启动类main方法启动web应用),而不像传统的war,内嵌tomcat容器,可以jar形式启动一个服务,可以快速部署发布web服务,微服务最好不过了。
2、将原有的xml配置,简化为java配置
3、当然结构可能跟一般的ssm有一定区别,但其实主要是在资源文件。
https://www.csdn.net/gather_23/MtjaYg4sMDUzMjAtYmxvZwO0O0OO0O0O.html

Redis面试题
1.Redis 如何做持久化的?
1.redis持久化的两种方式
2.两种持久化方式区别
3.两种持久化方式的使用场景
1.Redis 是内存型数据库,一般来用作缓存。保存在内存的数据有一个特点, 就是断电消失,因此一旦 Redis 宕机了,重启以后保存在 Redis 里面的数据就会消失, 此时服务器在 Redis 里面获取不到缓存,就会让缓存无法命中,导致缓存雪崩,请求直接打到 MySQL 上最后让 MySQL 也宕机。 因此我们需要 Redis 持久化来做灾难恢复、数据恢复还有数据库高可用。
2.Redis 有两种持久化方式,一种是 RDB、一种是 AOF。 RDB:就是对 Redis 中的数据进行周期性的持久化。类似于快照 AOF:就是对每一条写入、删除记录做日志,Redis 重启的时候,重启 AOF 日志重构数据集 如果同时使用两种,Redis 就会优先实现 AOF,因为数据更加完整
RDB: 优点:保存多份完整备份,对 IO 影响小,适合做冷备,并且在宕机后恢复更加快 缺点:一般快照文件生成的间隙在 5min,一旦宕机,就会丢失 5min 的数据。同时如果快照文件过大,会让服务暂停几毫秒甚至一秒
AOF: 优点:一般 1s 同步一次,最多丢失 1s 的数据。同步日志是使用 append-only 模式,写入快,并且日志文件不易破损,尾部破损也容易恢复。并且 AOF 文件大小不会影响性能。 缺点:AOF 日志一般比 RDB 文件大,同时以前 AOF出过 Bug导致数据没有完整的恢复。
一般我们选择的话,不能单单使用 RBD 会丢失许多数据,也不能单单使用 AOF 恢复速度比较慢,也容易有 bug。推荐同时使用,AOF 保证数据不丢失,RBD 做冷备,一旦 AOF 丢失或者不可用的时候可以用于快速恢复。

2.单线程的redis为什么这么快?
1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);
2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
4、使用多路I/O复用模型,非阻塞IO;这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。
5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

3.redis的数据类型有哪些?
Redis支持五种数bai据类型:string(字符串),duhash(哈希),list(列表),set(集合zhi)及zset(sorted set:有序集合)。

5.Redis异步消息(发布与订阅)?
发布与订阅(publish/subscribe)模式,简称为pub/sub模式,redis也实现了这种模式。
1.订阅频道subscribe channel 例如:订阅my1 subscribe my1
2.批量订阅psubscribe channel* 例如:psubscribe s* 批量订阅s开头的频道
3.在指定的频道中发布消息publish channel content
redis提供的发布订阅命令
命令 用例和描述
subscribe subscribe channel [channel …] 订阅一个或多个频道
unsubscribe unsubscribe [channel [channel …]] 退订频道,如果没有指定频道,则退订所有的频道
publish publish channel message 给指定的频道发消息
psubscribe psubscribe pattern [pattern …] 订阅给定模式相匹配的所有频道
punsubscribe punsubscribe [pattern [pattern …]] 退订给定的模式,如果没有指定模式,则退订所有模式

缺点,所有pub/sub很有用,但是redis的实现有这么几个问题:
1,如果一个客户端订阅了频道,但自己读取消息的速度却不够快的话,那么不断积压的消息会使redis输出缓冲区的体积变得越来越大,这可能使得redis本身的速度变慢,甚至直接崩溃。
2,这和数据传输可靠性有关,如果在订阅方断线,那么他将会丢失所有在短线期间发布者发布的消息,这个让绝不多数人都很失望吧。

dubbo和zookeeper做分布式的面试题
1.dubbo,zookeeper是什么?
Dubbo建议使用Zookeeper作为服务的注册中心
dubbo:是管理中间层的工具,一个解决大规模服务治理的高性能分布式服务框架;分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架;
Zookeeper提供的服务:配置维护、域名服务、分布式同步、组服务;
2.什么是分布式?什么是微服务?
分布式系统是由若干个独立计算机的集合,这些计算机对于用户来说就像单个相关的系统
RPC(Remote Procedure Call)是指远程过程调用,是一种进程之间的通信方式,它是一种技术的思想,而不是规范,它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不是程序员显式编码这个远程调用的细节,即程序员无论是调用本地的还是远程的函数,本质上编写的调用代码基本相同。
微服务是一种面向服务的架构(SOA)风格,其中,应用程序被构建为多个不同的小型服务的集合,这些较小的程序组合在一起,可以提供庞大的单程序所具备的所有功能。微服务是一种面向服务的架构风格,具有灵活性和低成本两个特点.

2.Dubbo的工作原理?注册中心挂了可以继续通信吗?说说一次rpc请求的流程?
(1)dubbo工作原理
第一层:service层,接口层,给服务提供者和消费者来实现的
第二层:config层,配置层,主要是对dubbo进行各种配置的
第三层:proxy层,服务代理层,透明生成客户端的stub和服务单的skeleton
第四层:registry层,服务注册层,负责服务的注册与发现
第五层:cluster层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务
第六层:monitor层,监控层,对rpc接口的调用次数和调用时间进行监控
第七层:protocol层,远程调用层,封装rpc调用
第八层:exchange层,信息交换层,封装请求响应模式,同步转异步
第九层:transport层,网络传输层,抽象mina和netty为统一接口
第十层:serialize层,数据序列化层
工作流程:
1)第一步,provider向注册中心去注册
2)第二步,consumer从注册中心订阅服务,注册中心会通知consumer注册好的服务
3)第三步,consumer调用provider
4)第四步,consumer和provider都异步的通知监控中心

可以,因为刚开始初始化的时候,消费者会将提供者的地址等信息拉取到本地缓存,所以注册中心挂了可以继续通信。
4.Dubbo有几种容错机制?
常见容错机制:failover ,failsafe,failfase ,failback,forking,来源于阿里的定义。
Failover 失败自动切换
当出现失败,重试其它服务器,通常用于读操作(推荐使用)。 重试会带来更长延迟。
Failfast 快速失败
只发起一次调用,失败立即报错,通常用于非幂等性的写操作。 如果有机器正在重启,可能会出现调用失败 。
Failsafe 失败安全
出现异常时,直接忽略,通常用于写入审计日志等操作。 调用信息丢失 可用于生产环境 Monitor。
Failback 失败自动恢复
后台记录失败请求,定时重发。通常用于消息通知操作 不可靠,重启丢失。 可用于生产环境 Registry。
Forking 并行调用多个服务器
只要一个成功即返回,通常用于实时性要求较高的读操作。 需要浪费更多服务资源 。
Broadcast
广播调用,所有提供逐个调用,任意一台报错则报错。通常用于更新提供方本地状态 速度慢,任意一台报错则报错 。
实际应用中,查询语句容错策略建议用默认Failover Cluster,而增删改 建议使用Failfast Cluster 或者 使用Failover Cluster(retries = “0”) 策略,防止出现数据重复添加

5.消费者调用提供者时每次都会走zookeeper吗?为什么?
不会,因为刚开始初始化的时候,消费者会将提供者的地址等信息拉取到本地缓存,所以注册中心挂了可以继续通信。

RocketMQ和RabbitMQ消息队列面试题
https://blog.csdn.net/jerryDzan/article/details/89183625

https://blog.csdn.net/ThinkWon/article/details/104588612?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2allfirst_rank_v2~rank_v25-17-104588612.nonecase&utm_term=rabbitmq%E4%B8%BB%E8%A6%81%E6%8B%BF%E6%9D%A5%E5%B9%B2%E4%BB%80%E4%B9%88&spm=1000.2123.3001.4430

1.你要知道rabitmq是干嘛的?
RabbitMQ是一款开源的,Erlang编写的,基于AMQP协议的消息中间件
消息中间件就是接收消息、存储消息、推送消息,我们使用消息中间件,很多时候就是在使用消息中间件的异步处理模式。同步串行处理耗时(Rabbitmq异步消息通知机制解决了串行问题。);并发流量削峰;程序设计解耦;主要是:解耦、异步、削峰。
组成部分简要说明:
Broker: Rabbitmq服务进程,主要包括两个部分Exchange(交换机)和Queue(队列);
Exchange: 交换机,按一定的规则将消息路由到某个队列,不同类型的交换机有不同的路由规则;
Queue: 消息队列,存储消息的队列,消息到达队列后推送给消费者。
Producer: 消息生产者,即生产方客户端,生产者将消息投递到消息队列。
Consumer: 消息消费者,即消费方客户端,接收消息队列推送的消息。
Connect: 可以理解为一个Tcp连接,Producer和Consumer都是通过TCP连接到RabbitMQ Server的;
Channel: 虚拟连接,它建立在上述的Tcp连接中,数据流动都是在Channel中进行的,也就是说一般情况是程序开始建立Tcp连接,第二步就是建立Channel。

系统可用性降低,系统复杂度提高
2.rabitmq用在什么场景?
(1)服务间异步通信
(2)顺序消费
(3)定时任务
(4)请求削峰
3.rabitmq如何使用?
4.rabitmq有几种模式?
RabbitMQ的工作模式
一.模式(即最简单的收发模式)
二.work工作模式(资源的竞争)
三.publish/subscribe发布订阅(共享资源)
四.routing路由模式
五.topic 主题模式(路由模式的一种)
其中Publish/Subscribe,Routing,Topics三种模式可以统一归为Exchange模式,只是创建时交换机的类型不一样,分别是fanout、direct、topic。

5优点:RabbitMQ,他的好处在于可以支撑高并发、高吞吐、性能很高,同时有非常完善便捷的后台管理界面可以使用。另外,他还支持集群化、高可用部署架构、消息高可靠支持,功能较为完善。

Nginx面试题
nginx是一款免费、开源的http服务器,nginx能支撑5万的并发量,主要功能有虚拟主机、反向代理和负载均衡等。
nginx作为虚拟主机,指的就是在一个nginx服务器上可同时运行多个网站。nginx可以通过配置多个server来配置多台虚拟主机,一个server对应一台虚拟主机,一台虚拟主机上可部署一个网站。各个虚拟主机的ip地址都是一样的(即服务器的ip地址),但是一个ip地址可以绑定不同的域名,所以每台虚拟主机都可以有自己独立的域名和端口号。
反向代理是相对于正向代理而言的,正向代理服务于客户端,反向代理服务于服务端。反向代理服务器位于客户端浏览器和web服务器之间,客户端不能直接向web服务器发请求,所有的请求都必须先发给反向代理服务器,然后由反向代理服务器转发给web服务器,同样,web服务器返回的响应也要先发给反向代理服务器,然后再转发给客户端。反向代理服务器发挥反向代理作用时就起到了一个中转站的作用。(代替真实服务器接收网络请求,然后将请求转发到真实服务器)
反向代理服务器可实现三大功能:

  1. 保护网站安全。客户端无法直接访问到网站的web服务器,所有请求必须先经过反向代理服务器,相当于在web服务器和可能的网络攻击之间建立了一个屏障。
  2. 缓存网站的静态资源,提高网站的响应速度。当用户第一次访问静态内容的时候,静态内容就被缓存在反向代理服务器上,这样当其他用户访问该静态内容的时候,就可以直接从反向代理服务器返回,加速web请求响应速度,减轻web服务器负载压力。
  3. 负载均衡。反向代理服务器位于web服务器前面,这个位置正好也是负载均衡服务器的位置,所以大多数反向代理服务器同时提供负载均衡的功能。

负载均衡:将请求转发给服务器集群,保证服务器的高可用,保证响应足够快,给用户良好的体验。核心是“分摊压力”。Ngnix默认处理负载均衡的方式是“轮询”,我们可以通过weight来调整权重。
5种策略:
1、轮询(默认)
每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
2、指定权重
指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
3、IP绑定 ip_hash
每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
4、fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。
5、url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。

nginx在发挥反向代理和负载均衡功能时,只是起到一个中转站的作用,客户端发送的请求要先发给nginx服务器,然后由nginx服务器转发给web服务器。Web服务器返回的响应也要先发给nginx服务器,然后再由nginx服务器转发给客户端。

nginx服务器发挥负载均衡功能,代码演示:
upstream tomcat1 {
server 192.168.25.148:8080;
server 192.168.25.148:8082;
}
server {
listen 80;
server_name www.sina.com.cn;
location / {
proxy_pass http://tomcat1;
index index.html index.htm;
}
}

http指令:接收http请求。
upstream tomcat2 { upstream指令:映射proxy-pass指定的代理服务器的路径。
server 192.168.25.148:8081; server指令:一个server对应一个虚拟主机,对应一个服务,对应一个网站。
server 192.168.25.148:8084 weight=2;
}
server {
listen 80; listen指令;监听端口号。
server_name www.sohu.com; server-name指令:监听域名。
location / { location指令:对请求资源路径进行整合和分发。它可以使用字符串和正则表达式进行配置。
proxy_pass http://tomcat2; location指令里的proxy-pass属性:指定反向代理的服务器的路径。
index index.html index.htm; location指令里的root属性:指定静态资源路径。
}
}

http指令:接收http请求。
server指令:一个server对应一个虚拟主机,对应一个服务,对应一个网站。
listen指令;监听端口号。
server-name指令:监听域名。
location指令:对请求资源路径进行整合和分发。它可以使用字符串和正则表达式进行配置。
location指令里的root属性:指定静态资源路径。
location指令里的proxy-pass属性:指定反向代理的服务器的路径。
upstream指令:映射proxy-pass指定的代理服务器的路径。

动态代理
所以在这里明确代理对象的两个概念:
    1、代理对象存在的价值主要用于拦截对真实业务对象的访问。
    2、代理对象应该具有和目标对象(真实业务对象)相同的方法。
使用代理模式必须要让代理类和目标类实现相同的接口,客户端通过代理类来调用目标方法,代理类会将所有的方法调用,分派到目标对象上反射执行,还可以在分派过程中添加"前置通知"和后置处理(是在invoke方法中添加,如在调用目标方法前校验权限,在调用完目标方法后打印日志等)等功能。
代理逻辑 和 动态代理本身是代码分离的,程序员只需要关注好自己的代理逻辑就行,动态代理本身就交给jdk本身去处理。在jdk动态代理中,美中不足就是整个设计都是针对接口做的代理,如果是普通的类,我们无法通过这个方式代理对象(通过生成的代理类也知道没有接口是不行的),但是我们知道 通过拼接字节码生成新的类自由度是十分大的,这也就启示我们 设计不管是针对接口类还是普通类的代理类 是完全可行的,比如cglib框架就是通过拼接字节码来实现非接口类的代理。
缓存雪崩:当某一时刻发生大规模的缓存失效的情况,比如你的缓存服务宕机了,会有大量的请求进来直接打到DB上面。结果就是DB 称不住,挂掉。
使用集群缓存,保证缓存服务的高可用
这种方案就是在发生雪崩前对缓存集群实现高可用,如果是使用 Redis,可以使用 主从+哨兵 ,Redis Cluster 来避免 Redis 全盘崩溃的情况。
缓存穿透:那么请求去查询一条压根儿数据库中根本就不存在的数据,也就是缓存和数据库都查询不到这条数据,但是请求每次都会打到数据库上面去。这种查询不存在数据的现象我们称为缓存穿透。
解决:缓存空值
1我们可以为这些key对应的值设置为null 丢到缓存里面去。后面再出现查询这个key 的请求的时候,直接返回null 。
这样,就不用在到数据库中去走一圈了,要设置过期时间。
2. BloomFilter
BloomFilter 类似于一个hbase set 用来判断某个元素(key)是否存在于某个集合中。
这种方案可以加在第一种方案中,在缓存之前在加一层 BloomFilter ,在查询的时候先去 BloomFilter 去查询 key 是否存在,如果不存在就直接返回,存在再走查缓存 -> 查 DB。
缓存击穿:在平常高并发的系统中,大量的请求同时查询一个 key 时,此时这个key正好失效了,就会导致大量的请求都打到数据库上面去。会造成某一时刻数据库请求量过大,压力剧增。这种现象我们称为缓存击穿。
解决:多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个 互斥锁来锁住它。
其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。

Mysql
1.表连接有哪几种?分表说下查出的数据结果
使用sql语句实现多表查询,比较常用的有inner join,left join,right join,full join,union几种方式
主要分为三种:内bai连du接、外连接zhi、交叉连接。
一、内连接
使用比较运算符(包括权=、>、<、<>、>=、<=、!> 和!<)进行表间的比较操作,查询与连接条件相匹配的数据。根据所使用的比较方式不同,内连接分为等值连接、自然连接和自连接三种。
1。等值连接/相等连接
使用”=”关系将表连接起来的查询,其查询结果中列出被连接表中的所有列,包括其中的重复列。
2.自然连接
等值连接中去掉重复的列,形成的连接。
3.自连接
如果在一个连接查询中,设计到的两个表都是同一个表,这种查询称为自连接查询。
二、外连接
分为左外连接、右外链接、全外连接三种。
三、交叉连接/笛卡尔积
两个表做笛卡尔积,得到的结果集的行数是两个表的行数的乘积。
2.索引有哪几种?为什么要加索引
索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存。
普通索引 这是最基本的索引类型
唯一性索引 这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一。
主键 主键是一种唯一性索引,但它必须指定为“PRIMARY KEY”。
组合索引 指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合.如果是组合索引,则列值的组合必须唯一
全文索引 MySQL从3.23.23版开始支持全文索引和全文检索。在MySQL中,全文索引的索引类型为FULLTEXT。全文索引可以在VARCHAR或者TEXT类型的列上创建。
1.虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行insert、update和delete。因为更新表时,不仅要保存数据,还要保存一下索引文件。
2.建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会增长很快。
索引只是提高效率的一个因素,如果有大数据量的表,就需要花时间研究建立最优秀的索引,或优化查询语句。
使用索引时,有以下一些技巧和注意事项:
2.1.索引不会包含有null值的列
只要列中包含有null值都将不会被包含在索引中,复合索引中只要有一列含有null值,那么这一列对于此复合索引就是无效的。所以我们在数据库设计时不要让字段的默认值为null。
2.2.使用短索引
对串列进行索引,如果可能应该指定一个前缀长度。例如,如果有一个char(255)的列,如果在前10个或20个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。
2.3.索引列排序
查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。
2.4.like语句操作
一般情况下不推荐使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。
2.5.不要在列上进行运算
这将导致索引失效而进行全表扫描,例如
SELECT * FROM table_name WHERE YEAR(column_name)<2017;
2.6.不使用not in和<>操作

3.如何判断你写的SQL语句查询效率快慢?
使用Mysql提供的 explain关键字查看执行计划
3.Mysql 中 MyISAM 和 InnoDB 的区别有哪些?
区别:
3.1.InnoDB 支持事务,MyISAM 不支持事务。这是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;
3.2.InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM 会失败;
3.3.InnoDB 是聚集索引,MyISAM 是非聚集索引。聚簇索引的文件存放在主键索引的叶子节点上,因此 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
3.4.InnoDB 不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。而MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
3.5.InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁。一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,因此并发访问受限。这也是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一;
3.6.MyISAM支持全文类型索引,而InnoDB不支持全文索引
3.7.MyISAM相对简单,效率上要优于InnoDB,小型应用可以考虑使用MyISAM
3.8.MyISAM表保存成文件形式,跨平台使用更加方便
4.如何选择:
4.1. 是否要支持事务,如果要请选择 InnoDB,如果不需要可以考虑 MyISAM;
4.2. 如果表中绝大多数都只是读查询,可以考虑 MyISAM,如果既有读写也挺频繁,请使用InnoDB。
4.3. 系统奔溃后,MyISAM恢复起来更困难,能否接受,不能接受就选 InnoDB;
4.4. MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共睹的。如果你不知道用什么存储引擎,那就用InnoDB,至少不会差。

5.Mysql优化这块怎么做的,比如查询?https://www.cnblogs.com/yangfanfan/p/11848510.html
like语句优化
SELECT id FROM A WHERE name like ‘%abc%’
由于abc前面用了“%”,因此该查询必然走全表查询,除非必要,否则不要在关键词前加%,优化成如下
SELECT id FROM A WHERE name like ‘abc%’
6、where子句使用 != 或 <> 操作符优化
在where子句中使用 != 或 <>操作符,索引将被放弃使用,会进行全表查询。
如SQL:SELECT id FROM A WHERE ID != 5
优化成:SELECT id FROM A WHERE ID>5 OR ID<5
7、尽量避免在 where 子句中对字段进行 null 值判断(IS NULL 或 IS NOT NULL),因为空判断将导致全表扫描,而不是索引扫描。对于空判断这种情况,可以考 虑对这个列创建数据库默认值。
在where子句中使用 IS NULL 或 IS NOT NULL 判断,索引将被放弃使用,会进行全表查询。
如SQL:SELECT id FROM A WHERE num IS NULL 优化成num上设置默认值0,确保表中num没有null值,
然后SQL为:SELECT id FROM A WHERE num=0
8、where子句使用or的优化
很多时候使用union all 或 nuin(必要的时候)的方式替换“or”会得到更好的效果。where子句中使用了or,索引将被放弃使用。
如SQL:SELECT id FROM A WHERE num =10 or num = 20
优化成:SELECT id FROM A WHERE num = 10 union all SELECT id FROM A WHERE num=20
9、where子句使用IN 或 NOT IN的优化

in和not in 也要慎用,否则也会导致全表扫描。
方案一:between替换in
如SQL:SELECT id FROM A WHERE num in(1,2,3)
优化成:SELECT id FROM A WHERE num between 1 and 3
方案二:exist替换in
如SQL:SELECT id FROM A WHERE num in(select num from b )
优化成:SELECT id FROM A WHERE num exists(select 1 from B where B.num = A.num)
方案三:left join替换in
如SQL:SELECT id FROM A WHERE num in(select num from B)
优化成:SELECT id FROM A LEFT JOIN B ON A.num = B.num

10、where子句中对字段进行表达式操作的优化
不要在where子句中的“=”左边进行函数、算数运算或其他表达式运算,否则系统将可能无法正确使用索引。
A:如SQL:SELECT id FROM A WHERE num/2 = 100
优化成:SELECT id FROM A WHERE num = 1002
B:如SQL:SELECT id FROM A WHERE year(addate) <2016
优化成:SELECT id FROM A where addate<‘2016-01-01’
11、任何地方都不要用SELECT *
select * from table ,用具体的字段列表替换"
",不要返回用不到的字段

12.B树和B+树的区别?
B树:每个节点都存储key和data,所有节点组成这棵树,并且叶子节点指针为null。
B+树:只有叶子节点存储data,叶子节点包含了这棵树的所有键值,叶子节点不存储指针。

高并发处理面试题

什么是 Http协议
超文本传输协议
Http协议组成部分
Http协议是基于TCP协议封装成超文本传输协议,包括请求(request)和响应(response),http协议请求(request)分为请求参数(request params)和方法类型(request method)、请求头(request hearder)、请求体(request body) ,
响应(response)分为 响应状态(response state)、响应头(response header)、响应体(response body)等.
TCP与UDP区别
udp:
a、是面向无连接, 将数据及源的封装成数据包中,不需要建立连接
b、每个数据报的大小在限制64k内
c、因无连接,是不可靠协议
d、不需要建立连接,速度快
tcp:
a、建议连接,形成传输数据的通道.
b、在连接中进行大数据量传输,以字节流方式
c 通过三次握手完成连接,是可靠协议
d 必须建立连接m效率会稍低

TCP握手协议
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),
即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,
客户端和服务器进入ESTABLISHED状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据,
谈谈七层网络模型
应用层:客户端的各种应用、app;
表示层:进行数据的格式区分,如图片、编码;
会话层:本地主机与远程主机的会话管理;
传输层:定义传输数据的协议端口号,TCP和UDP是这一层的协议;
网络层:进行逻辑地址寻址;
数据链路层:建立逻辑连接,进行硬件地址寻址;
物理层:建立物理连接;

范式
在设计数据库时,所需要满足的范式越多,那表的层次及结构也就越复杂,最终造成数据的处理困难。所以在使用范式的时候也要细细斟酌,是否一定要使用该范式,必须根据实际情况做出选择。一般情况下,我们使用前三个范式已经够用了,不再使用更多范式,就能完成对数据的优化,达到最优效果。
通俗的理解
第一范式就是属性不可分割,每个字段都应该是不可再拆分的。
第二范式就是要求表中要有主键,表中其他其他字段都依赖于主键,因此第二范式只要记住主键约束就好了。
第三范式就是要求表中不能有其他表中存在的、存储相同信息的字段,通常实现是在通过外键去建立关联,因此第三范式只要记住外键约束就好了

进入方法之前,就一定要先加一个锁,这种我们为称之为悲观锁。悲观锁总认为,如果不事先加锁的话,就会出事
而乐观锁却相反,认为不加锁也没事,我们可以先不加锁,如果出现了冲突,我们在想办法解决
HTTP 请求响应过程
1.1 浏览器根据域名解析IP地址
1.浏览器缓存:
2.系统缓存:
3.路由器缓存:
4.ISP(互联网服务提供商) DNS缓存
1.2 浏览器与WEB服务器建立一个TCP连接
TCP的3次握手。
1.3 浏览器给WEB服务器发送一个HTTP请求
一个HTTP请求报文由请求行(request line)、请求头部(headers)、空行(blank line)和请求数据(request body)4个部分组成。
1.3.1 请求行
请求行分为三个部分:请求方法、请求地址URL和HTTP协议版本,它们之间用空格分割。例如,GET /index.html HTTP/1.1。
1.请求方法
GET、POST
2.URL
URL:统一资源定位符,是一种资源位置的抽象唯一识别方法。
组成:<协议>://<主机>:<端口>/<路径>
端口和路径有事可以省略(HTTP默认端口号是80)

3.协议版本
协议版本的格式为:HTTP/主版本号.次版本号,常用的有HTTP/1.0和HTTP/1.1
1.3.2 请求头部

1.3.3 请求数据
1.4 服务器端响应HTTP请求,浏览器得到HTML代码
HTTP响应报文由状态行(status line)、相应头部(headers)、空行(blank line)和响应数据(response body)4个部分组成。
1.4.1 状态行
状态行由3部分组成,分别为:协议版本、状态码、状态码扫描。其中协议版本与请求报文一致,状态码描述是对状态码的简单描述。
1.4.2 响应头部

1.4.3 响应数据
1.5 浏览器解析HTML代码,并请求HTML代码中的资源
1.6 关闭TCP连接,浏览器对页面进行渲染呈现给用户
能满足数据库数据大量存储,提高了查询性能的数据库中间件mycat:做数据库集群,提高查询性能,将一个数据库的数据分散到不同的数据库中存储.用于支持数据库读写分离、分片的数据库中间件。
MyCAT主要是通过对SQL的拦截,然后经过一定规则的分片解析、路由分析、读写分离分析、缓存分析等,然后将SQL发给后端真实的数据块,并将返回的结果做适当处理返回给客户端。
核心技术(分库分表)
(1)数据库分片(Sharding)
通过某种条件,将同一数据库中的数据分散的存储到多个数据库中,已达到分散单台数据库设备负载的效果,这就是数据库分片。
a.水平拆分(特定字段取模)
同一张表的不同记录,根据表的某个字段的某种规则拆分到多个数据库(主机)上,这既是水平拆分。
b.垂直拆分
不同的表切分到不同的数据库(主机)上,这就是垂直拆分。
一般按照业务表进行分类,划分为不同的业务、模块库,耦合度越低,越容易做垂直拆分
在mysql主从复制实现的基础上,利用mycat做读写分离,分析对应的SQL,写操作时会连接主数据库,读操作时连接从数据库。

Elasticsearch 作为搜索引擎
反向索引又叫倒排索引,是根据文章内容中的关键字建立索引。
搜索引擎原理就是建立反向索引。
Elasticsearch 在 Lucene 的基础上进行封装,实现了分布式搜索引擎。
Elasticsearch 中的索引、类型和文档的概念比较重要,类似于 MySQL 中的数据库、表和行。
Elasticsearch 也是 Master-slave 架构,也实现了数据的分片和备份。
Elasticsearch 一个典型应用就是 ELK 日志分析系统。
关系数据库 ⇒ 数据库 ⇒ 表 ⇒ 行 ⇒ 列(Columns)

Elasticsearch ⇒ 索引(Index) ⇒ 类型(type) ⇒ 文档(Docments) ⇒ 字段(Fields)

而Lucene在term dictionary的基础上添加了term index来加速检索,term index以树(trie树)的形式缓存在内存中。从term index查到对应的term dictionary的block位置之后,再去磁盘上找term,大大减少了磁盘的random access次数。

Mybatisplus 操作数据库
对单表的操作进行了封装,有点类似hibernate,简化了对数据库的操作
Mybatis-Plus(简称MP)是一个Mybatis的增强工具,在 Mybatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
mybatis-plus不仅仅封装了基本的CRUD操作,还内置了防SQL注入操作、常用的分页插件,还有我最喜欢的ActiveRecord模式:Active Record 是一种数据访问设计模式,它可以帮助你实现数据对象Object到关系数据库的映射。

算法:https://mp.weixin.qq.com/s/IAZnN00i65Ad3BicZy5kzQ

分布式事务(mq:rabbitmq)transaction:用spring的话一个注解(@Transactional)就能搞定。大事务 = 小事务 + 异步
分布式事务是指操作多个数据库之间的事务
RocketMQ 事务消息设计则主要是为了解决 Producer 端的消息发送与本地事务执行的原子性问题,事务消息作为一种异步确保型事务, 将两个事务分支通过 MQ 进行异步解耦
1.事务发起方首先发送 prepare 消息到 MQ。
2.在发送 prepare 消息成功后执行本地事务。
3.根据本地事务执行结果返回 commit 或者是 rollback。
4.如果消息是 rollback,MQ 将删除该 prepare 消息不进行下发,如果是 commit 消息,MQ 将会把这个消息发送给 consumer 端。
5.如果执行本地事务过程中,执行端挂掉,或者超时,MQ 将会不停的询问其同组的其它 producer 来获取状态。
6.Consumer 端的消费成功机制有 MQ 保证。

RabbitMQ解决分布式事务原理:采用最终一致性原理。
需要保证以下三要素
1、确认生产者一定要将数据投递到MQ服务器中(采用MQ消息确认机制)
2、MQ消费者消息能够正确消费消息,采用手动ACK模式(注意重试幂等性问题)
3、如何保证第一个事务先执行,采用补偿机制,在创建一个补单消费者进行监听,如果订单没有创建成功,进行补单。

如果生产者投递消息到MQ服务器成功
场景1:如果消费者消费消息失败了,生产者是不需要回滚事务的。
解决方案:消费者采用手动ack应答模式,采用MQ进行补偿重试机制,注意MQ补偿幂等性问题。
问题:如何确保生产者投递消息到MQ服务器一定能成功?
解决方案:confirm机制(确认应答机制)。
场景2 如果生产者投递消息到MQ服务器失败,如何解决?
解决方案:使用生产者重试机制进行发消息,注意幂等性问题。
场景3 如何保证一个事务先执行,生产者投递消息到MQ服务器成功,消费者消费成功了,但是订单却回滚了。
解决方案:补单机制。

分布式锁(redission)
Redis分段锁
Rabbitmq怎么用
// 1.校验 交易密码,余额,参数校验
// 2.定义一个bean订单对象,生成订单ID(此步不需要保存数据库)
// 3.使用redis 存值: key:订单id,val(1) 【val:1处理中,2处理完成:3处理失败】
// 4.MQ消息推送(订单对象)
// 5.返回前端 订单ID

// 1.取出消息,(订单,用户信息)
// 查询redis 订单状态 :判断val 是否为1 ,为1则往下处理 , 不为1则终止程序,同时清除redis
// 2.扣除用户余额,保存订单
// redis 订单状态值 val 改成 2 成功

// 1.写一个接口给前端调用:查询订单支付状态,通过订单ID
// 2.接口: 查询reids订单状态返回前端
// 订单状态 1 处理中,不做处理,返回状态
// 订单状态 2 已完成,需要处理 将redis订单信息删除,返回前端成功
// 订单状态 3 处理失败,需要要出 将redis订单信息删除,返回前端失败

Nginx反向代理,负载均衡

多线程
线程池
ExcutorService类中submit(r c),excute®方法的区别
ExecutorService es = Executors.newFixedThreadPool(10);
高并发
redis
Dubbo,zookeeper分布式服务
MybatisPlugs ,Elasticsearch 作为搜索引擎,Mycat数据库中间件
熟悉 Linux 常用命令操作 / 环境部署
算法
熟悉项目
自我介绍

Springmvc的传参方式
传统传参方式
request.getParameter(“参数名”) PathVariable注解(/) requestparam注解 requestbody
值相等
explain type ALL、index、range、 ref、eq_ref、const、system、NULL(从左到右,性能从差到好)

把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位

了解的网络攻击手段,可以怎么预防
实现服务器集群的负载均衡方案——DNS域名解析。
cookie/session的出现就是为了解决http协议无状态的弊端,为了让客户端和服务端建立长久联系而出现的
cookie/session的区别与联系
区别:
1、Cookie和Session都是会话技术,Cookie是运行在客户端,Session是运行在服务器端。
2、Cookie有大小限制以及浏览器在存cookie的个数也有限制,Session是没有大小限制和服务器的内存大小有关。cookie只能存放4k的数据,而session理论上没有做限制
3、Cookie有安全隐患,通过拦截或本地文件找得到你的cookie后可以进行攻击。
4、Session是保存在服务器端上会存在一段时间才会消失,如果session过多会增加服务器的压力。
联系:
session虽说存放在服务器端,但是仔细看刚才的执行流程你会明白,session是依赖于cookie的。

cookie/session执行流程(这才是重点)
cookie执行流程
当你去访问应用的时候,来到服务器。服务器设置一个cookie(后边介绍api),在做响应的时候会通过set-cookie响应头将cookie带给浏览器。
来到浏览器,浏览器会将此数据保存起来,接下来再次去访问服务器的时候,浏览器会根据cookie的path属性(后边api介绍)将这些数据带回去(设置了一个叫做cookie的请求头),来到服务器,服务器有对应的api获取这些值,有了值就知道用户是谁了。
session执行流程
浏览器发起一个请求到服务器,服务器先检查你是否携带了一个叫做JSESSIONID的cookie。
如果有携带,会将此cookie的值取出来(比如为aaa123),然后从服务器的session池中找到ID为aaa123的session返回给调用者。
如果没有携带这个JSESSIONID的cookie,那么服务器将会自动创建一个session对象并且生成一个随机字符串(如aaa123)作为此session的ID保存到session池中。在服务器为客户端浏览器作响应的时候自动创建一个键为“JSESSIONID” 值为“aaa123”的cookie对象让浏览器储存起来以便下次再访问的时候带过来。

Linux命令
大全:https://blog.csdn.net/luansj/article/details/97272672

其他的题目
一、Java基础
1.Java和C语言有什么区别?Java好在哪里?
2.怎么理解Java的跨平台性,一次编译到处运行?
3.面向对象和面向过程的区别?
4.如何理解面向对象三大特性:封装、继承、多态?
5.类继承会有什么问题吗,一般什么情况下才会去用继承?
6.为什么重写equals方法还要重写hashcode方法?
7.深克隆和浅克隆
8.反射相关
9.注解的实现原理
10.Lambda表达式的优缺点?
11.Stream流式编程的好处?终止方法和延迟方法的区别是?终止方法存在的意义是什么?
二、Java集合
1.HashMap底层实现(JDK1.7使用数组+链表;JDK1.8使用数组+链表+红黑树)
2.HashMap为什么要引进红黑树?为什么不用其他的平衡二叉树之类的?红黑树的优势在哪里?(AVL树的旋转比红黑树的旋转更加难以平衡和调试,需要更高的旋转次数)
3.链表会转化为红黑树的两个条件是?(①链表的长度达到8;②HashMap底层使用的table数组长度length达到64;如果不满足后者,将会触发扩容方法)
4.链表长度大于8转化为红黑树,小于6红黑树转化为链表;为什么不直接设置成大于8转化成红黑树,小于8转化成链表;(中间有个差值7进行过渡是为了避免链表和树频繁转换,如果一个HashMap不停的插入、删除元素,链表个数在8左右徘徊,就会频繁的发生树转链表、链表转树,效率会很低)
5.把链表转化为红黑树的阈值是8,为什么不设置成其他值?(遵循泊松分布,链表长度超过8的概率非常小)
6.HashMap扩容机制,即resize方法?(JDK 1.7 会重新计算每个元素的哈希值,JDK1.8是通过高位运算(e.hash & oldCap)来确定元素是否需要移动,如果运算结果值为0,那么元素扩容后位置不变,结果值为1表示元素在扩容时位置发生了变化,新的下标位置等于原下标位置 + 原数组长度)
7.HashMap添加元素的步骤(put方法)、计算集合元素个数(size方法)
8.HashMap为什么是线程不安全的?(同时新增元素、同时扩容导致数据丢失,jdk1.7头部倒序插入出现死循环导致CPU占用100%)
9.HashMap默认的加载因子是0.75,为什么不设置成1或者0.5(从容量和性能考虑)
10.HashMap发生哈希冲突,新节点是插入到链表头部还是链表的尾部,头部倒序插入死循环是怎么产生的?(jdk1.7采用头部倒序插入,会导致死循环;jdk1.8使用尾部正序插入)
11.Hashtable怎么控制key value 不能为null?(当调用put方法时,首先会判断value是否为null,为null的话直接抛出空指针异常;对于key,由于Hashtable计算hash值是int hash = key.hashCode();直接取对象的hashcode,key为null就会报空指针异常;而HashMap计算hash值是return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16),key为null则hash值为0)
12.ConcurrentHashMap底层采用的结构(分jdk1.7和jdk1.8),jdk1.7和jdk1.8分别采用什么方式实现线程安全?(jdk1.7采用分段锁,也就是为每一个segment加上ReentrantLock锁;jdk1.8使用的是CAS机制加上synchronized锁)
13.ConcurrentMap中的size方法是如何实现的?多线程操作下,如果一个线程在查size方法,一个线程在执行put方法,底层是如何控制每次计算出来的值是正确的?
14.HashSet的底层实现?(基于HashMap来实现的,new 一个 HashSet对象底层实际就是new了一个HashMap,并且使用默认的初始容量16和默认的加载因子0.75;当我们往HashSet里面添加一个元素其实就是往HashMap里面put了一个元素,并且是以key存在的,HashMap的value值都是一样的,是一个静态常量PRESENT,源码为:private static final Object PRESENT = new Object(); )
15.BlockingQueue(阻塞队列)如何实现生产者消费者模型?
16.线程安全的List有哪些?(Vector、CopyOnWriteArrayList、还可以使用Collections类的synchronizedList方法将线程不安全的List转为线程安全的)
17.为什么ArrayList查询速度快?(ArrayList底层是基于数组实现,可以根据元素下标进行查询,查询方式为(数组首地址+元素长度*下标,基于这个位置读取相应的字节数就可以了),如果数组存的是对象,怎么根据下标定位元素所在位置?(对象数组每个元素存放的是对象的引用,而引用类型如果开启指针压缩占用4字节,不开启则占用8字节,所以对象数组同样适用上面的公式)
18.ArrayList的扩容?(ArrayList底层是基于数组实现,所以创建ArrayList会给数组指定一个初始容量,默认值为10,因为必须指明数组的长度才能给数组分配空间;由于数组的特性,ArrayList扩容是创建一个更大的数组,然后将原来的元素拷贝到更大的数组中,扩容的核心方法是Arrays.copyOf方法)
19.ArrayList和LinkedList的区别,添加一个元素的时间复杂度各是多少,既然ArrayList添加元素效率没有LinkedList高,为什么我们平时用的比较多的还是ArrayList?
20.一般什么情况下会用ArrayList,什么情况用LinkedList?(如果只是普通的存取元素多用ArrayList,LinkedList一般用作栈、队列)
21.将一个Map集合变成栈,如何实现?(我的思路是用TreeMap去实现,key存的是要入栈的元素,value存的是可以记录他们入栈的一个先后顺序的,例如时间戳,然后重写Comparator比较器,根据value进行排序,遍历Map时,先进的后面出)
22.Map集合有迭代器吗?遍历输出Map中所有元素有哪些方法?
三、多线程和Java锁
1.线程池的三大方法、七大参数、四种拒绝策略(可以顺带谈一下阿里巴巴开发手册对于线程池使用的规范)
2.最大线程数如何定义?(从CPU密集型和IO密集型考虑)
3.线程池的五种状态(Running、Shutdown、Stop、Tidying、Terminated)
4.线程池的任务执行流程、excute方法和 submit方法的区别?
5.Synchronized锁和Lock锁的区别
6.Java线程虚假唤醒(线程本应该处于wait状态却被唤醒了,解决方案是wait方法应该用while循环包裹,不用if)
7.JMM的三种特性(原子性、可见性、有序性)、主内存和线程工作内存的八种交互动作
8.volatile如何保证可见性(MESI缓存一致性协议)
9.volatile如何保证有序性(内存屏障——lock前缀指令)
10.synchronized和volatile的区别(volatile是一种非锁机制,这种机制可以避免锁机制引起的线程上下文切换和调度问题。因此,volatile的执行成本比synchronized更低;volatile只能保证可见性有序性;synchronized可以保证原子性可见性有序性)
11.JUC包中的原子类如何保证原子性?(CAS机制和自旋锁)
12.CAS机制,会引发什么问题,如何解决ABA问题?(CAS会导致ABA问题,解决ABA问题是使用版本号机制)
13.悲观锁和乐观锁的区别,应用?(java中的Synchronized关键字和lock锁使用的都是悲观锁;CAS机制是乐观锁的一种实现方式)
14.公平锁和非公平锁(公平锁按照先来先服务,不会出现饥饿;非公平锁会导致饥饿,但是效率更高,默认的锁都是非公平的)
15.自旋锁和互斥锁,自旋锁的优缺点?(优点:减少上下文切换和用户态内核态的切换带来的开销;缺点:循环等待消耗CPU)
16.可重入锁和不可重入锁(不可重入锁容易导致死锁发生,大多数锁都是可重入的,例如Synchronized锁和ReentrantLock)
17.JDK1.6 Synchronized锁升级(偏向锁—轻量级锁—重量级锁)
18.Synchronized锁的底层实现,锁的是什么,其它线程如何判断该锁已经被占用了?
19.死锁产生的四个必要条件以及死锁的处理策略
四、Mysql
1.Myisam和InnoDB存储引擎的区别?(Myisam不支持外键也不支持事务,支持的是表锁,当执行select操作时,自动给涉及的表加表锁,当执行增删改操作,自动给涉及的表加写锁;InnoDB支持外键也支持事务,支持的是行锁,当执行select操作时,不加任何锁,当执行增删改操作,自动给涉及的行加写锁)
2.间隙锁是什么?行锁升级为表锁的情况?
3.InnoDB的行锁有哪些?锁住的是行还是索引?(Record Lock、Gap Lock、Next-Key Lock;锁住的是索引,而不是行)
4.为什么可重复读隔离级别也可以解决幻读?(通过Next-Key Lock可以消除幻读)
5.并发事务处理带来的四种问题和事务的隔离级别(丢失更新、脏读、不可重复读、幻读;读未提交、读已提交、可重复读、串行化)
6.如何理解Mysql默认的事务隔离级别可重复读?
7.事务的ACID属性是如何实现的?(原子性通过回滚日志undo log实现;持久性通过重做日志redo log实现;隔离性通过锁和MVCC实现;而一致性则是通过原子性、隔离性、持久性来实现,只有满足这三个特性,才能实现事务的一致性)
8.聚簇索引、非聚簇索引、回表查询、覆盖索引;
9.索引失效的情况?(违反最左前缀法则、范围查询右边的列索引失效、字符串不加单引号、对索引列进行运算、头部模糊匹配、使用不等于!=或者<>)
10.explain分析执行计划、SQL语句的优化
11.mysql三大范式(1NF即原子性,2NF即消除部分依赖,3NF即消除传递依赖)
12.mysql索引的底层实现,为什么用B+树不用B树?(B+树IO次数更少、更适合范围查询、查询效率更加稳定)
13.哈希表查找速度不是更快吗,为什么不直接使用哈希表来做索引的底层数据结构?(哈希表不支持范围查找)
五、Redis
1.Redis五种基本数据类型的使用场景
2.缓存穿透、缓存击穿、缓存雪崩
3.Redis的过期策略和内存淘汰机制
4.Redis的zset底层数据结构,为什么用跳跃表而不用红黑树
六、框架相关
1.Spring AOP的实现原理?(基于动态代理模式,如果目标类实现了接口,那么使用基于接口的动态代理,否则使用基于子类/cglib的动态代理)
2.Spring AOP 的具体加载步骤?
3.AOP和OOP的区别,分别适用什么场景?
4.Spring Bean的作用域,Spring Bean的生命周期(Bean的实例化—初始化Bean—使用Bean—Bean的销毁)
5.Spring容器创建对象的两种时机,各有什么优缺点?(一是Spring容器启动时创建Bean,二是调用getBean方法时创建)
6.SpringMVC的执行流程(可以顺带讲一下适配器模式)
7.Mybatis的一级缓存和二级缓存?
8.Mybatis中#和$的区别?
9.Mybatis如何实现批量插入?
10.Mybatis的xml文件中,sql语句可以使用直接使用大于号小于号吗?应该用什么符号代替?
七、设计模式
1.代理模式(应用:一是创建多线程的方式之使用Runnable接口应用了静态代理;二是Spring AOP应用了动态代理)
参考文章:https://blog.csdn.net/can_chen/article/details/107827629
2.适配器模式(应用:一是创建多线程的方式之使用Callable接口;二是SpringMVC中的HandleAdapter)
参考文章:https://blog.csdn.net/can_chen/article/details/106968769
3.工厂模式(应用:一是Spring IOC;二是Mybatis中的SqlSessionFactory就用到了简单工厂模式)
参考文章:https://blog.csdn.net/can_chen/article/details/105924115
4.单例模式(一般会需要手撕单例模式的代码,主要谈DCL模式关于指令重排的问题,以及反射可以破坏除枚举以外的几种方式;单例模式的应用有:一是Spring Bean的作用域默认就是使用单例模式;二是Mybatis中的ErrorContext类也使用了单例模式,这个类用于记录线程执行环境的错误信息)
参考文章:https://blog.csdn.net/can_chen/article/details/105049999
5.装饰器模式(应用:JAVA的IO流就用到了装饰器模式)
参考文章:https://blog.csdn.net/can_chen/article/details/105786680
6.装饰器模式和代理模式的区别?
参考文章:https://www.cnblogs.com/yanggb/p/10952843.html
7.策略模式(应用:Arrays类的sort方法就用到了策略模式,Comparator接口就是一个策略接口,将排序方法定义成一个策略,用户可以自定义排序策略,可以是升序也可以是降序)
参考文章:https://blog.csdn.net/can_chen/article/details/106745298
8.观察者模式与发布订阅模式的区别?(JDK源码已经为我们提供好了一套观察者模式,Observer就是观察者接口,Observable类是被观察者,是一个具体类,提供了一个存放所有观察者角色的集合,并且也提供了添加观察者、移除观察者、通知观察者等方法)
参考文章: https://blog.csdn.net/hf872914334/article/details/88899326
八、网络
1.TCP三次握手和四次挥手的过程,每次发送的包的内容,客户端和服务端的状态?
2.TCP三次握手可以携带数据吗?TCP协议运行时阶段?
3.为什么是三次握手,可以四次握手或者两次握手吗?
4.为什么握手是三次,而挥手要四次?
5.TCP四次挥手为什么需要TIME-WAIT阶段等待2MSL,是哪一方有TIME-WAIT阶段?(主动释放释放连接的那端)
6.TCP的长连接和短连接(http://blog.sina.com.cn/s/blog_6d39b5be0101k6v4.html)
7.半连接队列和全连接队列,什么是syn flood攻击,如何应对syn flood攻击?(https://www.jianshu.com/p/ff26312e67a9)
8.在浏览器中输入一个网址回车后发生了什么?(https://www.cnblogs.com/tisikcci/p/5866753.html)
9.域名解析过程的递归查询和迭代查询(https://blog.csdn.net/weixin_42061048/article/details/80170991)
10.浏览器输入一个网址之后,按照TP/IP参考模型,从应用层到网络层各使用了哪些协议?
(应用层:HTTP、DNS;传输层:TCP、UDP;网络层:IP、ICMP、ARP)
11.ICMP协议的两个应用——Ping和Traceroute(https://www.jianshu.com/p/32bc2749a831)
12.IP地址和MAC地址有什么区别?
13.http和https的区别 (https://www.php.cn/faq/418162.html)
14.网站为什么要使用cookie和session;cookie和session有什么区别?
15.get请求和post请求的区别?
16.TCP和UDP的区别以及各自的应用场景?
17.epoll和select的区别?
九、JVM
1.JVM内存模型(程序计数器、虚拟机栈、本地方法栈、堆、方法区)
2.JDK1.8做了哪些变化?(JDK1.7已经将原本位于永久代的字符串常量池移到堆中了,但是永久代的概念还存在,JDK1.8才彻底废除永久代,进而用元空间代替)
3.永久代和元空间,JDK1.8为什么要使用元空间代替永久代?
4.元空间溢出?(元空间不属于Java虚拟机,使用的是本地内存,存放的是类及方法的一些信息,动态加载类或者频繁加载类信息,但是没有及时卸载,会导致元空间溢出)
5.对象创建的两种方式(指针碰撞、空闲列表)、对象访问定位的两种方式(使用句柄、直接指针)
6.栈上分配与逃逸分析(JVM层面进行java性能优化的技巧)
7.判断对象是否存活的两种方式,引用计数法的缺点?(引用计数法、可达性分析法)
8.关于Object类的finalize()方法(jvm自动执行,无需手动调用,只能执行一次).
9.java的四种引用(强引用、软引用、弱引用、虚引用)
10.三种垃圾回收算法,各自的优缺点(标记-清除法、标记-复制法、标记-整理法)
11.Minor GC 和 Full GC 的区别,触发条件,以及空间分配担保策略?
12.内存溢出和内存泄露(内存泄露的堆积会导致内存溢出)
13.JVM参数调优(-Xms、-Xmx、-Xss、-XX:NewRatio、-XX:SurvivorRatio、-XX:+PrintGCDetails、-HeapDumpOnOutOfMemory)
14.发生OOM如何解决(首先尝试通过JVM参数调优扩大堆内存空间;再者dump出堆内存存储快照,使用JProfile工具进行分析)
15.垃圾收集器(CMS问的居多,另外,如果谈及发生gc会给用户带来什么不好的体验,可以谈谈Stop the World)
16.类加载机制的过程,准备阶段做了哪些工作?(准备阶段会给类的静态变量分配内存(方法区)并赋初值,如果类的静态变量被final修饰,那么初始化的值就不是零值,而是声明的值)
17.类的双亲委派模型定义,双亲委派模型的好处?如何破坏类的双亲委派模型?
十、操作系统
1.linux的僵尸进程和孤儿进程的区别,如何清理僵尸进程?(kill僵尸进程的父进程)
2.如何查看僵尸进程信息?如何统计僵尸进程数量?(ps - ef | grep defunct;ps -ef | grep defunct | wc - l)
3.并发和并行的区别?
4.进程和线程的区别?
5.进程通信的方式有哪些?(管道、消息队列、共享内存、信号量、套接字Socket)

你可能感兴趣的:(研发)