冲冲冲冲冲

目录

java基础

面向对象

集合

线程

异常

IO

反射

MySQL

SpringMVC

1.SpringMVC常用的注解有哪些?

2.说说你对Spring MVC的理解

Spring

1. spring是什么?

2.Autowired和Resource关键字的区别?

3.说说你对Spring的IOC是怎么理解的?

3.谈谈你对Spring的AOP理解

4.什么是通知呢?有哪些类型呢?

5.Spring基于xml注入bean的几种方式?

6.Spring框架中都用到了哪些设计模式?

7.BeanFactory和ApplicationContext有什么区别?

8.什么是循环依赖,Spring 是怎么解决循环依赖的?

9.解释一下spring bean的生命周期

10.说说spring事务的隔离级别

11.Spring 事务实现方式

Mybatis

1.什么是MyBatis

2.#{}和${}的区别是什么?

3.当实体类中的属性名和表中的字段名不一样 ,怎么办 ?

4.mybtis的常见封装策略

5.Mybatis中的转义标签

6.如何批量处理相同的多个数据

7.Xml映射文件中,除了常见的select|insert|updae|delete 标签之外,还有哪些标签?

8.resultType和resultMap的区别

9.MyBatis实现一对一有几种方式?具体怎么操作的?

10.说说Mybatis的缓存机制:

Redis

1.什么是 Redis?

2.redis常用五种数据类型?

3.Redis 持久化方式有哪些?以及有什么区别?

4.如何选择redis的持久化方式

5.怎么使用 Redis 实现消息队列?

6.什么是BigKey?怎么解决

7.什么是redis缓存雪崩,怎么解决?

8.什么是缓存穿透,怎么解决?

9.什么是缓存击穿,怎么解决

Nginx

1.简述一下什么是Nginx

2.反向代理

3.负载均衡

4.负载均衡中还有三大策略

5.动静分离

RabbitMQ

1.为什么要使用MQ

2.RabbitMQ的工作模式

3.如何保证消息的可靠传输?如果消息丢了怎么办

4.怎么解决当一个消费方在处理一个消息时过长时,MQ还是会采用轮询的方式对多个消费方进行发送消息

5.如何保证消息的顺序性

SpringCloud


java基础

面向对象

1.重载和重写的区别

/*重载: 发生在同一个类中,方法名必须相同。参数列表必须不同(个数不同、类型不同、参数排序不同)。
     方法的返回类型、修饰符可以相同也可以不同。但是仅仅是返回类型不同就不是重载*/
     
重写: 发生在父子类中。遵循两同、两小、一大的注意事项。
      两同:方法名、参数列表相同。
      两小: 子类返回值范围、异常抛出范围要小于等于父类
      一大: 子类的访问修饰符范围要大于等于父类。如果父类的方法修饰符是private,子类不能重写此方法

2.什么是面向对象

对比面向过程,是两种不同的处理问题的角度。
面向过程更注重事情的每一个步骤及顺序
面向对象更注重事情有哪些参与者(对象)、及各自需要做什么
面向对象的三大特性:
    封装:该藏的藏、该漏的漏。隐藏对象的属性和实现细节,仅仅对外提供公共的方法(get、set)
    继承:可以使子类具有父类的属性和方法,还可以在子类中重新定义,追加属性和方法
    多态:同一对象在不同时刻具有不同的状态。
    多态的前提:1.有继承或实现关系 2.有方法重写 3.有父类引用指向子类对象

3.==和equals比较

==对比的是栈中的值,基本数据类型是变量值,引用类型是堆中内存对象的地址
equals:Object类中默认也是采用==比较的,如果没有重写,equals与==没有什么区别。如果重写,则比较的是内容。在String底层默认是重写了euqals方法的

4.String、StringBuffer、StringBuilder

String 是不可变类,String对象一旦被创建,其值不能被改变。每次操作都会产生新的String对象
StringBuffer、StringBuilder是可变类,都是在原对象上操作的。不会产生新的对象
在线程方面:因为StringBuffer的方法都是synchronized修饰的,所以它是线程安全的,而StringBuilder是线程不安全的。
在性能方面:StringBuilder > StringBuffer > String

5.接口和抽象类的区别

