java军火库

一 Java 基础

1.java的特性:

封装,继承,多态

封装:

​ 含义:

​ 封装就是把同一类事物的共性(包括属性和方法)归到同一类中,方便使用。

​ 实现:

​ 1.对成员变量进行私有化(使用private修饰);

​ 2.写成员变量对应的getter/setter方法 (用于属性的读写);

​ 3.在getter/setter方法中加入属性控制语句(用于判断属性值的合法性);

​ 优点:

​ 1.将变化隔离

​ 2.便于使用

​ 3.提高重用性

​ 4.提高安全性

​ 缺点:

​ 将变量等使用private修饰,或者封装进方法内,使其不能直接被访问,增加了访问步骤与难度

继承:

​ 含义:

​ 在JAVA中, 被继承的类叫父类(parent class)或超类(superclass), 继承父类的类叫子类(subclass)或派生类(derivedclass)。 因此, 子类是父类的一个专门用途的版本, 它继承了父类中定义的所有实例变量和方法, 并且增加了独特的元素 。

​ 实现:

​ extends,子类继承父类

​ 优点:

​ 1.减少代码量,能很好的提高复用率

​ 2.使类与类之间存在继承关系,是实现多态操作的前提

​ 缺点:

​ 继承使得多个类之间具有了子父类关系,当一个类存在多个子类的时候,如果父类发生变化,那么这些子类会跟着一同变化,造成类与类之间的“强耦合”关系

多态:

​ 含义:

​ 多态指的是对象的多种形态

​ 引用多态和方法多态,继承是多态的实现基础。

​ 实现:

​ 1.必须有子类和父类,具有继承或实现(继承)

​ 2.子类必须重写父类的方法(重写)

​ 3.父类的引用指向子类的对象,或接口的引用指向实现接口的对象

​ 优点:

​ 1.可替换性,多态对一存在的代码具有可替代性

​ 2.可扩充性:增加的子类不影响已存在的类的特性的运行和操作

​ 3.接口性:多态时超类通过方法签名想子类提供了一个公共的接口,由子类来完善或者覆盖它而实现的

​ 4.灵活性:在应用中体现了灵活多样的操作,提高了使用的效率

​ 5.简化性: 多态简化对应用软件的代码的编写和修改过程,尤其在处理大量的对象的运算和操作时,这个特点尤为突出和重要

​ 缺点:

​ 1.只能使用父类的引用访问父类的成员

​ 2.成员变量:编译与运行时期都看父类

​ 3.成员方法:编译时期看父类,运行时期看子类

2.重写和重载

重写:

​ 1.必须不在同一个类

​ 2.必须是继承关系

​ 3.方法名字返回值类型列表必须保持一致

重载:

​ 1.必须在同一个类

​ 2.方法名字必须一致

​ 3.形式参数必须不一致

3.java各关键字区别

abstract(抽象)

​ 1.abstract修饰成员方法之后,这个类也必须使用abstract修饰

​ 2.abstract修饰方法以后,这个方法不能有方法体

​ 3.凡是使用abstract修饰的类叫做抽象类,abstract修饰的方法叫做抽象方法

​ 4.抽象方法下面可以有非抽象方法

​ 5.在子类中,只要是抽象方法,就必须去实现(无条件实现)

​ 6.抽象类没有自己的类对象

​ 7.有抽象方法的类必须是抽象类,但是抽象类下边可以没有抽象方法

final

​ 1.final修饰的成员变量,必须定义初始化的值,初始化以后不能修改

​ 2.final修饰局部变量,使用final修饰的一旦被赋值,就无法更改

​ 3.final修饰成员方法,子类不能被重写

​ 4.final修饰的类,不能被继承,不能有自己的子类

interface(接口)

​ 1.接口下面可以声明成员属性,但是这个属性是static和final修饰的,省略了public,static和final

​ 2.接口下面可以声明成员方法,但是方法必须是抽象的方法,省略了abstract

​ 3.jdk1.8新特性,接口中允许使用default修饰方法,来完成对方法默认的定义,这个方法可以有方法体

​ 4.使用implements这个关键字实现接口

static

​ 1.使用static修饰成员变量,类名,成员方法,代码块

​ -1.static修饰的成员变量,都是在class类文件加载阶段,都会直接在内存的数据区,创建对应的成员变量。该过程是早于创建对象的,而且当前存在数据区的静态的成员变量,是伴随咱们整个程序运行阶段的,只要程序不退出,不销毁,它就一直存在。

​ -2.静态成员方法完全可以摆脱类对象的约束,静态的成员方法和类对象一点关系都没有。静态成员方法是伴随着class进行加载到内存中的,已经在内存的代码区完成定义。这个时候没有对象的创建,只要代码不退出或者销毁,静态成员方法会一直存在代码区。

​ 静态的成员方法中不能使用非静态的成员属性和非静态的成员方法。

​ 静态的成员方法中不能使用this关键字,因为this表示是调用当前方法的类对象,静态方法是没有对象,是直接使用类名。

​ 静态方法中可以创建对象。

​ 静态方法不能被重写

​ -3.static修饰代码块,类文件只要加载,静态代码块一定加载

​ 代码执行最基本的原则,从上到下的执行原则

​ 执行构造方法,一定会有构造代码块

​ 构造代码块的优先级最高

​ 2.在代码中没有创建任何类对象的话,可以通过类名,直接调用static修饰的成员属性

​ 3.在代码运行过程中,已经销毁了所有的类对象,依然是可以通过类名调用静态的成员变量

​ 4.static修饰的成员变量和对象没有任何关系

this

​ 1.表示调用当前方法的类对象

​ 可以使用this调用类对象的成员变量和成员方法,也可以用于操作当前类对象

​ 2.可以调用构造方法

​ -1.this(实际参数),有且只能放在当前构造方法的第一行

​ -2.有且只能用在构造方法内

​ -3.this()在类内调用其它的构造方法,是根据传参不同决定调用哪个构造方法

​ -4.不能调用本身的构造方法

super

​ 调用父类的成员方法和成员属性

4.集合

《一》Collection

​ Collection是java中所有的集合的总的接口

(1).list:

​ 是Collection集合的子类,有序的,可重复的

----1.ArrayList:

​ ArrayList是List集合的子接口

​ 增删慢,查询块

​ 1.ArrayList是一种变长的集合类,基于定长数组实现,使用默认构造方初始化出来的容量是10(1.7以后都是延迟初始化,即第一次调用add方法添加元素的时候才将elementData容量初始化为10)

​ 2.ArrayList允许空值和重复元素,当往ArrayList中添加的元素数量大于其底层数组容量时,其会通过扩容机制重新生成一个更大的数组。ArrayList扩容的长度是原长度的1.5倍

​ 3.由于ArrayList底层基于数组实现,所以其可以保证在0(1)复杂度下完成随机查找操作

​ 4.ArrayList是非线程安全类,并发环境下,多个线程同时操作ArrayList,会引发不可预知的异常或错误

​ 5.顺序添加很方便

​ 6.删除和插入需要复制数组,性能差(可以使用LinkindList)

​ 7.Integer.MAX-ARRAY_SIZE-8:主要是考虑到不同的JVM,有的JVM会在加入一些数据头,当扩容后的容量大于MAX-ARRAY_SIZE,我们会区比较最小容量和MAX-ARRAY_SIZE做比较,如果比它大,只能取MAX_ARRAY_SIZE,否则是MAX-ARRAY_SIZE-8.这个是从jdk.17开始才有的

----2.LinkedList:

​ LinkedLisg是List集合的子接口

​ 增删快,查询慢

​ 1.LinkedList以链表的形 式存储数据、对增删元素有很高的效率、查询效率较低、尤其是随机访问、效率不忍直视

​ 2.LinkedL ist继承AbstractSequentialdList (其继承与AbstractList.所以要求其子类要实现通过索弓|操作元素)、使得LinkedList支持使用索引的"增删改查”操作

​ 3.LinkedList直接实现了List接口、 使其可以内部存储元素有序并且为每个元素提供索引值

​ 4.LinkedList直接实现了Deque接口、Deque接口继承了Queue、 使其可以作为双向链表这种数据结构来使用、操作元素

​ 5.LinkedList直接实现 了Cloneable接口、使其可以复制其中的全部元素

​ 6.在使用ObjectOutputStream/ObjectInputStream流时、 会先讲LinkedList的capacity读取/写入到流中、 然后将元素读取写入

----3.Vector:

​ Vector是List集合的子接口

​ 1.Vector是内部是以动态数组的形式来存储数据的

​ 2.Vector具有数组所具有的特性、通过索引支持随机访问、所以通过随机访问Vector中的元素效率非常高、但是执行插入、删除时效率比较底下

​ 3.Vector实现 了AbstractList抽象类、List接口、 所以其更具有了AbstractList和List的功能、前面我们知道AbstractList内部已经实现了获取Iterator和Listlterator的方法、所以Vector只需关心对数组操作的方法的实现

​ 4.Vector实现 了RandomAccess接口、此接口只有声明、没有方法体、表示Vector支 持随机访问

​ 5.Vector实现了 Cloneable接口、此接口只有声明、没有方法体、表示Vector支持克隆

​ 6.Vector实现了Serializable接口、此接口只有声明、没有方法体、表示Vector支 持序列化、即可以将Vector以流的形式通过ObjectOutputStream来写入到流中

​ 7.Vector是线程安全的

(2)set:

​ 是Collection集合的子类,无序的,不可重复的

----1.HashSet:

​ 是set的子接口

​ hashset是由一个hash表来实现的,因此它的元素是无序的,而且不是同步的,集合元素可以是null,但是只能放置一个null,存储效率相当高使用hashset需重写hashcode和equals方法。因为在java中,两个对象相等,hashcode一定相等;两个对象不相等,hashcode一定不相等;hashcode相等,两个对象不一定相等;hashcode不相等,两个对象一定不相等

​ 重写了hashcode方法,必须重写equals方法,缺一不可

​ 1.如果只重写了hashcode方法,也是不能判断两个对象是否相等

​ 2.如果只重写了equals方法,也不能判断两个对象是否相等,因为比较的是内容

​ 论证:

​ 1.如果没有重写hashcode和equals方法,只比较hash值是否相等,两个对象两个内存地址,两个hash值,就直接判定是不同的,就可以写进集合中

​ 2.如果重写了hashcode方法,没有重写equals方法,如果hash值一样,但是物理地址不一样,还是可以存到集合中

​ 3.如果重写了equals方法,没有重写hashcode方法,hash值还是不一样的,直接判断hashcode方法,而不会调用equals方法

​ 4.如果重写了hashcode方法和equals方法,两个对象比较时不看物理地址,直接比较hash值和内容,如果相等就只存一个

----2.TreeSet:

​ 是set的子接口

​ TreeSet底层是一个树状结构,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。向 TreeSet中加入的应该是同一个类的对象

(3)Iterator:

​ 迭代器就是另外一种操作集合的方式,Iterator接口提供了很多对集合元素进行迭代的方法,每一个集合类都包含了可以返回迭代器实例的迭代方法。迭代器可以在迭代的过程中删除底层集合的元素。克隆或者是序列化的语义和含义是跟具体的实现相关的。因此应该由集合类的具体实现来决定如何被克隆或者是序列化,

《二》Map

​ map集合是键值对形式存储的,成双成对出现的;键是唯一的,一个键只能对应唯一的数据;值可以相等,对应多个键,通过键取值

(1) HashMap

​ 无序的,hashmap底层是一个hash表,存储的就是当前键值对的key,也就意味着你的key不能重复。jdk1.8之前是list+链表,jdk1.8之后list+链表(当链表长度达到8时,转化为红黑树),hashmap 的扩容因子,也就是会浪费1/4的空间,达到扩容因子时,会将list扩容一倍,0.75是时间与空间的一个平衡值。hashmap是非线程安全的,hashmap允许null值存在(key和value都可以)

(2)TreeMap

​ 底层是一个红黑树,比较存储的数据的时候,参考的也是key值,有序的

5.list,map,set存取元素,有什么特点?

list可以重复元素,set不能重复元素,map必须键值对,映射关系一对一或一对多

6.反射

​ 反射就是动态加载对象,并对对象进行解剖。在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法,这种动态获取信息以及动态调用对象方法的功能成为java反射机制

​ 1.在运行时判断任意一个对象所属的类

​ 2.在运行时构造任意一个类的对象

​ 3.在运行时判断任意一个类所具有的成员变量和方法

​ 4.在运行时调用任意一个对象的方法

​ 可以通过getClass()方法来获取;类名.class的方式得到;通过Class对象的forName()静态方法来获取

​ 优点:在运行时动态获取类和对象中的内容,极大地提高系统的灵活性和扩展性;夸张一些说,反射是框架设计的灵魂

​ 缺点:会有一定的性能损耗,JVM无法对这些代码进行优化,破坏类的封装性

7.error和exception区别?

error:错误只能避免

exception:异常可以处理

8.comparable(内比较器)和comparator(外比较器)区别?

comparable只包含一个自然比较方法,这个方法可以给两个对象排序,返回负数,0,正数,比较两个对象大小。comparator包含compare()和equals()两个方法

二:Java IO

1.IO里面常见的类?

输入流,外部文件输入到内存

输出流,内存输出到外部文件

IO流主要分为字符流和字节流

程序中的输入输出都是以流的形式保存,流中保存的全都是字节文件

2.IO和NIO的区别?

nio和io有相同的作用和目的,实现方式不同

io,面向流,阻塞式,无选择器

nio,面向缓冲,非阻塞式,有选择器

3.BIO,NIO和AIO区别?

BIO,同步阻塞IO模式,人在厨房烧水,一直在面前等

NIO,同步非阻塞模式,人在厨房烧水,不在面前等,在客厅看电视,每隔几分钟看下水烧开没

AIO,同步非阻塞IO模型,人在厨房烧水,不在面前等,在客厅看电视,烧水壶上有开关,水烧开会通知我

4.字符流和字节流区别?

字节流的操作不经过缓冲区,直接操作文件本身,字节流8位传输

字符流的操作先经过缓冲区(内存),再操作文件,字符流16位传输

5.什么是JAVA序列化,如何实现?

序列化就是一种用来处理对象流的机制,将对象的内容进行流化,可以对流化后的对象进行读写操作,将流化后的对象传输于网络之间,序列化是为了解决对象流读写操作时所引发的问题

6.什么是节点流,处理流?

节点流,直接与数据源相连,用于输入或输出

处理流,在节点流的基础上对之进行加工,进行一些功能的扩展

处理流的构造器必须要传入节点流的子类

7.什么是缓冲区?

缓冲区就是一段特殊的内存区域,将一部分数据暂时存在缓存区,从此区域读取数据即可

三:多线程

1.进程和线程的区别

​ 进程就是独立的应用程序,进程是通过系统分配,获取系统的cpu,内存,显卡,网络和磁盘这些资源的。具有独立性,互斥性

​ 线程就是进程中的一个功能,进程由多个线程组成,而且至少有一个线程。抢占式运行,cpu执行程序是按照时间片来进行执行的。资源共享,一个当前的程序中的线程是可以共享程序的资源的,cpu java代码就是一个应用程序。在运行的时候,必须有线程

​ 1.调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位

​ 2.并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行

​ 3.拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源

​ 4.系统开销:在创建或撤销进程的时候,由于系统都要为之分配和回收资源,导致系统的明显大于创建或撤销线程时的开销。但进程有独立的地址空间,进程崩溃后,在保护模式下不会对其他的进程产生影响,而线程只是一个进程中的不同的执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但是在进程切换时,耗费的资源较大,效率要差些

2.线程池的作用

1.降低资源消耗

2.提高响应速度

3.提高线程的可管理性

3.jdk线程池的类型?

五种

1.有缓冲的线程池,线程数JVM控制

2.固定大小的线程池

3.定时周期的线程池

4.单线程的线程池,只有一个线程在工作

5.默认线程池,可控制参数比较多

4.线程池拒绝策略

四种拒绝策略

1.默认,队列满了丢任务抛异常,阻止系统运行

2.队列满了丢任务不抛异常,若允许任务丢失,比较适合使用

3.删除最早进入队列的任务,再尝试加入队列,抛弃等待时间最久的任务, 当前任务加入队列尝试提交

4.如果添加线程池失败,主线程会自己执行任务,调用调节机制,不丢弃也不抛异常,退还某些任务给调用者,降低新任务流量

5.线程池创建的七个参数?

1.核心线程数

2.最大线程数,大于等于核心线程数

3.线程存活时间

4.存活时间单位

5.任务队列

6.创建线程的工程

7.拒绝策略

6.synchronized,Volatile,CAS区别

synchronized是悲观锁,属于抢占式,会引起线程阻塞

volatile提供多线程共享变量可见性,禁止指令重排序

CAS是乐观锁,非阻塞

7.线程同步的方法?

wait()使一个线程进入等待状态,并且释放对象所持有的锁

sleep()使一个正运行的线程处于休眠状态,是静态方法,使用该方法,需要捕捉异常

notify()随机唤醒一个处于等待状态的线程,由VJM决定唤醒哪个,并且是随机顺序

notityAll()唤醒所有处于等待状态的线程

8.什么是线程安全?

代码所在的进程有多个线程同时运行,而这些线程可能同时运行这段代码。每次运行结构和单线程运行结构一致,就是线程安全的。

9.线程的创建方式

1.继承Thread类

2.实现Runnable接口

3.实现Callable接口

4.使用线程池

10.wait()和sleep()的区别

wait()是Object类的方法,进入等待时间,必须使用notity()方法才可以使线程进入运行状态

sleep()是Thread类的方法,进入休眠状态,休眠一定时间

11.线程的几种状态?

1.新建状态,新建了一个线程对象

2.就绪状态,其它线程调用了该对象的start()方法,该状态线程位于可运行线程池中,变得可运行

3.运行状态,就绪状态的线程获得了CPU,指向程序代码

4.阻塞状态,线程某种原因放弃了CPU使用权,暂时停止运行

5.死亡状态,线程执行完了,或者因异常退出了run()方法,该线程结束生命周期

四:Java Web

1.cookie

​ cookie就是存储在浏览器的一小段信息,以键值对形式存储,存的都是字符串

​ 特点:

​ 1.以key:value键值对形式存储

​ 2.cookie由服务器产生,通过response 返回,浏览器保存(cookie 服务器产生,浏览器保存,下次请求路径是在header中携带cookie)

​ 3.cookie有大小限制 4k

​ 4.cookie 有时间限制 默认 30min

​ 5.cookie 不能存储敏感信息(密码等)

2.session

​ Session 就是会话(同一个浏览器请求同一个服务器,无论打开多少个窗口,这些窗口都共享一个会话),会话就是浏览器和服务器保持的链接一种形式,主要作用就是记录用户的状态,记录用户相关的信息

​ 1.存储在服务端

​ 2.以键值对存储,值可以是任何类型

​ 3.会话也有时间限制(如果用户尝试建没有访问,则会话会自动删除)

​ 4.浏览器关闭,会话结束,如果浏览器重新打开,则是新的会话

​ 5.sesssion 的安全性相对较高

浏览器关闭,会话cookie消失,但是session的信息还存在服务器,只是我们查询不到,并不是真的不存在;session的真正丢失,是服务器关闭的时候,或者session过期(默认时间30分钟)

3.cookie和session的区别

cookie和sessio 共同点都是 存储用户相关的信息

cookie:

​ 由服务器产生,浏览器保存,每次请求携带cookie

​ cookie不可以存储敏感信息

​ cookie大小有限制

session:

​ 服务器产生,并保存,通过每个请求 提交session的id 辨别当前 请求到底属于哪个会话(浏览器)

​ session 可存储任何对象

​ session 无大小限制

​ 浏览器关闭 session 销毁

默认情况下,session是基于cookie 存储 session的id,鉴别来自不同的浏览器的会话,如果浏览器禁用了cookie,session的id无法存储,默认不可以使用session,可以使用重写url形式解决,在所有的url后面加上请求路径?

4.servlet的生命周期

加载,初始化,服务,销毁

5.转发和重定向的区别?

重定向:

1.浏览器行为

2.浏览器做了2次请求

3.上一次请求的request对象会丢失

4.url发生改变

5.可以是任意的网络资源

重转发:

1.服务器行为

2.浏览器只做了一次行为

3.转发带有用户的HttpServletRequest

4.url没有变化

5.只能在当前项目进行,不能到网络资源

6.创建servlet的三种方式?

java服务器的小程序,是javaweb非常重要的环境。主要作用是完成html和java后台代码的交互(请求《====》响应)

servlet接口创建, GenericServlet抽象类, HttpServlet抽象类(一般用这个)

7.request.getAttribute()和request.getParameter()的区别?

1.request.getParameter()通过容器实现,取得post,get等方式传入的数据

2.request.getAttribute()只在容器内部流转

3.request.getAttribute()返回对象,request.getParameter()返回字符串

4.request.getAttribute()需要和request.setAttribute()配合使用,只有设置过值以后,才能获取

8.mvc设计模式?

mvc 设计模式,使用一种常见设计模式(一种套路/规范),所有前后端交互的软件都遵循mvc

m:model (模型) ,数据/实体类 从数据库中查询

v:view (视图),前端界面/jsp/html 接收数据/展示数据

c:controller (控制器),后端servlet ,控制界面的跳转,返回响应的数据/model

9.三层架构指什么?

三层架构 指的是 代码 不同业务的书写位置

View(表示|界面层),html/jsp 前端 web

Service(业务逻辑层),处理前端请求对应的业务数据

Dao(数据访问层),专门用来做数据的增删改查

10.jsp是什么?

JSP:表面上看就是html,可以显示图片,css效果,但是jsp可以在html 中写局部的java 代码,动态的获取数据

jsp:本质jsp 就是servlet jsp —> java ---->class