抽象类只能继承一个,接口可以实现多个。
抽象类中可以存在普通方法,半普半抽、全抽。接口在jdk7及以前只能存在抽象方法、jdk8之后还可以存在默认方法
抽象类中的成员变量可以是各种类型的,而接口的成员变量只能是public static final 类型的
抽象类表达的是is a的关系,主要实现代码的复用性
接口表达的是like a 的关系,主要表达的是对类的行为进行约束

6.Java 创建对象有几种方式

1.使用new关键字                                      eg:User user=new User();
2.使用反射方式创建对象,使用 newInstance()               eg:
3.使用克隆clone()方法创建对象
4.使用反序列化创建对象

集合

1.List

元素有序,按照对象存入的顺序保存对象;可重复,允许多个Null元素对象。
可以使用迭代器(Iterator)取出所有元素,再逐一遍历。
也可以使用get(int index)获取指定下标的元素

2.Set

元素无序,不可重复,最多允许有一个null元素对象,只能使用迭代器取得所有元素,再逐一遍历各个元素

3.ArrayList 、LinkedList、Vector的区别

ArrayList : 底层封装了Object类型的数组,属于连续内存存储,适合下标随机访问,故查询快,增删慢。
			因为源码中没有synchronized关键字,线程是不安全的。
			其扩容机制采用的是位运算符的形式。
			当创建ArrayList对象时,如果使用的是无参构造方法,初始容量为0,第一次扩容为10,再扩容为其1.5倍
			如果使用的是指定大小的有参构造方法,则初始容量为指定大小,再扩容依旧是其1.5倍
LinkedList: 底层维护了一个双向循环链表和双端队列,链表中的每一个元素都使用引用的方式来记住它的前一个元素和后一个元素,从而将所			有元素连接起来。当插入、删除一个元素时,只需要修改元素之间的引用关系即可,故增删快,查询慢。
			因为源码中没有synchronized关键字,线程是不安全的。
		    遍历LinkedList的时候,必须使用迭代器,不能使用for循环。因为for循环使用get()获取一个元素时,都需要给linkedList			 重新遍历一次,消耗大
Vector:
		线程是同步的,即线程安全。因为其操作方法有synchronized关键字,但是效率慢
		其底层是Object类型的数组,扩容机制采用的是三元运算符,即原数组长度+原数组长度

4.HashMap

线程不安全,key、value结构,key值不允许重复,如果重复,对应的value会被覆盖,value无序,允许key和value为null
HashMap的底层实现在jdk8之前是数组+链表实现。jdk开始链表高度到8、数组长度超过64,链表转变为红黑树。
实现流程是:
	1. 添加一个元素时,会先得到其hash值,再转换成索引值
    2. 然后存储数据表table,看这个索引值对应的位置有没有元素
    3. 没有的话,直接加入。
    4. 有的话,通过equals比较,如果相同,放弃添加。如果不相同,添加到已存放元素后面,形成链表
    5. 当链表长度>=8 并且table>=64时,会进化成红黑树
扩容机制为:第一次扩容到16,当元素到达其临界值12时,再次扩容为其2倍

5.Hashtable

线程安全;key、value不能为null;底层是数组+链表+树的结构;初始容量为11,扩容到初始容量的2倍+1

6.ConcurrentHashMap


线程

1.Java中实现多线程有几种方法

1.继承Thread类
2.实现Runable接口
3.实现Callable接口(实现Runnable接口与实现Callable接口的方式基本相同,只是Callable接口里定义的方法返回值,可以声明抛出异
常)
4.线程池的方式创建

2.如何停止一个正在运行的线程

1.使用退出标志,使线程正常退出,也就是当run方法完成后线程终止;
2.使用interrupt方法中断线程 ;
3.使用stop方法强行终止(不推荐使用该方法,目前该方法已作废)。

3.并发的三大特性

原子性:在一个操作中cpu不可以在中途暂停然后再调度,即不被中断操作,要不全部执行完成,要 不都不执行。就好比转账,从账户A向账户B转1000元,那么必然包括2个操作:从账户A减去1000元, 往账户B加上1000元。2个操作必须全部完成
关键字:synchronized

可见性:当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。
关键字:volatile、synchronized、final

有序性:虚拟机在进行代码编译时,对于那些改变顺序之后不会对最终结果造成影响的代码,虚拟机不一定会按 照我们写的代码的顺序来执行,有可能将他们重排序。实际上,对于有些代码进行重排序之后,虽然对 变量的值没有造成影响,但有可能会出现线程安全问题
关键字:volatile、synchronized

4.为什么调用是start方法,而不是run方法

因为调用start方法是启动线程,再去调用start0方法,再由start0方法调用线程类的run方法。
而直接调用run方法的话,run方法其实就是一个普通的方法,没有真正的启动线程,会把run方法执行完,才会先下执行

5.线程的生命周期、线程有几种状态

线程通常有七种状态,创建,就绪,运行、阻塞、等待状态、超时等待状态和死亡状态。
1.新建状态(New):新创建了一个线程对象。 
2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start方法。该状态的线程位于 可运行线程池中,变得可运行,等待获取CPU的使用权。 
3.运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。 
4.阻塞状态(Blocked):也叫同步阻塞,运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放 入“锁池”中,等待获得锁,再次进入就绪状态。
5. 等待状态:运行的线程执行wait方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待 池”中。进入这个状态后,是不能自动唤醒的,必须依靠其他线程调用notify或notifyAll方法才能被唤醒,唤醒后再次进入就绪状态
6. 超时等待状态:运行的线程执行sleep或join方法或者发出了I/O请求时,JVM会把该线程设置为超时等待状态,当sleep状态超时、join等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态
7.死亡状态(Dead):线程执行完了或者因异常退出了run方法,该线程结束生命周期。

冲冲冲冲冲_第1张图片

 

6.请说出与线程同步以及线程调度相关的方法

1.wait():使一个线程处于等待状态,并且释放所持有的对象的锁
2.sleep(): 是一个正在运行的线程处于超时等待状态
3.notify():唤醒一个处于等待状态的线程
4.notifyAll():唤醒所有处于等待状态的线程

7.sleep()和wait()有什么区别?

两者都可以暂停线程的执行
	sleep()方法,是属于Thread类中的。wait()方法,属于Object类中的
	sleep()不释放锁,wait()释放锁
	wait()方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上notify()或者notifyAll()
	sleep()方法执行完成后,线程会自动苏醒

8.如何保证多线程的运行安全

1.使用自动锁synchronized
2.使用安全类.eg:原子类:AtomicInteger
3.使用手动锁Lock

9.自己是怎么使用synchronized关键字

1. 修饰实例方法: 作用于当前对象实例加锁,进入同步代码前要获得当前对象实例的锁
2. 修饰静态方法: 也就是给当前类加锁,会作用于类的所有对象实例
3.修饰代码块: 指定加锁对象,对给定对象加锁,进入同步代码库前要获得给定对象的锁

异常

1.平时是怎么处理 Java 异常的

try-catch-finally
try 块负责监控可能出现异常的代码
catch 块负责捕获可能出现的异常,并进行处理
finally 块负责清理各种资源,不管是否出现异常都会执行
其中 try 块是必须的,catch 和 finally 至少存在一个标准异常处理流

2.throws和throw的区别

throws关键字通常被应用在声明方法时,用来指定可能抛出的异常。多个异常可以使用逗号隔开。
throw关键字通常用在方法体中,并且抛出一个异常对象。

3.try-catch-finally中,如果catch中return了,finally还会执行嘛

会,因为不管有没有异常,finally中的代码都会执行。

4.常见的异常类有哪些?

1.空指针异常
2.SQLException
3.数据下标越界异常
4.IO异常

IO


反射

MySQL

1.数据库查询,如何实现行转列的查询

 使用GROUP BY和CASE语句
	首先,我们需要使用GROUP BY语句将数据按照需要的列进行分组。然后,使用CASE语句将分组后的数据进行转换。

2.mysql数据库引擎有哪些

查询mysql的所有存储引擎:SHOW engines
常用引擎有:	MYISAM、Innodb、Memory、MERGE
		MYISAM:	全表锁	拥有较高的执行速度,不支持事务,不支持外键,并发性能差
		Innodb: 行表锁 提供了具有提交、回滚和崩溃回复能力的事务安全,支持自动增长列,支持外键约束,并发能力强,处理效率低
		Memory: 全表锁 存储在内容中,速度快
		MERGE:	是一组MYISAM表的组合

SpringMVC

1.SpringMVC常用的注解有哪些?

@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中
的所有响应请求的方法都是以该地址作为父路径。
@RequestBody:注解实现接收http请求的json数据,将json转换为java对象。
@ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户

2.说说你对Spring MVC的理解

Spring

1. spring是什么?