作用:简化前端界面的开发,可以动态加载数据----》动态网页

11.jsp有哪些内置对象?

9个内置对象

request,封装客户端的请求

response,封装服务器对客户端的响应

pageContext,通过该对象可以获取其它对象

session,封装用户会话的对象

application,封装服务器运行环境的对象

out,输出服务器响应的输出流对象

config,web应用的配置对象

page,jsp页面本身

exception,封装页面抛出异常的对象

12.Http请求的get和post方法的区别?

1.get是向服务器索取数据的请求,post是向服务器提交数据的请求

2.get是获取信息,不是修改信息;

3.get请求数据有大小限制,get通过url提交数据,get提交的数据跟url长度有关,浏览器对url长度有要求

4.get请求的数据会被浏览器缓冲起来,数据不安全

5.post表示可能改变服务器上资源请求

6…post没有限制提交的数据,数据放在html header内提交,post比get安全

13.tomcat容器如何创建servlet实例?

A.先到缓存中寻找有没有这个对象
如果没有: 1、通过反射去创建相应的对象(执行构造方法)
2、tomcat会把对象存放到缓存中
3、执行初始化方法init
如果有该对象,直接获取到这个对象
B. 执行服务方法
C.返回响应的数据到客户端(浏览器)

14.jdbc访问数据库的基本步骤?

Sun公司制定的通过java来连接数据库的标准规范,而且要求数据库的提供商解决 连接和操作的问题。

1.加载数据库驱动

2.获取数据连接对象

3.通过sql获取sql会话对象

4.执行sql

5.处理结果集

6.关闭结果集,关闭会话,关闭连接

15.为什么使用preparedStatement而不使用statement?

statement sql语句的搬运工,没有判断sql和预处理的能力,容易导致sql的注入

登录:需要用户名和密码。密码不对也可以登录上。

statement需要不断拼接,preparedStatement不需要,preparedStatement能够防注入

16.数据库连接池的原理,为什么使用连接池?

1.连接池可以使多个操作共享一个连接

2.为数据库连接建立一个缓冲池

3.提高对数据库连接资源的管理

17.request作用?

1.获取请求参数

2.获取当前web虚拟路径

3.转发

4.域对象

18.filter(过滤器)工作原理

1.拦截不符合要求的请求进行拦截,使之不能够到达servlet

2.对请求的数据进行加工处理

19.监听器

20.servlet,filter,listener启动顺序

listener大于filter大于servlet

监听器大于过滤器大于服务器

五:JVM(java虚拟机)

1.java的内存划分

  • 线程共享区:方法区、堆
  • 线程私有区:虚拟机栈、本地方法栈、程序计数器

1.程序计数器,是一块较小的内存空间,每个线程都有自己的程序计数器,任何时间一个线程都只有一个方法在执行,各条线程之间互不影响,独立存储

2.本地方法栈,与java虚拟机栈发挥的作用十分相似,区别是java虚拟机栈是为虚拟机执行java方法的,本地方法栈是为虚拟机执行native方法的,本地方法栈和java虚拟机栈在同一个区域,

3.虚拟机栈(java栈),每个线程创建都会创建一个虚拟机栈,内部保存着一个个的栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,对应着一次次的java方法调用,

栈内存的管理:通过压栈出栈操作来完成的,以栈帧为基本单位来管理程序的调用关系,每当有函数调用时,都会通过压栈方式创建新的栈帧,每当函数调用结束后都会通过出栈的方式释放栈帧

4.,java内存管理的核心区域,放置对象实例,java堆是被所有线程共享的一块内存区域,java堆是垃圾收集器管理的主要区域,因此很多时候也被称作GC堆(垃圾收集管理器),

从内存回收的角度来看,现在收集管理器都采用分代收集算法,java堆还分为,新生代老生代

从内存分配的角度来看,java堆中可能划分出多个线程私有的分配缓冲区,进一步的划分目的是为了更好地回收内存和更快地分配内存,

5.方法区,和Java堆一样也是各个线程共享的内存区域,他用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。使用永久代实现方法区,方法区也称为永久代,永久代有上限,容易出现内存溢出问题,方法区是线程安全

jdk7中,已经将放在永久堆的字符常量池移出,

jdk1.6字符串常量池在方法区中,

jdk1.7之后在堆中。运行时常量池一直在方法区中。

jdk1.8开始,移除永久代概念,方法区用元数据区实现

6.数据区,堆数据区是用来存放对象和数组(特殊的对象),堆内存由多个线程共享,静态修饰

7.运行时常量池,方法区的一部分,常量池在编译期间就将一部分数据存放于该区域,包含基本数据类型如int、long等以final声明的常量值,和String字符串、特别注意的是对于方法运行期位于栈中的局部变量String常量的值可以通过 String.intern()方法将该值置入到常量池中

2.什么时java虚拟机?

java虚拟机是一个可执行java字节码的虚拟机进程,java源文件被编译成能被java虚拟机执行的字节码文件,java在任意平台允许,且不需要单独重写和重新编译,java虚拟机知道底层指令长度和其它特性

3.如何判断一个对象应该被回收?

1.可达性分析法,通过GCRoots和一个对象之间没有可达路径,该对象不可达,通过两次标记对象,成为可回收对象

2.虚拟机栈中引用的对象,

方法区中类静态属性引用的对象,

方法区中常量引用的对象,

本地方法栈中引用的对象

4.GC触发的条件

1.会在cpu空闲的时候自动进行回收

2.在堆内存存储满了之后

3.主动调用System.gc()后尝试进行回收。

5.可以作为GCroots的对象有哪些?

虚拟机栈中引用的对象,

本地方法栈中引用的对象,

方法区中类静态熟悉引用的对象,

方法区中常量引用的对象

6.什么是垃圾回收?

垃圾回收 是JVM垃圾回收器提供的一种用于空闲时间不定时回收无任何对象引用的对象占据内存空间的一种机制

7.JVM中一次完整的GC流程是怎样的,对象如何晋升到老年代?

java堆= 老年代 + 新生代

新生代 = Eden + S0 + S1

新生代将内存按照8:1:1分为一个Eden(伊甸区)和so,s1(幸存者区)三个区域;大部分对象都在Eden区域生成,

当Eden区满的时候,java虚拟机会触发一次Minor GC,收集新生代的垃圾,存活下来的对象转移到Survivor区,

大对象直接进入老年代,

若对象在Eden出生,经过第一次Minor GC后仍然存活,并且被Survivor容纳的话,年龄设为1,每熬过一次Minor GC,年龄+1,当年龄超过15,则晋升到老年代,即长期存活的对象进入老年代

老年代满了,Minor GC会进行Full GC,Full GC会清理整个内存堆,包括年轻代和老年代,

Major GC发生在老年代,清理老年代,伴随至少一次MInor GC,并且比其慢10倍以上

8.双亲委派模型?

类加载器收到请求,不会自己去加载这个类,而是委派给父类加载器完成,

只有当父类加载器找不到指定的类,子加载器才会自己加载

9.为什么需要双亲委派模型?

防止内存中出现多份同样的字节码

10.怎么打破双亲委派模型?

不仅要继承ClassLoader类,还要重写loadClass和findClass方法

11.导致Full GC一般有哪些情况?

1.新生代设置过小

2.新生代设置过大

3.Survivor设置过小

4.Survivor设置过大

GC策略的设置方式:1.吞吐量优先 2.暂停时间优先

12.Minor GC,Full GC 触发条件?

Minor GC触发条件:当Eden区满时,触发Minor GC

Full GC触发条件:

1.调用system.gc时,系统建议执行Full GC,但是不必然执行

2.老年代空间不足

3.方法区空间不足

4.通过MInor GC后,进入老年代的平均大小,大于老年代的内存

5.由Eden区,From Space区向To Space区复制时,对象大于To Space内存,则把该对象转到老年代,且老年代的可用内存大小小于该对象大小

13.JVM性能调优?

1.设定堆内存大小

2.设定新生代大小

3.设定垃圾回收器

14.JAVA中堆和栈的区别?

栈用来存储局部变量和方法调用,栈内存属于单个线程

堆用来存储Java中的对象,无论成员变量,局部变量,类变量,指向的对象都存储在堆内存,堆内存是线程共享

15.常见的垃圾回收算法?

基础算法三种:标记清除算法,复制算法,标记压缩算法

垃圾回收器采用分代收集算法

标记清楚算法,标记出需要回收的对象,标记完成后统一回收

复制算法,可用内存划分为大小相等两块,每次用其中一块,内存用完,将活着的对象复制到另一块,然后使用过的内存空间清除掉

标记压缩算法,标记出需要回收的对象,将所有存活的对象向一端移动,清理掉以外的内存

分代收集算法,根据新生代,老年代,收集清理

16.解释栈,堆,方法区?

栈,基本数据变量,对象的引用,函数调用

堆,new关键字,构造器创建,垃圾回收器主要管理

方法区,常量池是方法区的一部分

17.什么是类的加载?

将类的.class文件二进制数据读入到内存中,放在运行时数据区的方法区内,然后在堆区创建一个对象

18.类加载器有哪些?

启动类加载器,

扩展类加载器,

应用程序类加载器

19.java对象创建过程?

1.jvm检查能否在常量池定义到类的符号引用

2.为对象分配内存,指针碰撞,或空闲列表方法,最常用的就是本地线程缓冲分配

3.将除对象头外的对象内存空间初始化为0

4.对对象头进行必要设置

20.java类的生命周期?

1.加载

2.连接

3.初始化

4.使用

5.卸载

21.都有哪些垃圾回收期?

Serial收集器,串行收集器,只使用一个线程去回收,

ParNew收集器,其实就是串行收集器的多线程版本,

Parallel收集器,类似ParNew收集器,只是更关注系统的吞吐量,

Parallel Old收集器,使用多线程和标记整理算法,

CMS收集器,获取最短回收停顿时间为目标的收集器,

G1收集器,面向服务器的垃圾收集器,

22.JVM调优指令?

1.jps,显示指定系统内所有的虚拟机进程

2.jstat,监视虚拟机运行时状态信息,

3.jmap,用于生成heap dump文件

4.jhat,与jmap搭配使用,

5.jstack,生成java虚拟机当前时刻的线程快照,

6.jinfo,实时查看和调整虚拟机运行参数

23.描述JVM加载class文件的原理机制?

由类加载器和子类来实现,类的加载是指把类的.class文件中的数据,读入到内存中,通常是创建一个字节数组读入.class文件

24.GC是什么?为什么要有GC?

GC就是垃圾收集的意思,

忘记或者错误的内存回收,会导致程序的不稳定甚至崩溃,,

25.垃圾回收期的基本原理是什么?

创建对象时候,GC就监控这个对象,监控对象哪些时可达,哪些是不可达,当确定对象不可达时,GC就可能回收说这些内存空间

26.Java中引用类型哪几种?

1.强引用,若一个对象强引用,就不会被垃圾回收器回收,即使内存空间不足,也不会回收,而是抛出异常,使程序停止,若想中止,将引用赋值为null,jvm就会在合适的时间回收该对象