Spring是一个轻量级的控制反转和面向切面的容器框架
	从大小和开销两个方面可以说spring是轻量级的
	控制反转技术可以达到松耦合的目的
	面向切面可以实现业务逻辑的各个部分的隔离
	可以管理bean对象的配置和声明周期说其是一个容器
	可以将简单的组件配置组合成复杂的应用方面说其是一个框架

2.Autowired和Resource关键字的区别?

 两者都是 在Spring/Spring Boot 项目中,用来进行依赖注入的注解。它们都提供了将依赖对象注入到当前对象的功能
 不同点:
 	1.来源不同 
 			@Autowired 是 Spring 定义的注解  @Resource 是 Java 定义的注解
 	2.依赖查找顺序不同
 		依赖注入的功能,是通过先在 Spring IoC 容器中查找对象,再将对象注入引入到当前类中。
 		@Autowired 是先根据类型(byType)查找,如果存在多个 Bean 再根据名称(byName)进行查找
 		@Resource 是先根据名称查找,如果(根据名称)查找不到,再根据类型进行查找
 	3.依赖注入的用法支持不同:
 	 	@Autowired 既支持构造方法注入,又支持属性注入和 Setter 注入,而 @Resource 只支持属性注入和 Setter 注入
 	4.编译器提示不同
 	 	当注入 Mapper 对象时,使用 @Autowired 注解编译器会提示错误,而使用 @Resource 注解则不会提示错误。
 	5.支持的参数不同
 		@Autowired 只支持设置一个 required 的参数,@Resource 支持 7 个参数eg:name type 

3.说说你对Spring的IOC是怎么理解的?

Ioc是控制翻转就是将对象的创建权利和对象的声明周期交给spring管理
比如说未使用IOC时,A对象依赖于B对象,当A对象运行到要使用B对象时,A对象必须去创建B对象。控制权在自己手上。
而使用IOC后,A对象与B对象就没有直接联系,当A运行到要使用B时,IOC容器会主动创建B对象注入到A对象需要的位置。控制权不在自己手上,这就是控制翻转
而IOC容器主动创建B对象注入到A对象需要的位置就叫过DI注入

Ioc是基于IOC容器完成的。IOC容器实际上就是一个map,里面存的是各种对象(比如@Controlle,xml的bean节点),在项目启动时会读取配置文件里面的bean节点,根据全限定类名使用反射创建对象或扫描到注解描述的类,放入map中,当我们需要这些对象时,就可以通过DI注入的方式使用这些对象

DI注入就是IOC容器在运行时,会动态的将某种依赖关系注入到对象中。

3.谈谈你对Spring的AOP理解

简单来说,可以在不修改原代码的情况下增加业务逻辑
复杂来说,可以将程序中的业务逻辑,封装成一个切面,然后注入到目标对象中去。可以对某个对象或某个对象功能进行增强。比如说某对象中方法在执行前后可以额外的做某些事情
AOP的底层使用的是动态代理设计模式,当要对一个实现接口的类中方法增强,采用JDK动态代理。当对于没有接口类中方法增强时,采用的CgLib动态代理

4.什么是通知呢?有哪些类型呢?

通知是个在方法执行前或执行后要做的动作,实际上是程序执行时要通过SpringAOP框架触发的代码段
Spring切面可以应用五种类型的通知:
        before:前置通知,在一个方法执行前被调用。
        after: 在方法执行之后调用的通知,无论方法执行是否成功。
        after-returning: 仅当方法成功完成后执行的通知。
        after-throwing: 在方法抛出异常退出时执行的通知。
        around: 在方法执行之前和之后调用的通知。

5.Spring基于xml注入bean的几种方式?

1.Set方法注入;
2.构造器注入:①通过index设置参数的位置;②通过type设置参数类型;

6.Spring框架中都用到了哪些设计模式?

工厂设计模式:由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类 BeanFactory处体现出来。
动态代理:为A对象提供一个代理以控制对B对象的访问,AOP的底层就使用了动态代理模式,
单例模式:在 spring 中用到的单例模式有: scope="singleton" ,注册式单例模式,bean 存放于
Map 中。bean name 当做 key,bean 当做 value。

7.BeanFactory和ApplicationContext有什么区别?

ApplicationContext是BeanFactory的子接口,提供了更丰富的功能,比如说可以同时加载多个配置文件
BeanFactory:在使用某些bean时,才会对bean进行实例化
ApplicationContext:会在容器启动时,一次性加载所有bean

8.什么是循环依赖,Spring 是怎么解决循环依赖的?