2.软引用,内存足够,继续使用,内存不足,就会回收

3.弱引用,无论空间是否充足,都会回收,由于垃圾回收期是一个优先级叫较低的线程,并不一定迅速发现弱引用对象

4.虚引用,形同虚设,任何时候都可能被回收

六:设计模式

1.设计模式分类

根据目的来分:

1.创建型模式,将对象的创建与使用分离

2.结构型模式,如何将类或对象按某种布局组成更大的结构

3.行为型模式,类或对象怎样互相协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责

根据作用范围来分:

1.类模式,处理类与子类之间的关系

2.对象模式,处理对象之间的关系

2.设计模式的优点

1.多个项目重复使用

2.帮助定义系统架构解决方案

3.吸收经验,提供设计透明,被实践证明有效

3.设计模式的六大基本原则?

1.单一原则,一个类只负责一项职责,做到类只有一个行为引起变化

2.替换原则,子类可以扩展父类的功能,但不能改变原有父类的功能

3.依赖导致原则,面向接口编程

4.接口隔离,建立单一接口

5.最少知道原则,降低类与类之间的耦合

6.开闭原则,抽象构建架构,实现扩展原则

4.熟悉的设计模式

单例模式,只被创建一次,节省系统开销

工厂模式(简单工厂,抽象工厂),解耦代码

观察者模式,对象之间一对多依赖,一个对象改变,其它对象都改变

外观模式,提供统一接口,访问子系统的接口,让子系统更容易使用

模板方法模式,提供算法的骨架,子类步改变算法结构的情况下,重新定义算法步骤

状态模式,允许对象内部状态改变时改变行为,看起来像是修改了类

代理模式,不访问目标类,通过代理间接访问对象,增加功能

桥接模式,抽象与实现分离,组合关系代替继承关系,降低抽象和实现的耦合

策略模式,定义一系列算法,算法封装起来,算法之间可以互相替换,算法的改变不影响使用算法的客户

5.代理模式

代理模式,就是指不直接访问目标类,通过代理的方式间接的访问目标类

1.可以记录日志

2.可以拦截

3.事务控制,权限控制

静态代理:

​ 一个代理只能代理一个类

动态代理:

​ 一个代理可以代理多个类

jdk动态代理:

​ 只能代理目标类实现的子类,执行效率低,加载速度快(反射执行)

cglib动态代理:

​ 基于asm字节码生成目标类对应子类的字节码文件,继承目标类,执行效率高,加载速度慢(启动时,生成字节码文件)

七:mybatis

1.什么是ORM框架?

orm对象关系映射,简单理解,数据表中的一条数据可以映射为软件中的一个对象

ORM框架:解决的问题就是如何将数据表中的数据,读取出来,直接转换为对象,将java中的对象直接保存到数据库中,有时候也成为持久层框架,数据落地到数据库,掉电不丢失

2.mybatis和hibernate的区别?

相同点:

1.都属于ORM框架

2.都是对jdbc的包装

3.都属于持久层的框架

不同点:

1.hibernate是面向对象,mybatis面向sql

2.hibernate全自动orm,mybatis半自动orm

3.hibernate查询必须全字段查询,mybatis不用

4.hibernate级联操作,mybatis没有

5.hibernate降低对象和数据库的耦合性,mybatis提供动态sql,需要手写sql,hibernate移植性大于mybatis

6.hibernate有方言夸数据库,mybatis依赖于具体的数据库

7.hibernate有完整的日志系统,mybatis相对欠缺

3.mybatis框架的优缺点

优点:

1.基于sql语句编程,sql写在xml里,解除sql与程序代码的耦合,提供xml标签,支持编写动态sql语句,可以重用

2.与JDBC相比,减少了大量的代码量,解决大量冗余问题,不需要手动开关连接

3.能与各种数据库兼容,基于JDBC连接数据库,JDBC支持的,mybatis都支持

4.与spring很好的集成

5.提供映射标签,支持对象与数据库的ORM字段关系映射,提供对象关系映射,支持对象关系组件维护

缺点:

1.sql语句编写工作量大

2.sql语句依赖于数据库,导致不能随意更换数据库

4.什么是懒加载?

懒加载:针对多表联查(一对一,一对多)
单表查询,在需要数据时 在触发关联的数据查询
好处:提高查询效率
坏处: 如果数据量大,加大等待时长

5.mybatis 缓存有哪些?

一级缓存:基于sqlsession,所有查询都会缓存,一旦发生增删改,缓存立即清除

二级缓存:基于namespace ,有多个sqlsession 共享

一级缓存,二级缓存之间的关系?

查询时先查询二级缓存,没有再去一级缓存,一级没有去数据库
一级缓存 只有在sqlsession commit() 或者 close() 才会将缓存提交到二级

一级缓存二级缓存同时存在,有可能存在脏数据问题

6.如何开启二级缓存?

eviction=“LRU” 缓存是有大小限制,超过大小要 清除一些缓存
LRU(默认) 最近最少回收,移除最长时间不被使用的对象
FIFO 先进先出,按照缓存进入的顺序来移除它们
SOFT 软引用,移除基于垃圾回收器状态和软引用规则的对象
WEAK 弱引用,更积极的移除基于垃圾收集器和弱引用规则的对象

7.mybatis 如何开启事务?

openSession(false) 关闭自动提交,开启事务

提交事务 sqlSession.commit();
回滚事务 sqlSession.rollback();

八:spring

1.什么是spring?

Spring 就是一个容器,容器内放置了bean(就是放置到容器中的对象),容器管理bean的生命周期,容器启动,创建对象并加入到容器中,变为bean,

bean就是对象,只不过对象由容器保存

2.spring实现beanFactory和ApplicationContext?

beanFactory是最原始的Factory,无法支持spring的许多插件功能

ApplicationContext是beanFactory的子类,多了国际化,资源访问,事件传播机制

1.ApplicationContext,bean默认的singleton,无论是否使用,都会被实例化,优点预先加载,缺点浪费内存

2.beanFactory,bean只有使用的时候才会被实例化,优点节约内存,缺点浪费内存

3.没有特殊要求,使用ApplicationContext

3.什么是bean?

bean就是spring的对象,由容器创建并负责维护bean的生命周期,

4.bean中id和name的区别?

id: bean 的唯一标识,

name:bean的名字,可以有多个,使用",“分割,

id 和 name 都不能重复

5.spring控制反转,依赖注入?

ioc控制反转,自己不创建对象,而是spring容器创建对象,创建的控制权交给spring容器

di依赖注入,容器中bean之间的依赖关系,一个bean依赖另外一个bean,可以注入进来

6.spring常用作用域?

作用域,bean在容器中存在的时机

singleton,单例模式,容器启动时,创建bean并且持有管理bean,容器中只有一个

prototype,多例模式,容器启动时,不创建bean,容器获取bean时,每次都是新的bean,容器只创建,不持有不管理

request,每次http请求,使用request定义的bean都是产生新的bean,只有在web应用,该作用域才生效

session,每次httpSession,使用session定义的bean都将产生一个新的实例

globalsession,每个全局的httpSession,使用session定义都会产生一个新的bean

7.springbean的生命周期

bean的生命周期 和 bean 作用域相关,

singleton:单例 容器启动时创建bean ,还会调用 init-method 进行初始化,将bean加入到容器中
当容器销毁时 调用 bean destroy-method 释放资源

prototype:原型 当容器启动时 不创建bean
当从容器中获取bean时 创建,可以调用init-method 进行初始化,容器销毁 bean不会销毁

8.常用spring注解?

注入注解:

@AutoWired: 1.首先根据注解属性的类型 去查找
2.如果查找到多个 使用 属性名 作为id进行区分查找 如果找到就设置
3.如果还不能搞找到使用 @Qualifier(“id”)进行区分

@Resource:
1.首先根据属性名 去查找
2.找不到根据属性类型查找
3.如果还是找不到 @Resource(name=“id/name”)

生成bean的注解:

@Component 生成bean
@Service 是@Component 子类,只适用于service 层
@Controller 是@Component 子类 只适用于控制层
@Repository 是@Component 子类 只适用于持久层

AOP:

@Aspect 声明一个切面
@PointCut 声明一个切入点

前置通知 @Before:在目标方法执行前调用

环绕通知 @Around: 在目标方法执行前后 调用
后置通知 @AfterReturning:在目标方法执行后(正常执行,异常不调用)调用

最终通知 @After:在目标方法执行后(不管是否有异常都会调用)
异常通知 @AfterThrowing:在目标方法执行 发生异常时,调用

MVC:

@Controller 标记类上 控制类 加入到容
@RequestMapping
标记在方法 处理器方法
标记类 方法该控制类下的处理器路径要补全
@GetMapping
@PostMapping

@RequestParam 配置参数别名 在前端传递参数和接受参数不一致 基本类型

@ResponseBody 处理器返回对象 转换为json
@RequstBody 处理接受json 转换为 java 对象

@RestController 标记在类上 等价于@Controller + @ResponseBody
当前控制器下所有的处理器都返回json

事务注解:

@Transactional

9.什么是spring自动装配?

将一个bean 注入到另一个bean当中,默认情况下不会开启自动装配,需要手动开启自动装配

10.自动装配有哪些方式?

no,默认,表示没有自动装配

byName,根据bean的名称

bytype,根据类型

构造函数,根据构造函数

autodetect,首先尝试通过构造函数,如果不行,尝试通过byType

11.自动装配的局限性?

1.覆盖的可能性

2.基本元数据类型

3.困惑的性质

12.半自动装配?

13.什么是springAop?

面向切面编程,在spring中切面就是一个类,封装了公共代码

aop 将公共代码/业务抽离 封装切面 对应目标方法进行拦截,记录日志,鉴权 事务

aop的底层实现是jdk和cglib

14.springAop的实现方式有哪些?

​ 1.基于ProxyFactoryBean 生成 代理对象
​ ProxyFactoryBean 实现FactoryBean
​ 2.基于aspectj

15.BeanFactory 和FactoryBean 区别?

​ FactoryBean:用来创建对象 在容器初始化时 创建bean
​ BeanFactory: 容器核心实现类 主要用来获取对象

16.springAop常用通知类型?

前置通知 @Before:在目标方法执行前调用

环绕通知 @Around: 在目标方法执行前后 调用
后置通知 @AfterReturning:在目标方法执行后(正常执行,异常不调用)调用