循环依赖就是循环引用,也就是两个或者两个以上的bean对象互相依赖对方,最终形成循环,比如A依赖B,B依赖C,C依赖A
三级缓存
1.创建A时,发现A依赖B,会先将自己曝光出来(ObjectFactory),再去尝试get(B)
2.然后 B 就走创建流程,在 B 初始化的时候,同样发现自己依赖 C,C 也没有被创建出来;
3. 这个时候 C 又开始初始化进程,但是在初始化的过程中发现自己依赖 A,于是尝试 get(A)。可以在三级缓存中获取A,完成初始化,将自    己存放在一级缓存
4. 回到 B,B 也可以拿到 C 对象,完成初始化,A 可以顺利拿到 B 完成初始化。到这里整个链路就已经完成了初始化过程了。

9.解释一下spring bean的生命周期

1. 实例化bean---》2.注入对象属性---》3.处理Aware接口---》4.前置处理---》5.检查初始化bean或者初始化方法---》6.后置处理
---》7.注册DisposableBean回调---》8.检查DisposableBean和destroy-method

10.说说spring事务的隔离级别

未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
提交读(Read Committed):只能读取到已经提交的数据。Oracle的默认级别
可重复读(Repeated Read):在同一个事务内的查询都是事务开始时刻一致的,Mysql的InnoDB默认级别
可串行化(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

11.Spring 事务实现方式

1. 编程式事务管理
2. 声明式事务管理(使用)
	1. 基于注解方式(使用)
	2. 基于xml配置文件方式

Mybatis

1.什么是MyBatis

Mybatis是一个优秀的持久层框架,基于ORM设计思想,实现了以对象的方式操作数据库. 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作.可以通过简单的 XML 或注解来配置和映射原始类型、接口为数据库中的记录。

2.#{}和${}的区别是什么?

使用#{} 获取数据时,默认有预编译的效果.防止sql注入攻击.
${}是字符串替换,当以字段名称为参数时,一般使用${},但是这样的sql慎用. 可能出现sql注入攻击问题.

3.当实体类中的属性名和表中的字段名不一样 ,怎么办 ?

第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
第2种: 通过来映射字段名和实体类属性名的一一对应的关系。resultMap标签实现

4.mybtis的常见封装策略

1.封装为实体对象,通过#{属性}获取数据.
2.封装成Map集合,则通过#{key}获取数据
3.使用注解 @Param 封装为Map集合,通过#{Param定义的参数key}获取数据

5.Mybatis中的转义标签

        >  > 大于
        <  < 小于
        &  & 号
    说明:如果sql中有大量的转义字符 建议使用转义标签体
    语法: 

6.如何批量处理相同的多个数据

通过foreach标签将数组或者集合拆分成单个数据
            1).如果参数传参为数组,       则collection="array"
            2).如果参数传参为list集合,   则collection="list"
            3).如果参数传参为map集合,    则collection="map集合中的key值"

7.Xml映射文件中,除了常见的select|insert|updae|delete 标签之外,还有哪些标签?

1. where if 标签
2. set  标签
3. choose when otherwise

8.resultType和resultMap的区别

当结果集中的字段名称,如果与属性的名称一致时,可以使用resultType实现自动的数据封装
当结果集中的字段名称,与对象中的属性不一致时,使用resultMap实现自定义的封装

9.MyBatis实现一对一有几种方式?具体怎么操作的?

1.关联查询
	多个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;
2.子查询
	先查一个表,根据这个表里面的结果的外键id,去再另外一个表里面查询数据。通过association的select属性配置

10.说说Mybatis的缓存机制:

Mybatis的缓存机制分为:一级缓存和二级缓存
     Mybatis默认开启一级缓存, 一级缓存可以在同一个SqlSession对象中查询相同的数据,实现数据的共享。
     同一个SqlSession内部有效,不同的SqlSession内部无效
 	 二级缓存mybatis中默认也是开启的.但是需要手动标识. 二级缓存可以在同一个SqlSessionFactory内部有效.
 	 SqlSession查询数据之后,会将缓存信息保存到一级缓存中,但是不会立即将数据交给二级缓存保存
 	 如果需要使用二级缓存,则必须将SqlSession业务逻辑执行成功之后,再关闭

Redis

1.什么是 Redis?