最终通知 @After:在目标方法执行后(不管是否有异常都会调用
异常通知 @AfterThrowing:在目标方法执行 发生异常时,调用

17.什么是springMVC?

spring 按照mvc 模式开发的一个轻量级 mvc 框架,。它与Struts2框架一样,都属于MVC框架

springMVC只有一个DispatcherServlet,不存在其他Servlet,支持国际化,支持多种视图技术

18.springMVC各种器有哪些,有什么作用?

前端控制器:DispatcherServlet 负责分发请求路径,是springmvc 的中枢,在web.xml配置

后端控制器:@Controller 标记的类 或者实现 Controller 接口,内部放置的是处理器

处理器:处理器前端路径对应的请求 返回数据
本质就是一个方法
使用@RequestMapping @GetMapping …
Controller.handerRequest()

处理器映射器:map <路径,<控制器实例,处理器方法,参数>>
<路径,>
根据路径找到处理器

处理器适配器:兼容前端端控制器发来的处理器,调用处理器方法
使用@RequestMapping @GetMapping …
Controller.handerRequest()

视图解析器:
1.解析处理器返回的数据(结果集)转化为视图
2.可以补全jsp 前缀 后缀

19.springMVC执行流程?

20.spring 处理器方法 默认参数有哪些,返回值有哪些

默认的参数:

HttpServletRequest
HttpServletResponse
ServletRequest
ServletResponse

Model
map
ModelMap

返回值:

string
1.jsp 路径,
2.以forward:/路径 转发(200)
3.以redirect:/路径 重定向(第一次302,第二次200)
void
modelAndView

21.事务

四大特性:

1.一致性,总额不变

2.隔离性,两个sqlsession能否看到对方的数据

3.原子性,要么都成功,要么都失败

4.持久性,掉电不丢失,持久到磁盘

22.什么是事务的隔离级别?

一个sqlSession能够看到另一个sqlsession提交数据的程度

脏数据的程度:

脏读,一个事务可以看到另外一个事务未提交的数据

不可重复读,一个事务查询同一行数据多次,结果不一致,针对于修改

幻读,一个事务查询同一个sql(查询多行数据),查询出来数量,不一致,针对于增删

隔离级别:

读未提交,允许脏读,允许不可重复读,允许幻读

读已提交,不允许脏读,允许不可重复读,允许幻读

可重复读,不允许脏读,不允许不可重复读,允许幻读

序列化读,不允许脏读,不允许不可重复读,不允许幻读

从上到下,级别越高,性能越差

23.什么是事务的传播行为?

传播行为,在一个方法中开启了事务,我们调用另一个方法也开启事务,那么方法1能否传递给方法2中

required,必须的,如果方法1开启了事务,方法2使用方法1的事务;如果方法1没有开启事务,方法2自己开启事务

supports,如果方法1开启了事务,方法2使用方法1的事务;如果方法1没有开启事务,方法2不开启事务

requires-new,如果方法1开启了事务,方法2使用自己的事务;如果方法1没有开启事务,方法2自己开启事务

24.springboot作用?

1.简化spring应用开发流程,提高效率

2.开箱即用

3.约定优于配置(springboot的自动装配)

25.springboot常用注解?

@SpringbootApplication 启动类

@ConfigurationProperties(prefix = “student”) 批量读取文件配置

@Validated 开启格式校验

@Value 读取单个属性

@PropertySource 读取自定义配置文件

@Configration 标记当前类是一个配置类

@Bean 默认名字是方法名字

@Mapper 让当前接口生成bean 并加入到容器

@MapperScan 等价于每个类注解了@Mapper

@RunWith(SpringRunner.class)

@SpringBootTest 表明当前类是 springboot 单元测试类 必须和启动类 在同一包下

26.springboot如何配置静态资源?

在esources目录下创建

public,static,resources,META-INF/resources,优先级从低到高

九:git

1.git的作用

1.版本控制工具,可以记录代码所有提交的版本

2.代码协作工具,工程师之间代码的交互通过git

2.git仓库有哪些分类

本地仓库:git

远程仓库:

​ 开源,github gitee

​ 私有,gitlab

十:linux

什么是生产环境,开发环境测试环境?

环境:就是软件运行在那种操作系统中

生产环境:就是线上环境 ,直接面向用户(不可以在线修改用户数据 不可以debug)

开发环境: 程序员开发代码测试所处环境 可以随意修改数据 debug
代码在程序员电脑中 数据库测试
和生产环境隔离

测试环境:就是测试人员 专门测试代码功能业务逻辑 及性能测试环境 也是独立

linux和windows区别?

在linux中一切皆文件,网络,磁盘驱动,软件,都是文件

严格区分大小写

在linux 名称可以创建 任何文件,没有后缀名 但是一般有约定

十一:docker

Docker:其实是一个虚拟化工具 类似于 vmware,但是更加轻量级 ,dokcer 是进程级别的(使用宿主 cpu 内存 硬盘), vmware 是系统级别,必须有自己的硬盘 内存 cpu

集装箱: 特点就是标准化

​ 在docker 中集装箱就是 封装了 代码需要的环境(jdk tomcat mysql 及代码) 又称为镜像

镜像:就是集装箱 封装了代码 +环境
容器:将镜像运行起来 就是容器 活的
中央仓库:存储镜像发布镜像

数据卷

数据卷:其实就是docker存储数据的文件夹,就是文件夹,将系统的文件夹 和 容器中对应文件夹进行 映射,普通文件夹也可以作为数据卷,相当于开了一个后门通道:可以在linux修改文件,容器可以实时看到,两者实时同步

Docker-Compose

Docker-Compose 是一个容器编排工具,我们可以通过 Docker-Compose 一键 启动所有的容器,并管理容器的依赖关系

十二:redis

redis简介

Redis是非关系型数据库,是key value型数据库,类似Map,但是功能 数据结构比Map更加强大

1.特点:key value

2.数据基于内存存储

3.使用c语言编写(性能好)

4.读写速度快(110000/s读取数据以及81000/s写入数据 ,而mysql 8000-10000(基于磁盘存储))

5.支持持久化机制

6.支持主从集群模式提供高可靠保证(重点)

redis数据类型有哪些?使用场景?

​ 1.string 普通键值对
​ 2.hash 存储map 对象
​ 3.list 有序集合 作为消息队列使用
​ 4.set 无序集合 去重 取交集 并集
​ 5.zset 有排名集合 根据积分进行排序 主要用于热搜,排名

​ 设置key时要注意一下两点:

​ 1.key都要有前置和后缀

​ 2.key尽量设置有效时间

redis作用

​ 1.存放热点数据
​ 2.作为缓存使用 (mybatis 二级缓存)
​ 3.作为消息对列
​ 4.作为分布式锁 setnx 如果key 不存在 ,就设置成功
​ 如果key 存在,什么都不做 --》没有抢占成功锁

如何使用redis实现分布式锁?

使用 setnx key value 如果key 不存在 ,正常设置—》持有锁
如何过key存在,则无法设置值—》无法持有锁

当key 不存在时 可以设置成功 就相当于抢到了锁

当key 存在则是,什么都不做 就相当于 别人持有了锁,自己需要阻塞尝试设置成功 得到锁

redis有哪些集群模式?

主从模式:

主机负责读写 ,从机负责读;主机挂了就不能提供写服务,需要手动将从库改为主机

特点: 1.主机内存有限

​ 2.无法自动切换

哨兵模式:

一主多从 ,每台机器都有哨兵监控对应redis 状态,
一旦redis 主进程挂了,哨兵立即进行选举 将选举出来的从机变为主机 提供读写服务

特点: 1.可以实现高可靠 自动切换主机
2.主节点内存容量限定整个集群容量

去中心化模式:

有多个主节点,每个主节点 只负责读写 一部分数据,

多主多从,三主三从。主机可以接受读写,从机只接受读 ,整个集群将数据分别存储到16384 个 slot(hash槽),每台主机分享一部分,主机挂了,对应的从机立即上位变为主机

特点: 1.内存随主机数量成倍增加
2.高可靠 主机挂了从机立即上位

redis持久化机制?

Redis持久化机制:Redis 是基于内存的缓存,所有数据都存到内存,但是redis也会将数据存储到硬盘,以便于关机再开机可以立即回复数据。

RDB:

默认存储形式,RDB就是redis 内存数据做的一个镜像 存储到磁盘

特点:1.隔一段时间生成新的镜像,消耗性能

​ 2.特定时间,发生宕机,数据丢失问题

​ 3.宕机之后,回复数据快

AOF:

aof 就是一个文件,redis会将所有用户执行的 增删改 命令记录下来,写入一个aof 文件中

aof 默认是 不开启,最好 rdb 和 aof 同时使用

特点:1.几乎可以做到不丢数据

​ 2.aof宕机之后,回复较慢

​ 3.相对于rdb来说,持久化性能耗费较少

如何使用redis实现高可靠

通过集群模式,和持久化机制实现高可靠

如何实现mybatis使用redis作为二级缓存?有什么好处?

如何实现:

1.配置开启二级缓存
mybatis.configuration.cache-enable=true
2.实现 Cache 接口,给用户自定义存储二级缓存
3.在对应的mapperxml 中声明

好处:

​ 1.提高查询效率
​ 2节约jvm 内存 便于垃圾回收
​ 3.降低mysql 查询服务器压力

spring 缓存和mybatis 使用redis 二级缓存的区别?

mybatis 使用redis 二级缓存 :仅限于 查询数据库 将数据库结果缓存 发生在 dao层

spring 缓存 无论在哪里只要标记对应的方法 ,就会在下次调用该方法时 直接返回结果,不会调用该方法执行

在springboot 中 RedisTemplate 和StringRedisTemplate使用了什么设计模式?两者有何区别?

RedisTemplate,StringRedisTemplate 都使用了 模板 设计模式
模板 :只要实现了模板接口的实现类 ,用户调用不同的 实现类,在使用方式上没有区别

RedisTemplate 默认序列化 jdk序列化(不便于查看,阅读) 可以自定义 keyString 序列化 value 使用 json
StringRedisTemplate key value序列化 String类型

ApplicationContextAware 接口的作用?

方法加入到容器中的bean 如果实现ApplicationContextAware接口
那么在初始化bean时 回回调ApplicationContextAware。setApplicationContext( ApplicationContext ) 传递过来 ,也就是说该bean 持有了当前容器上下文(ApplicationContext),通过容器的上下文可以或缺容器中的而所有的 bean

redis缓存的常见问题

缓存穿透

查询时,查询的数据在数据库中没有时,不会存在redis缓存中,每次都回去mysql中查询

解决方法:

1.如果按照主键自增id查询,可以比查询id和表中最大id进行比较;如果超过最大值,直接返回空数据
2.在查询id查询 先去set 看一下, 数据表中有没有这条数据,直接返回空数据;还可以通过布隆过滤器 检查 id 是否存在。 布隆过滤器 适合海量数据(hbase )
3.如是用户恶意攻击,可以限制用ip

缓存击穿

查询时,缓存中的数据失效,不得已去数据库中查询

解决方法:

1.热点数据 设置较长的失效时间 (或者永久)
2.设置不同的失效时间
3.如果如何key失效, 在高并发是可以加分布式锁 ,将数据库压力

雪崩:

缓存击穿大批量的key 同一时间集体失效,去数据库查询,造成 mysql压力过大 (tomcat 等待mysql 返回数据过长 ,造成tomcat连接堆积 ,tomcat 连接数饱和,线程数 ,内存增大,----tomcat 挂了) 这就是雪崩

解决方法:

1.热点数据 设置较长的失效时间 (或者永久)
2.设置不同的失效时间
3.如果如何key失效, 在高并发是可以加分布式锁 ,将数据库压力

缓存倾斜:

热点数据放在一个redis节点上,导致redis节点无法承受住大量的请求,最终redis宕机

解决方法:

1.扩展主从结构,搭建大量的节点,环节redis压力,也就是设置去中心模式

2.可以在tomcat中使用jvm缓存,声明一个map作为缓存,在查询redis之前,先去查询tomcat中的缓存

十三:ngixn

Nginx是一款轻量级的Web服务器/方向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like协议下发行,其特点是占有内存少,并发能力强

nginx作用:

1.反向代理

反向代理:就是nginx 可以代理我们的tomcat ,用户只需要访问nginx 不需要知道真正提供服务的Tomcat 的ip,通过nginx 访问就可以了

正向代理:客户端主动需要一台代理服务器 ,通过代理服务器去访问目标服务器

2.负载均衡

就是用户请求过来到达nginx ,nginx 将请求 转发个tomcat 处理 响应请求,如果每秒都有1000次请求,nginx 会根据tomcat 机器的性能 均衡分配(能者多劳)

负载均衡算法
(1)轮询 (默认算法)
(2)weight (能者多劳,物尽其用)

根据两个端口号设定比例,选择使用次数

(3)ip_hash

nginx 会根据用户的 ip 对应的hash 对tomcat 数量进行取余,来决定用户访问那一台tomcat;

(4)backup

备胎策略 ,所有能用的tomcat 都挂了,备胎上位

(5)down

让当前对应的tomcat 下线 ,便于升级tomcat

(6)max_fails

允许请求的失败次数,默认为1,配合fail_timeout一起使用

经历max_fails次失败后,暂停服务的时间,默认为10s(某个server连接失败了max_fails次,则nginx会认为该server不工作了。同时,在接下来的 fail_timeout时间内,nginx不再将请求分发给失效的server。)

3.动静分离

就是将我们以前工程中的 静态资源 放在nginx中,使用nginx 提供静态资源服务,使用tomcat 提供动态资源

为什么要做动静分离?

1.tomcat 加载静态资源性能差

2.让tomcat专注于 响应用户动态请求,降低Tomcat压力

3.修改静态代码,不需要重置tomcat ,只需要将nginx 对应静态目录文件 替换就可以

nginx 和 tomcat 的区别?

tomcat : Servlet 容器 可以响应用户动态请求,编译jsp,加载静态资源

nginx:高性能http 服务 静态资源加载 ,服务分发(负载均衡,反向代理) 还可以左右邮件服务器

十四:vue

vue是一套基于构建用户界面的渐进式框架,只关注图层。

MVVM模式

model:模型/数据

view:视图/界面

viewmodel:视图和界面的绑定

vue语法

-----{{}} 插值表达式

------事件指令,只能用在button标签中,v-on:click=“方法名” @click=“方法名”

--------v-model 数据绑定,只能用在input标签中,input中修改的数据会立马同步到vue实例中message,

​ methods 写的都是vue实例中的方法,可以被调用,

​ 双向绑定,加载时可以初始化input,输入数据时同步修改

--------computed和methods方法一样,都是用在vue实例中的方法,区别是computed有缓存,methods没有缓存,当依赖的数据发生变化时候,computed内的方法只计算一次,而 methods会计算多次(调用几次,计算几次),调用computed方法时候不用加(),computed性能更好

---------watch,监控数据的变化,再watch写data中数据,对应的方法,监控数据的变化

Component

vue组件是最常用的模块,需要用到前端代码块的复用,将公共代码块的抽离,就是我们的组件

组件分为两类:

全局组件:在工程中任何地方都可以使用

局部组件:只能在当前vm实例中使用

1.template 标签声明一个模板

2.Vue.component(‘componentmsg’,{

template:模板id5

props:[“声明参数”]

})

3.componentmsg v-bind:声明参数=声明参数的值,绑定vue中的参数数据

生命周期

vue实例生命周期:实例化(create)—>绑定将vue实例和el 对应的节点(mount)—》如果数据变化(update)----->销毁(destory)

声明周期对应的方法:8个

beforeCreate() 实例化前

created() 实例化后

beaforeMount() 挂载前

mounted() 挂载后 初始化数据,发生在当前位置

beforeUpdate():更新前

updated():更新后

beforeDestory():销毁前

destoryed():销毁后

所有vm实例内的方法调用都要加$ this.$de’s’troy()

路由

路由:路由器分发网络

vue路由:根据不同的路径响应不同的界面

router:路由管理者 负载分发请求

route:一条路由 包含 路径 组件 名字 (一个路径 +一个界面(组件))

routes:多条路由组成数组

声明路由routes= [path:“路径”,component:路由名字]

声明路由管理者router = new VueRouter({ routes:routes})

将路由管理者设置到vue实例中

使用路由

网络请求

vue异步请求:

axios:

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中

1.从浏览器创建

2.支持Promise API

3.拦截请求和响应

4.转换请求数据和响应

5.自动转换JSON数据

axios({

​ url: 路径

​ method:请求方式(post)

​ params:{

​ id:vm.id(vm实例中的id)

}

​ . then(function (response) { 接收返回的数据

​ alert(“data” + JSON.stringify(response.data) );弹出查询的数据

​ vm.content = response.data.name; 返回的数据

})

​ . catch(function (error) {

​ alert(“服务器异常:”+error)

})

})

vue实例化

声明全局组件

1.在components目录下创建vue

------2.template标签,引用组件参数

------1.声明组件参数

​ export default {

​ name:部件名字

​ props:[“形参”,“多个形参”]

}

2.在main.js中声明全局组件

import 组件名字 from 组件路径

Vue.component(“声明组件”,组件名字)

3.在App.vue使用组件

--------3.<MyContent v-bind:绑定数据或方法>

--------4.export default{

}

声明局部组件

1.import 组件名字 from 路径

2.export default {

​ components: {

​ //声明局部组件

​ “HelloWorld”:helloword

}

}

1.computed 中的 方法调用 和 methods 的区别?

1.computed 是有缓存 ,只要依赖数据发生改变就会计算 ,无论调用多少次 只计算一次
methods 没有缓存 只要依赖数据发生改变,调用多少次,就计算多少次

2.调用方式区别 computed对应方法不加()
methods 对应的方法加()

2.写出vue生命周期方法

create mount update destroy

beforeCreate()
created() 创建 vm 实例

beforeMount()
mounted() 界面绑定之后初始化数据

beforeUpdate()
updated() 页面数据更新之后使用

beforedestroy()
destroyed() vm 实例销毁

3.vue 路由中 router route routes 都是什么?

路由:分发路径 根据不同的路径,响应不同的界面

route:一条路由 (路径 组件 name) 一个路径 对应一个界面(组件)
routes:多个路由组成
router:路由管理者 负责分发路径

4.什么是node.js?

node 是一个前端框架,也是一个运行环境
node.js 不仅可以写前端,还可以使用js写后端

5.什么是npm? 常用命令

npm 是一个包管理工具,帮助我们下载依赖 相当于java 中的maven

npm install 插件名 --save
npm run dev 调试环境运行
npm run build 编译,构建工程

vue init webpack 工程名 初始化vue

6.什么是vuex ?作用?

vuex vuex 全局变量的存储,作用:便于多个组件之间 交换,共享数据
eventbus

state 转态 存储数据

getters 用来获取state中的数据

mutations 用来修改 state 中的数据 阻塞改变数据

actions 用来修改 state 中的数据,但是他是异步修改(不会立即改变,不会阻塞)

十五:日志相关

1.日志简介

日志框架就是记录应用中所有的事件,可以将事件以文件文字的形式 输出到控制台 还可以输出到文件中

2.日志作用

1.记录事件

2.帮助我们快速的调试代码,通过日志就可以知道代码的运行情况 通常用户与生产环境调试

3.日志级别

日志级别从低到高:

TRACE(踪迹)、DEBUG(调试)、INFO(信息)、WARN(警告)、ERROR(错误)、FATAL(致命错误)

最常用 debug info

十六:微服务框架

1.什么是微服务框架

微服务 就是将一个应用按照功能进行拆分,每一个功能都是一个独立的应用,应用之间可以通过http/tcp 请求互相调用

java 微服务中最常用的框架springcloud

2.什么是springcloud

springcloud 就是基于springboot实现的微服务框架,springcloud可以认为是一个标准,一套接口/规范,基于这种规范有了两大类实现

3.如何实现springcloud

—1.springcloud netflix

是springcloud 的第一代版本

—2.springcloud alibaba

springcloud 的第二代版本,阿里开发

4.Nacos作用

就是微服务的,注册中心和配置中心

1.服务发现注册
2.健康检测服务中的实例 可以动态感知 实例是否有问题
3.动态dns
在使用 ribbon 时 根据服务名 可以查找到对应的实例
4.存储实例的元数据

5.Nacos中创建服务者(响应),和消费者(请求)

6.什么是ribbon,有哪些负载均衡算法 ?

ribbon 负载均衡器,作用就是负载均衡

负载均衡算法:
1.随机,随机选择

2.轮询,按照顺序选择
3.重试,选择的不成功,会继续选择成功的
4.最低并发数,逐个考察,选择并发最低的
5.过滤,过滤掉一直失败的
6.响应时间权重
7.区域加权

7.springcloud常用组件

nacos:注册中心和配置中心
ribbon:负载均衡器

feign:伪装接口
sentinel:哨兵
sleuth:链路追踪
gateway:网关

8.什么是restTemplate?

restTemplate 是一个工具类,帮助我们发起http请求
发起有三种形式
1.restful 风格 使用 路径传参

接受 必须使用@PathVariable

2.普通的key value
接受必须使用 @RequestParam 配置参数
3.提交对象 转json -post 形式提交
接受必须使用 @RequestBody

9.Feign是什么?

Feign就是伪装,

feign 将调用远程的请求 伪装成本地的接口,让应用调用,非常的方便,

springcloud微服务之间,互相调用是通过restTemplate互相调用,传入路径和参数,就可以完成http请求

10.Feign作用是什么?

feign: restTemplate + Ribbon + 容错

​ 网络请求 + 负载均衡 + 容错

feign负载均衡,

feign容错,

容错是指,当我们消费者依赖了提供者,如果服务提供者出现异常,或者瘫痪,我们配置了feign消费者容错,那么当提供者出现异常或者瘫痪,我们依然可以继续提供服务

容错可以保证我们服务的高可用(类似备胎,短暂使用,一般容错返回的都是死数据)

11.Nacos Config分布式配置中心

将同一服务的配置文件放置到nacos 中,每次应用启动时,会从nacso拉取最新的配置文件,初始化到应用中,并且如果配置中的的配文件值发生变化,应用也会立即感知到

可以使用nacos配置中心,来配置我们开发过程中的多个环境,

开发环境,测试环境,生产环境

12.springboot配置文件,配置顺序?

bootstrap.properties > bootstrap.yaml >application.properties > application.yaml

从左到右,优先级依次降低

13.读取配置文件顺序

先去bootstrap.properties/ bootstrap.yaml ,如果配置了nacos,并且nacos配置中心有对应的该服务的额配置文件也会去nacos配置中心拉取配置文件, 再去本地 application.properties/application.yaml

bootstrap.properties/ bootstrap.yaml ---->线上nacos 服务名.properties -----》本地 application.properties/application.yam

如果配置了nacos 中的配置文件 则同一个属性 nacos 中的配置文件的属性会把bootstrap.properties 中的属性进行覆盖

14.Sentinel哨兵是什么?

Sentinel哨兵是springcloud中一个组件,作用是监控各个应用中接口的流量,并且可以根据流量的大小,

完成流量熔断(超过流量触发熔断),

异常熔断(一定时间内超过一定数量的异常触发熔断),

超时熔断(超过响应时间的比例触发熔断),

容错(如果被调用的服务挂了,哨兵也有自己的容错功能,和feign容错功能类似)

总的来说哨兵的作用就是,

流量监控 和 熔断降级 (容错)

15.sentinel哨兵的几种流控规则 &降级规则 ?

流控规则 &降级规则 都是配置降级策略,一旦达到一定的条件就会熔断(触发降级策略)

流控规则

1.qps(访问次数),

每秒钟,每个机器对应的接点,只能接收设置次数的请求,超过次数就会触发限流降级策略

2.线程数,

每台机器对接点开启的最大线程数多少,控制并发量,限制占用过多的线程,超过触发限流降级策略

降级规则

1.慢调用比例,

设置多个请求,如果请求响应时长,超过最大平均响应时长数量,就会触发熔断。

比如,设置响应时长5秒,5个请求,请求比例为0.5,熔断时长为5秒,

意思就是指,当5个请求,超过0.5比例的请求,请求时长超过设置的响应时长,就会触发熔断降级

2.异常比例,

设置多个请求,如果请求的异常比例,超过设置的比例,则触发熔断

3.异常数

设置请求异常个数,请求异常达到设置个数,触发熔断

15.sentinel哨兵特征?

sentinel以流量为切入点,从流量控制,熔断降级,系统负载保护等多个难度维护服务的稳定性

sentinel特征:

1**.丰富的应用场景**,突发流量控制在系统容量可以承受的范围,比如双十一秒杀

2.完备的实时监控,可以在控制台看到接入应用的单台机器数据,以及500台以下集群的总运行情况

3.广泛的开源生态,sentinel开箱即用,与其它开源框架更好的融合,比如springcloud,Dubbo,gRPC,简单的依赖和配置即可融合

4.完善的SPI扩展点,简单易用完善的SPI扩展接口,可以通过实现扩展接口快速的制定逻辑

16.Sleuth分布式链路追踪框架

其实就是一个日志框架,记录每个请求的调用时间,并且该请求调用其它请求的时间也会显示出来,请求之间的依赖关系也会显示出来

Span:基本工作单元,发送一个远程调度任务 就会产生一个Span,Span是一个64位ID唯一标识的,

​ 通俗的理解 一个span 就是一个方法(远程请求的方法)

Trace:用另一个64位ID唯一标识的,Trace还有其他数据信息,比如摘要、时间戳事件、Trace的ID、以及进度ID。

​ 通俗的理解 一个trace 就是一个网络请求(是对应一个网络请求从开始到结束的时间描述)

一个Trace由多个Span组成

17.ZipKin

Zipkin 就是一个插件,作用就可以接收sleuth 产生的数据,并使用可视化的方式显示出来,还可跟踪服务之间的依赖关系

18.Gateway(网关)

网关,微服务网关和路由器网关不同,他的功能类似于sevlet 中Filter spring中拦截器Interceptor

功能:拦截 过滤 鉴权 ,另外 动态路由(分发路径),负载均衡,限流

使用网关,可以完成负载均衡一般用于流量的分流,便于我们做ab测试

针对不同的服务 返回数据格式一致,但是内容不同

对所有经过gateway 的请求进行过滤鉴权,

19.什么是分布式事务?

分布式事务就是同一个业务处理多条sql,而多条sql发生在在多个应用中(或者多个数据源中),如何保

证我们业务的一致性,原子性

20.CAP理论,Base理论

CAP理论,

C:一致性,A:可用性,P:分区容错性,

分布式环境下不能同时满足cap,分布式环境下,三者取其二。

Base理论,

BA:基本可用,S:中间状态,E:最终一致性。

CAP 理论的妥协,业务开始可以,没有一致性,先保证可用性,通过一定的时间,使用补偿机制到最用

一致性

我们分布式业务无法满足cap三个特性,那我们就满足可用性,分区容错,达到基本可用的目的,通过

一些后补的错谁最终完成 最终的一致性

先基本可用,不强调 强一致性,只强调最终的一致性

21.分布式事务解决方案

四种解决方案,

2pc(两阶段提交)

两段提交分为两个阶段:

第一个阶段准备阶段,参与者开启事务,执行sql,保证数据库存在对应的数据,参与者会向TransactionManager(全局事务管理器)表示准备OK

1,开启本地事务,执行sql

2,将执行sql结果告诉全局事务管理器

第二个阶段,当TransactionManager(全局事务管理器)收到了所有的参与者的OK通知后,向所有的参与者发送Commit(提交)请求

3,全局事务管理器如果,发现所有的子业务也就是参与者,报告sql没有异常,则让所有的子业务提交事务,有异常,所有的子业务对应的事务都回滚

3pc(三阶段提交)

三阶段提交 其实就是在两阶段提交的基础上多了2个步骤,

多了,

1.对事务超时的判断 (假如如果有事务一直不执行,则将其他子业务执行的sql 通过undo 日志进行回

滚 )

2.对所有执行的sql 增加了 redo日志(执行的sql 记录下来) undo日志(课通过日志将数据复原)

TCC机制

Try,Confirm,Cancel 三个单词的缩写,他的执行需要和我们的代码耦合在一起,

Try: 尝试执行业务代码,对资源检查 与执行sql 检查资源是否足够

Confirm:确认 提交各个子模块的事务

Cancel:如果sql 有异常或者 资源不够充沛 则回滚

TCC机制 本质上2pc 流程基本上一致?

只不过TCC需要

1.将业务代码嵌套在 try 接口中 需要自己实现

2.需要检测资源是否可用

TCC,机制也就是你如果有钱,是你想买无尽 要先买暴风大剑,暴风大剑的钱够了 但是无尽钱不够,把暴风大剑的钱退给你

MQ分布式事务

使用消息队列(RabbitMQ)完成分布式事务,

这种模式全部需要自动手动来完成,非常的复杂,维护性很低,

四种解决方法其实都是 2pc的变种,都是两阶段提交

22,2pc与3pc的区别?

3pc 多了

1.对事务超时的判断 (假如如果有事务一直不执行,则将其他子业务执行的sql 通过undo 日志进行回

滚 )

2.对所有执行的sql 增加了 redo日志(执行的sql 记录下来) undo日志(可通过日志将数据复原)

23,什么是seata

Seata 是springcloud alibaba 的一个组件,在使用是必须依赖springcloud alibaba 和注册中心

(nacos) ,

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将

为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。

24,seata三个名词

seata有三个名词,

TM,全局事务管理器,发起全局事务,产生全局事务唯一XID,并负责全局提交或者全局回滚的决议,

TC,事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或者回滚,

这是一个通讯员,负责协调各个子模块之间的事务

RM,控制分支事务,每个分支会产生一个RM,控制分支事务,负责分支注册,状态汇报,接收事务协调器的指令,驱动本地事务提交和回滚,

负责本地事务的提交和回滚

25,seata工作原理

1,TM会向TC申请开启一个全局事务,全局事务创建成功并且生成一个全局唯一XID

2,XID在各个分支事务中传播

3,RM向TC注册本地事务,和对应的XID,

假如某个RM的sql执行有问题,RM也会将异常告诉TC,TC会告诉TM,TM收到某个RM有异常,就会通知TC凡是在XID下绑定的所有RM,事务都要回滚,TC会告诉XID下所有的RM,事务要回滚

4,TM向TC发起所有XID下的全局提交或者回滚,

假如所有的RM都没有问题,会通知到TC,TC会将结果告知TM,TM会告诉TC执行全局提交,TC会告诉RM执行提交

5,TC会调度所有XID下的所有RM全部事务提交或者回滚

26,seata四种模式

AT

最简单的分布式事务模式,底层使用的 就是两阶段提交 ,使用seata 中的AT 只需要一个注解即可,

TCC

TCC 模式,我们必须实现seata 为我们提供的TCC接口,所有的业务都需要自己实现,并且也要配合本

地事务,

性能非常的好,但是需要工程师手写代码,难度稍微大一些

saga

长事务模式,适合在一个事务开启到提交耗费时间很长的场景,

长事务:就是事务从开启到提交,时间耗费特别长的,一般长事务都特别耗费性能,并发能力非常低

XA

XA 模式其实就是AT模式的升级,更加的可靠,但是性能有所减低,使用起来也是很简单,只需要一条

注解

27.什么是zookeeper?

分布式应用程序协调服务,集群管理者

28.zookeeper作用

1.注册中心

2.配置中心

3.集群管理

4.分布式协调服务,选举master(主节点)

5.分布式锁

6.队列(性能低下),因为zk存储是使用文件存储

29.zk的存储结构

znode就是一个节点,znode可以存储数据,还可以存储子节点,

相当于一个文件夹,这文件夹可以存数据,还可以内部存储子文件夹,

节点类型,

永久节点,不删除一直存在,

临时节点,客户端连接时存在,断开后节点自动删除

有序节点,节点可以是有顺序的

30.为什么要有临时节点,有序节点

临时节点,

如果把zk中的节点当成一个锁(标记),是有某一个客户端创建,如果存在,客户端持有锁,假如客户端挂了,节点会自动删除,可以利用此特性防止死锁,

有序节点,

可以作为队列使用保证消息的顺序性

31.zk的集群模式

至少2N+1台机器,机器数量是奇数,如果机器数量可用的数量个数少于总数的一半,则整个集群不能使用,无法提供服务,因为无法发起选举机制

32.zk读写数据的流程

客户端读取数据可以在任意节点读取,

客户端写入数据:

1.客户端写入数据,

2.若是在从节点写入数据,从节点将客户写入的数据提交到主节点

3.主节点会自己先写入数据,然后命令所有的从节点写入数据

4.主节点,等待所有的从节点写入数据后,再返回给客户端,

33.为什么zk写入数据的流程是从主节点发起的

zk强调的是强一致性,任何时候任何节点读取到的数据都是一致的,

当然强一致性的存在,会损失一定的可用性

34.集群中节点的状态/角色

leader,领导者,也就是master主节点,

follower,跟随者,也就是从节点slave,

observer,观察者,特殊的从节点,不参与主节点选举,只提供读操作,

looking,是一个临时状态,在集群选举master过程中,所有的follower节点都会去竞选master,此时会将自己的状态改为looking,

集群中必须有主节点,否则无法正常工作,在没有主节点时,会根据投票机制,选举主节点

35.zk集群的选举机制

投票,谁的票多,谁就是主节点

36.什么情况下需要选举

1.主节点挂了,

2.集群启动时,选举主节点

3.集群中的从节点数量不足以通过半数校验,主节点会自己挂掉,选举新的主节点

4.加入新的从节点

37.集群初始化时的选举机制

每个节点自己携带有唯一的myid,

1.启动第一台机器节点1,发起选举,自己给自己投票,票数不过半,选举失败

2.启动第二台机器节点2,发起选举,

节点1和节点2都会给自己投票,票数一致,

比较节点1和节点2的id,谁的id大,id小的票数投给id大的,

节点2得到2票,票数超过一半,选举为主节点

3.启动第三台机器节点3,此时已经有主节点,不需要选举

38.集群运行时主节点挂掉了,如何选举新的节点

每个节点有自己的myid,和zxid,

zxid是事务id,事务id越大,代表数据越大,代表当前节点存储的数据越新

1.每个节点会给自己投一票,

2.票数一致,每个节点会将自己的myid和zxid发送给其它节点

3.每个节点会将票投给zxid最大的那个节点

39.zk监听机制

客户端监听zk节点的数据,如果节点的数据发生变化,客户端可以及时感知到

40.如何实现分布式锁

1.使用redis实现分布式锁,

在获取锁时使用 setnx 设置key,成功就是获取锁,没有成功,其他线程持有锁,
释放锁的时候,删除key,

2.使用zk实现分布式锁,

-----1.zk实现分布式锁,用的就是临时有序节点,

------2.客户在指定节点下,创建临时有序节点,获取了锁资源,

-------3.若自己不是最小的节点,监听比自己小一号节点,如果小一号的节点被删除了,当前节点再次判断自己是不是最小的节点,拿到了资源

3.zk本身的监控功能,实现分布式锁,非常繁琐,

使用第三方封装的锁,InterProcessMutex 提供互斥锁 来自 curator 框架,

41…zk vs redis 分布式锁?

首选redis,因为 redis 基于内存 并发量很高,不易成为性能瓶颈,zk 的存储基于文件(磁盘),并发写的能力很差,另外zk 创建节点是 不仅master要写入,slave 也要 写入,从而更加耗时,所以zk 只适合并发量很低的场合。

42.抢购商品 iPhone12 mate50 vivox60,分布式应用抢购

试问这三种产品 用同一个分布式锁么?

在抢购是每一种商品 用同一个锁,所有商品用同一个,性能会非常差

十七:消息队列框架

1.什么是消息队列?

消息队列,其实就是存储数据的一个数据结构(List 结构),并且能够保证数据的顺序性

2.消息队列的作用?

解耦,削峰,异步,

解耦,

就是将2个应用不是互相之间强依赖关系,一个挂了,两外一个依然可以使用,

削锋,

就是可以将高并发的网络请求 缓存到消息队中,慢慢的执行消息对对应的业务,

异步,

用户向服务发起请求,我们不会直接告诉用户结果,而是异步处理业务逻辑,稍后通过 通知的形式告诉用户

3.消息队列框架

常用消息队列框架

ActiveMQ,RocketMQ,Kafka,RabbitMQ。

RabbitMQ :特点 简单易用,支持多种语言,保证消息不丢失 可以配合作为分布式事务

Kafka: 特点是吞吐量非常大,适合大数据项目使用 支持多语言

RocketMQ:阿里出品,效率也很好,主要在spingcloud alibaba套件中使用,可以配合作为分布式事务

ActiveMQ:支持java语言 很少用

4.rabbitMq概念

publisher (生产者) :负责生产消息,并且将消息 放到交换机

Exchange - 交换机:交互机 主要用来接收生产者 发送的消息 并且将消息发送给 路由

Routes - 路由:将接收到的消息 根据路由规则 ,发送到不同的消息队列(真正存储数据的地方)

Queue - 队列:就是存放消息的位置(存储在磁盘中)

Consumer - 消费者:负责 将队列中的消息读取出来

channel-通道

5.RabbitMQ的通讯方式

–1.最简单模式(P2P消息)

一个生产者,一个队列,一个消费者,

–2.多个消费者共享队列模式(Work消息)

一个生产者,一个队列,多个消费者,

多个消费者获得数据的方式,是随机的抢占式的,而且一个数据只能获得一次

–3.发布订阅模式(Pub/Sub消息)

一个生产者, 多个队列,多个消费者,

生产者发布的数据,多个消费者通过多个队列都可获得,

–4.路由模式

一个生产者,多个队列,多个消费者,不同路由规则,

交换机根据路由规则,将消息发送到不同队列中,作用就是将消息分流

–5.topic主题模式

跟路由模式几乎一样,实现方式都一样

一个生产者,多个队列,多个消费者,路由规则不同的消息类型,跟模糊查询差不多,

交换机根据路由规则,将消息发送到不同队列中,作用就是将消息分流

6.rabbitMq的高可靠性

1.消费者手动ack,保证该消息的接收和业务处理

2.confirm确认机制,只有生产者收到交换机回馈的confirm,才能表明当前消息到达交换机

3.return机制,如果消息到达队列,没有任何响应,表明消息成功到达,

​ 如果消息没有到达队列,则该消息会通过return接口进行回调,告诉开发者,消息没有到达队列

7.rabbitMq的消息不重复问题

在消息发送到消费,消费者消费,执行对应的业务,但是,因为某些原因,消费者没有ack 成功,此时造成消息二次投递,发生重复消费,

解决方法,

1.为消息配置唯一的ID标识,

2.在消费者接收时,使用redis,setnx设置唯一标识,

十八:架构演进

1.各种环境

开发环境,程序员开发调试的环境

生产环境,就是线上环境,用户使用的服务运行的环境

测试环境,和开发环境类似,用于测试

2.web 1.0& web2.0

单体架构,用户少,内容少 对高可靠,高并发的性能要求都很低

单体集群架构,一定程度上可以解决用户高并发,高可用问题,存在高耦合,低内聚

1.路径分发问题

2.共享session问题,

使用nginx ip_hash 解决, 使用redis 共享session

3.多个服务器共享 mybatis 二级缓存问题

3.垂直架构

nginx先去我们的各个模块寻找,

把一个项目,按照各个功能分为多个模块,多个模块单独负责一个功能,大大提高软件维护性,体现为高内聚,低耦合,但是会带来一个问题?各个模块之间如何通信?

–1.模块之间通讯

–1.同步通讯,

模块之间通过http 请求 发送请求数据,发起一个请求等着另外一个模块回复

实现:使用springcloud(底层http请求) 使用dubbo(rpc框架底层是 scoket 长连接(tcp)实现

相当于打电话

–2.异步通讯,

模块发出一个消息,就不用关心了,可以去干其他事情了,另外一个模块接收到消息,按照对应的业务处理就可以了

实现:使用消息队列实现(rabbitmq, rockermq,kafka ,redis 中的 list )

相当于 模块件发送短息

–2.服务之间通讯地址的维护

使用注册中心(Nacos)解决 各个服务模块之间如何快速的发现对应服务的ip 和端口,并且如果某一服务下线,发起调用的模块可以立即感知到,不会再次向 下线的服务ip 发起调用

–3.模块之间 请求的负载均衡

调用一个模块,如果该模块有多台机器提供服务,那么发起请求时就需要配置不同的负载均衡算法发起请求

负载均衡实现

Ribbon:解决的是springcloud 模块间请求的负载均衡

Feign:封装了 ribbon,更加简便 解决的是springcloud 模块间请求的负载均衡

–4.服务降级/熔断

作用:避免 某一模块依赖其他模块,如果依赖的模块挂了,引起当前模块也出现问题

避免服务之间连锁雪崩的情况出现

–5.海量的数据

海量数据的存储

mysql 数据表 最大是千万级别 ,如果数据量是上亿,必须使用mycate/sharding 进行分库分表

海量数据的查询/检索

可以使用es 搜索引擎解决

4.微服务架构

–1.分布式架构

可以将一个应用拆分多个模块应用开发部署,还可以将一个数据库分为多个

mysql 可以分库分表 ,redis 去中心化,多台tomcat可以通过nginx 负载均衡

–2.微服务架构

微服务架构:微小的服务 微服务架构就是将一个应用 按照功能模块划分为多个独立应用,

每个应用可以单独的部署多台,这些应用可以通过http/tcp 互相调用,那么这种架构可以成为微服务架构

–3.模块过多,使用docker 容器化部署

1.现在有很多tomcat 部署 不同的服务,服务器很多,如果人员介入很麻烦

2.各个服务的升级

3.服务中的tomcat 实例可以动态的扩容 和 缩减

使用 dockerimage(tomcat + ssm) +dokcker + swarm/k8s(可以动态增加某一容器的数量) + 云主机(阿里云)

–4.分布式事务

生成订单

1.购物车模块

2.订单模块

3.库存模块

4.支付模块

在单应用中,可以让所有的模块共享一个sqlsession ,并且开启事务,来保证一致性

在微服务应用中,不可让所有的模块共享一个sql session ,使用单机开启事务 无法保证整体一致性

如何解决?

可以使用分布式事务解决 seata 框架解决

–5.分布式锁

解决多个应用之间访问同一数据,保证线程安全(数据的一致性)

解决方案:

1使用 redis setnx 实现

2.使用zookeeper 临时有序节点实现

十九:数据查询问题

1.如何解决海量搜索问题

常用搜索引擎 有 es ,Solr,

es:最为常用,Solr逐步被边缘化(性能更为强大,比较难用,文档没有es 丰富)

2.搜索引擎作用

1.作为全文检索,搜索使用

2.作为数据库使用,存储海量数据,

3.查询结果高亮显示,

4.作为日志搜索,监控工具

3.ES

Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析(类似mysql groupby 分组聚合)引擎,能够解决不断涌现出的各种用例。 作为 Elastic Stack 的核心,它集中存储您的数据,帮助您发现意料之中以及意料之外的情况。

4.Kibana

使用Es 的可视化工具,可以通过网页 ,查看 es,使用es,管理es

5.Es 简介

Es 基于 Lucene 的一个 搜索引擎,使用java开发,具有分布式横向拓展能力。

6.倒排索引(重点******)

索引:

英文词典,首页是不是都可以看到目录,目录中有所有的单词已经,单词所在的页面,

目录( 单词,页码)便于我们快速的查找。

倒排索引作用:

1.快速的查找对应的文章

2.通过倒排索引 记录词在文章中出现的 频次 和 位置,能够够好的衡量 当前单词对于文章的重要程度()

7.es结构

索引:其实就是一个存储数据的位置(类似数据库)

分片:一个索引 可以 分为多个分片 类似redis中的slot 默认有5个分片

备份:在es 的集群中,每一个索引都有多个分片,每一个分片在其他机器上 都已一个副本分片

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值