Redis是一个key-value存储系统,是一个分布式缓存数据库.基本架构为C/S架构。6.0版本之前所有操作都是单线程,6.0版本之后,读写操作还是单线程.网络IO操作是多线程。

2.redis常用五种数据类型?

string(字符串),hash(哈希),list(列表),set(集合)及zset(有序集合)。

3.Redis 持久化方式有哪些?以及有什么区别?

1.rdb方式
2.aof方式
RDB持久化方式是通过手动保存或周期性的方式保存的数据的一种方式。
其优点在于
	适合用于灾难恢复数据,因为RDB文件中保存了redis某些时间点的数据
	还可以保证redis最大的性能。因为在保存数据时,redis主进程会fork一个子线程去保存数据,主线程继续处理请求
其缺点在于
	有可能丢失几分钟的数据,根据配置文件中的配置决定。
AOF方式是通过记录写操作日志的方式,记录数据的一种方式
	其优点在于
		AOF可以更好的保护数据不丢失,根据配置文件中对AOF配置,最多会丢失一秒的数据。
		AOF文件过大时,会出现后台重写操作,也不会影响客户端的读写。
		AOF日志文件的命令通过易读的方式进行记录的,可以做灾难性的误删除的紧急恢复。
	其缺点在于
		对于同一份数据,AOF日志文件通常比RDB数据快照文件大
		AOF开启后,支持的写QPS比RDB支持的写QPS低
		AOF这种基于命令日志的方式,比基于RDB每次持久化一份完整的数据快照文件的方式,健壮性稍微低一点

4.如何选择redis的持久化方式

不能仅选择RDB的方式进行持久化。因为:丢失数据量较多
不能仅选择AOF的方式,因为AOF保存数据的方式没有RDB保存数据的方式进行恢复数据的速度快,并且RDB保存数据的方式更健壮
应该同时使用RDB和AOF的方式。用AOF保证数据不丢失,RDB用于保存不同时刻的数据。

5.怎么使用 Redis 实现消息队列?

可以使用 list 结构作为队列,rpush在list尾部添加数据,作为生产消息,lpop在list头部删除数据,作为消费消息。

6.什么是BigKey?怎么解决

Redis中什么是Big Key(大key)问题?如何解决Big Key问题?_redis大key解决方案_每天都要进步一点点的博客-CSDN博客

Big Key就是某个key对应的value很大,占用的redis空间很大,本质上是大value问题
1.对大Key进行拆分
	将一个Big Key拆分为多个key-value这样的小Key,并确保每个key的成员数量或者大小在合理范围内,然后再进行存储,通过get不同的	key或者使用mget批量获取。
2.对大Key进行清理
3.定期清理失效数据

7.什么是redis缓存雪崩,怎么解决?

缓存雪崩就是在短时间内,redis中出现大量的key过期,从而导致大量请求去查询数据库,给数据库带来极大的压力,从而导致服务器的崩溃
	1.记录key过期的时间,在key快过期时,同时其他线程去更新key的缓存
	2.可以设置key的过期时间不同。采用随机数的方式设置key的过期时间,让redis缓存中key的过期时间不同
	3.采用多级缓存的方案解决

8.什么是缓存穿透,怎么解决?

缓存穿透就是大量数据在redis中查询不到数据,从而去查询数据库,而数据库中又没有数据,无法在redis中添加缓存,因此这些数据会一直查询数据库,最后导致数据库崩溃
	1.对空值缓存:如果在数据库中查不到此数据,在redis缓存中将数据库返回的null值进行缓存,并设置这个null的过期时间
	2.设置可访问的名单:使用bitmaps类型定义一个可以访问的名单,名单id作为bitmaps的偏移量,每次访问都会和bitmaps里面的id进行					  比较,如果访问id不再bitmaps里面,进行拦截,不允许访问
	3.进行实时监控:当发现redis的命中率开始急速降低,就开始排查访问对象和访问的数据,设置黑名单的限制服务

9.什么是缓存击穿,怎么解决

缓存击穿就是Redis某个key过期了,大量数据访问这个key。访问不到就会去访问数据库,数据库承受不了这个大量数据访问的压力,从而导致宕机
	1.预先设置热门数据
	2.实时调整
	3.可以使用Setnx,去set一个互斥的key,当操作返回成功时,再去连接数据库,并设置缓存,最后删除互斥key。当操作返回失败时,证		明有线程在查询数据库,让现在这个线程睡眠一段时间再重新查询
		

Nginx

1.简述一下什么是Nginx

Nginx是一个高性能的HTTP和反向代理web服务器,也是一款轻量级的Web服务器/反向代理服务器及电子邮件代理服务器
它的特点是:占有内存少,并发能力强。

2.反向代理

1.在客户端与用户之间有一个反向代理服务器
2.客户端会以为反向代理服务器就是目标服务器
3.反向代理服务器保护了目标服务器的信息

3.负载均衡

当单个服务器服务器解决不了问题,增加多个服务器,
将原先请求集中分发给单个服务器的情况改为了将请求分发给多个服务器,将负载分发给不同的服务器

4.负载均衡中还有三大策略

1.轮询策略:根据配置信息,依次访问服务器
2.权重策略:根据服务器的性能,手动分配服务器的负载
3.IPHASH策略:让用户的请求跟服务器绑定,用户初次访问的是哪个服务器,以后永远访问其服务器

5.动静分离

将静态资源和动态资源放在不同的服务器上,当用户访问哪个资源时,用哪个服务器接受。降低原来单个服务器的压力、加快网站的解析速度

RabbitMQ

1.为什么要使用MQ

因为MQ有3个核心观念
1.服务解耦
		平常状态下服务A产生数据,服务BCD需要使用。我们需要使用服务A去调用服务BCD,然后将数据传输到服务BCD。随着服务的增加,
		会让服务与服务之间的耦合度过于紧密。使用MQ后,服务A只需要想MQ发送数据就行了,下面的服务需要数据,自行从MQ订阅就行了
2.流量削峰
		就是在高峰时刻,瞬间出现的大量请求数据,可以先发送到消息队列服务器(mq),排队等待即可。而我们的应用可以慢慢的从信息			队列服务器接收数据进行处理。这样处理的方法就是将数据处理时间拉长,以减轻瞬时压力
3.异步调用
		当服务A去对服务B进行调用时,可以将调用信息发送给mq,由mq去执行调用服务B,等待服务B返回的数据。而服务A就不用在此等			待,可以去做别的事情

2.RabbitMQ的工作模式

1.简单模式
	一个提供方(或多个提供方)给MQ发送消息,一个消费方从MQ接受消息。这种模式就称为简单模式
2.工作模式
	一个提供方(或多个提供方)给MQ发送消息,多个消费方从MQ接受消息,MQ会采用负载均衡的方式将消息轮询的发给每一个消费。
3.发布与订阅(群发)模式
	服务器将消息发送给所有消费者,同一消息所有消费者都可以收到
4.路由模式
	服务端通过关键词匹配,来确定把消息发送个那隔消费端
5.主题模式
	和路由模式相同,但是具有特殊的关键词规则
	*:表示可以匹配一个任意的字符
	#:表示可以匹配多个任意的字符

3.如何保证消息的可靠传输?如果消息丢了怎么办

数据的丢失问题,可能出现在生产者、MQ、消费者中
生产者:
	1.开启confirm模式(异步).开启后,每次写的消息会分配到一个唯一的id,如果写入到RabbitMQ 中,RabbitMQ会返回一个ack消息,表	  示这个消息ok了。如果没有写入RabbitMQ 中,会返回一个nack消息,表示消息接受失败,可以重试
	2.开启RabbitMQ 事务,消息没有被RabbitMQ接收到,生产者会收到异常报错,回滚事务。如果被接收到,提交事务
MQ中丢失
	开启RabbitMQ 的持久化
	1.创建 queue 的时候将其设置为持久化
	2.就是将消息设置为持久化的
消费者中:
	关闭 RabbitMQ 的自动ack.当代码处理完后,会在程序中ack一下。如果没有处理完,不会ack。

4.怎么解决当一个消费方在处理一个消息时过长时,MQ还是会采用轮询的方式对多个消费方进行发送消息

这个问题是服务器不知道某个消费者对请求是否处理完,会依旧采用负载均衡轮询的方式对多个消费者发送请求
解决方案:
	开启手动确认模式,返回这服务器回执,消费者告诉服务器自己是否处理完消息
	设置qos=1,每次只收一条,处理完之前不收下一条 

5.如何保证消息的顺序性

将一个queue拆分成多个queue,每个queue对应一个consumer。当生产者发送消息到queue时,通过关键值进行哈希排列,如果是同一个类型的多个消息,将多个消息发送到同一个consumer中

SpringCloud

你可能感兴趣的:(java)