200개의 Java 면접 질문을 정리하고 마스터했는데도 여전히 면접관이 두렵습니까?

CSDN 주제 챌린지 2단계
참여 주제: 연구 노트

목차

객체 지향

JDK JRE JVM

스레드, 동시성

springmvc, springBoot

내 신발

MySQL

가장 왼쪽 접두사 원칙은 무엇입니까? 가장 왼쪽 일치 원리는 무엇입니까

노동 조합

레디스

Redis 클러스터 체계

분산/마이크로서비스

Kafka는 메시지 순서, 반복 전송, 반복 사용 및 메시지 손실을 어떻게 처리합니까?

끝 (투표)


객체 지향

객체지향이란?

프로세스 지향과 비교하여 문제를 다루는 두 가지 다른 각도가 있습니다.

프로세스 지향은 사물의 각 단계와 순서에 더 많은 관심을 기울이고, 객체 지향은 어떤 참여자(객체)가 무엇을 가지고 있고 무엇을 해야 하는지에 더 많은 관심을 기울입니다.

예: 세탁기

프로세스 지향은 작업을 일련의 단계(기능)로 분해합니다. 1. 세탁기 켜기 -----> 2. 옷 넣기 -----> 3. 세제 넣기 ---- -> 4. 세척- ---->5. 건조

객체 지향은 사람과 세탁기의 두 개체를 분리합니다. 사람: 세탁기를 열고 옷을 넣고 세탁기에 세제를 넣습니다. 세탁 및 건조

위의 예에서 볼 수 있듯이 프로세스 지향은 보다 직접적이고 효율적이며 객체 지향은 재사용, 확장 및 유지 관리가 더 쉽습니다.

객체 지향

캡슐화: 캡슐화의 의미는 외부에서 사용할 수 있는 모든 멤버 함수와 데이터 항목을 명확하게 식별하는 것입니다.

내부 세부 정보는 외부 호출에 투명하며 외부 호출은 수정하거나 내부 구현에 대해 걱정할 필요가 없습니다.

  1. 속성의 할당 또는 획득 논리는 javabean 자체에 의해서만 결정될 수 있기 때문에 javabean의 속성은 비공개이며 getset에 대한 외부 액세스를 제공합니다. 외부에서 임의로 수정할 수 없습니다.

  2. 옴 프레임워크

데이터베이스를 운영하기 위해 우리는 링크가 어떻게 설정되고 SQL이 어떻게 실행되는지에 대해 신경 쓸 필요가 없습니다. 하위 클래스의 변경 및/또는 확장 메소드 또는 속성은 직접 재정의하지 않고 상위 클래스를 직접 사용합니다. 자신의 개인화를 확장하십시오.

다형성(Polymorphism): 서로 다른 개체 클래스를 기반으로 동일한 메서드에 대한 외부 호출은 실제로 실행되는 서로 다른 논리를 가집니다.

상속, 메서드 재작성, 부모 클래스 참조는 하위 클래스 객체를 가리킴

하위 클래스별 함수를 호출할 수 없습니다.

JDK JRE JVM

JDK:

Java 개발 키트 Java 개발 도구

JRE:

Java Runtime Environment java运行时环境

JVM:

java Virtual Machine java 虚拟机

==和equals比较

==对比的是栈中的值,基本数据类型是变量值,引用类型是堆中内存对象的地址 equals:object中默认也是采用==比较,通常会重写

Object

String

上述代码可以看出,String类中被复写的equals()方法其实是比较两个字符串的内容。

hashCode与equals

hashCode介绍:

hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。hashCode() 定义在JDK的Object.java中,Java中的任何类都包含有 hashCode() 函数。

散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)为什么要有hashCode:

以“HashSet如何检查重复”为例子来说明为什么要有hashCode:对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,看该位置是否有值,如果没有、HashSet会假设对象没有重复出现。但是如果发现有值,这时会调用equals()方法来检查两个对象是否真的相同。如果两者相同,HashSet就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。这样就大大减少了equals的次数,相应就大大提高了执行速度。

如果两个对象相等,则hashcode一定也是相同的两个对象相等,对两个对象分别调用equals方法都返回true 两个对象有相同的hashcode值,它们也不一定是相等的因此,equals方法被覆盖过,则hashCode方法也必须被覆盖

hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

final

终的

修饰类:表示类不可被继承修饰方法:表示方法不可被子类覆盖,但是可以重载

修饰变量:表示变量一旦被赋值就不可以更改它的值。

  1. 修饰成员变量 如果final修饰的是类变量,只能在静态初始化块中指定初始值或者声明该类变量时指定初始值。 如果final修饰的是成员变量,可以在非静态初始化块、声明该变量或者构造器中执行初始值。

  2. 修饰局部变量 系统不会为局部变量进行初始化,局部变量必须由程序员显示初始化。因此使用final修饰局部变量时,即可以在定义时指定默认值(后面的代码不能对变量再赋值),也可以不指定默认值,而在后面的代码中对final变量赋初值(仅一次)

  3. 修饰基本类型数据和引用类型数据

如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。但是引用的值是可变的。

为什么局部内部类和匿名内部类只能访问局部final变量?编译之后会生成两个class文件,Test.class Test1.class

首先需要知道的一点是: 内部类和外部类是处于同一个级别的,内部类不会因为定义在方法中就会随着方法的执行完毕就被销毁。

这里就会产生问题:当外部类的方法结束时,局部变量就会被销毁了,但是内部类对象可能还存在(只有没有人再引用它时,才会死亡)。这里就出现了一个矛盾:内部类对象访问了一个不存在的变量。为了解决这个问题,就将局部变量复制了一份作为内部类的成员变量,这样当局部变量死亡后,内部类仍可以访问它,实际访问的是局部变量的"copy"。这样就好像延长了局部变量的生命周期

将局部变量复制为内部类的成员变量时,必须保证这两个变量是一样的,也就是如果我们在内部类中修改了成员变量,方法中的局部变量也得跟着改变,怎么解决问题呢?

就将局部变量设置为final,对它初始化后,我就不让你再去修改这个变量,就保证了内部类的成员变量和方法的局部变量的一致性。这实际上也是一种妥协。使得局部变量与内部类内建立的拷贝保持一致。

String、StringBuffer、StringBuilder

String是final修饰的,不可变,每次操作都会产生新的String对象

StringBuffer和StringBuilder都是在原对象上操作

StringBuffer是线程安全的,StringBuilder线程不安全的

StringBuffer方法都是synchronized修饰的

性能:StringBuilder > StringBuffer > String

场景:经常需要改变字符串内容时使用后面两个

优先使用StringBuilder,多线程使用共享变量时使用StringBuffer

重载和重写的区别

重载: 发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同,发生在编译时。

重写: 发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为private则子类就不能重写该方法。

接口和抽象类的区别

抽象类可以存在普通成员函数,而接口中只能存在public abstract 方法。

抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的。

抽象类只能继承一个,接口可以实现多个。

接口的设计目的,是对类的行为进行约束(更准确的说是一种“有”约束,因为接口不能规定类不可以有什么行为),也就是提供一种机制,可以强制要求不同的类具有相同的行为。它只约束了行为的有无,但不对如何实现行为进行限制。

추상 클래스의 설계 목적은 코드 재사용입니다. 서로 다른 클래스가 일부 동일한 동작을 갖고(동작 집합 A로 표시됨) 일부 동작이 동일한 방식으로 구현되는 경우(A의 적절하지 않은 하위 집합, B로 표시됨) 이러한 클래스는 추상에서 파생될 수 있습니다. 수업. B는 이 추상 클래스에서 구현되며 모든 하위 클래스는 코드 재사용의 목적을 달성하는 B를 구현하지 못하도록 합니다. A에서 B를 뺀 부분은 구현하기 위해 각 하위 클래스에 남겨집니다. 여기에서 AB가 구현되지 않았기 때문에 추상 클래스를 인스턴스화할 수 없습니다(그렇지 않으면 AB를 호출할 때 실행할 수 없습니다).

추상 클래스는 클래스 본질의 추상화이며, is a의 관계를 표현합니다(예: BMW는 자동차입니다). 추상 클래스는 하위 클래스의 일반적인 특성을 포함하고 구현하며, 하위 클래스의 차별화된 특성을 추상화하여 구현을 위해 하위 클래스에 전달합니다.

인터페이스는 a와 같은 관계를 표현하는 동작의 추상화입니다. 예: Bird like a Aircraft(비행기처럼 날 수 있음), 하지만 본질적으로 새입니다. 인터페이스의 핵심은 행위(behavior), 즉 구현 클래스가 무엇을 할 수 있는지를 정의하는 것인데, 구현 클래스의 주체가 누구이고 어떻게 구현되는지 인터페이스는 신경쓰지 않는다.

사용 시나리오: 사물의 본질에 집중할 때는 추상 클래스를 사용하고 작업에 집중할 때는 인터페이스를 사용합니다.

추상 클래스의 기능은 인터페이스의 기능을 훨씬 능가하지만 추상 클래스를 정의하는 비용은 높습니다. 고급 언어(및 실제 설계)로 인해 각 클래스는 하나의 클래스만 상속할 수 있습니다. 이 클래스에서는 모든 하위 클래스의 모든 공통성을 상속하거나 작성해야 합니다. 인터페이스는 기능면에서 훨씬 약하지만 동작에 대한 설명일 뿐입니다. 그리고 동시에 하나의 클래스에 여러 인터페이스를 구현할 수 있습니다. 설계 단계에서 난이도가 감소합니다.

리스트와 세트의 차이점

목록: 순서대로 개체를 입력한 순서대로 저장, 반복 가능, 여러 Null 요소 개체 허용, Iterator를 사용하여 모든 요소를 ​​제거하고 하나씩 탐색할 수 있습니다. get(int index)을 사용하여 지정된 항목을 가져올 수도 있습니다. 첨자 요소

설정: 순서가 없고 반복 불가능하며 최대 하나의 Null 요소 객체만 허용 요소를 가져올 때 Iterator 인터페이스만 사용하여 모든 요소를 ​​얻을 수 있으며 각 요소는 하나씩 순회합니다.

ArrayList와 LinkedList의 차이점

ArrayList: 동적 배열 기반, 지속적인 메모리 저장, 첨자 액세스(랜덤 액세스)에 적합, 확장 메커니즘: 배열의 길이가 고정되어 있기 때문에 길이를 초과하는 데이터를 저장할 때 새로운 배열을 생성해야 합니다. 기존 배열의 데이터가 마지막에 있지 않으면 새 배열로 복사 데이터 삽입에는 요소의 이동도 포함됩니다(나중에 사본을 복사하고 새 요소 삽입) 꼬리 삽입을 사용하고 초기 용량을 지정하면 성능이 크게 향상될 수 있습니다. 능가 linkedList (많은 수의 노드 객체 생성 필요)

LinkedList: 연결 목록 기반, 분산된 메모리에 저장 가능, 데이터 삽입 및 삭제 작업에 적합, 쿼리에 적합하지 않음: 하나씩 탐색해야 함

LinkedList를 순회하려면 for 루프 대신 반복자를 사용해야 합니다. for 루프 본문에서 get(i)를 통해 요소를 가져올 때마다 목록을 다시 순회해야 하므로 많은 성능이 소모되기 때문입니다.

또한 indexOf를 사용하여 요소 인덱스를 반환하려고 시도하지 말고 순회하는 데 사용하십시오. indexlOf를 사용하여 목록을 순회하십시오. 결과가 비어 있으면 전체 목록을 순회합니다.

HashMap과 HashTable의 차이점은 무엇입니까? 기본 구현은 무엇입니까?

차이점:

  1. HashMap 메소드는 동기화에 의해 수정되지 않고 스레드는 안전하지 않으며 HashTable은 스레드로부터 안전합니다.

  2. HashMap은 키와 값이 null일 수 있지만 HashTable은 그렇지 않습니다.

2. 기본 구현: 배열 + 연결 목록 구현

jdk8부터는 연결 리스트의 높이가 8에 도달하고 배열의 길이가 64를 초과합니다. 연결 리스트는 레드-블랙 트리로 변하고 요소는 내부 클래스 노드 노드로 존재합니다.

키의 해시 값을 계산하고 두 번째로 해시한 다음 배열 첨자에 해당하는 배열 길이의 계수를 취합니다.해시 충돌이 없는 경우(첨자 위치에 요소가 없음) 직접 Node를 생성하여 저장합니다. 배열 내에서 해쉬 충돌이 있을 경우 먼저 Equal 비교, 동일 요소이면 교체, 다르면 연결 리스트의 높이를 판단하여 연결 리스트에 삽입, 링크

테이블의 높이가 8에 도달하고 배열의 길이가 64에 도달하면 red-black 트리로 변환되고 길이가 6보다 작으면 red-black 트리는 연결 목록으로 다시 변환됩니다. 키는 null이고 첨자가 0인 배열이 확장됩니다.

ConcurrentHashMap의 원리, jdk7과 jdk8 버전의 차이

jdk7: 데이터 구조: ReentrantLock+Segment+HashEntry, 세그먼트에는 각각 HashEntry 배열이 포함됩니다.

HashEntry는 또 다른 연결 목록 구조입니다.

元素查询:二次hash,第一次Hash定位到Segment,第二次Hash定位到元素所在的链表的头部

锁:Segment分段锁 Segment继承了ReentrantLock,锁定操作的Segment,其他的Segment不受影响,并发度为segment个数,可以通过构造函数指定,数组扩容不会影响其他的segment get方法无需加锁,volatile保证 jdk8:

数据结构:synchronized+CAS+Node+红黑树,Node的val和next都用volatile修饰,保证可见性查找,替换,赋值操作都使用CAS

锁:锁链表的head节点,不影响其他元素的读写,锁粒度更细,效率更高,扩容时,阻塞所有的读写操作、并发扩容

读操作无锁:

Node的val和next使用volatile修饰,读写线程对该变量互相可见 数组用volatile修饰,保证扩容时被读线程感知

什么是字节码?采用字节码的好处是什么?

java中的编译器和解释器:

Java中引入了虚拟机的概念,即在机器和编译程序之间加入了一层抽象的虚拟的机器。这台虚拟的机器在任何平台上都提供给编译程序一个的共同的接口。

编译程序只需要面向虚拟机,生成虚拟机能够理解的代码,然后由解释器来将虚拟机代码转换为特定系统的机器码执行。在Java中,这种供虚拟机理解的代码叫做 字节码(即扩展名为 .class的文件),它不面向任何特定的处理器,只面向虚拟机。

每一种平台的解释器是不同的,但是实现的虚拟机是相同的。Java源程序经过编译器编译后变成字节码,字节码由虚拟机解释执行,虚拟机将每一条要执行的字节码送给解释器,解释器将其翻译成特定机

器上的机器码,然后在特定的机器上运行。这也就是解释了Java的编译与解释并存的特点。

Java源代码---->编译器---->jvm可执行的Java字节码(即虚拟指令)---->jvm---->jvm中解释器----->机器可执行的二进制机器码---->程序运行。

采用字节码的好处:

Java 언어는 해석 언어의 이식성을 유지하면서 바이트 코드를 통해 기존 해석 언어의 낮은 실행 효율성 문제를 어느 정도 해결합니다. 따라서 Java 프로그램은 실행 시 더 효율적이며 바이트코드가 특정 시스템에 고유하지 않기 때문에 Java 프로그램은 재컴파일 없이 여러 다른 컴퓨터에서 실행될 수 있습니다.

Java의 예외 계층

Java의 모든 예외는 최상위 상위 클래스인 Throwable에서 시작됩니다.

Throwable 아래에는 두 개의 하위 클래스 Exception 및 Error가 있습니다.

오류는 프로그램이 처리할 수 없는 오류로, 이 오류가 발생하면 프로그램이 강제로 중지됩니다.

예외는 프로그램을 중지시키지 않으며 RunTimeException 런타임 예외와 CheckedException 검사 예외의 두 부분으로 나뉩니다.

RunTimeException은 프로그램 실행 중에 종종 발생하며, 이로 인해 프로그램의 현재 스레드 실행이 실패합니다. CheckedException은 프로그램 컴파일 중에 자주 발생하며 이로 인해 프로그램이 컴파일되지 않습니다.

자바 클래스 로더

JDK에는 부트스트랩 ClassLoader, ExtClassLoader, AppClassLoader의 세 가지 클래스 로더가 함께 제공됩니다. BootStrapClassLoader는 기본적으로 %JAVA_HOME%lib에서 jar 패키지 및 클래스 파일을 로드하는 ExtClassLoader의 상위 클래스 로더입니다.

ExtClassLoader는 %JAVA_HOME%/lib/ext 폴더에서 jar 패키지 및 클래스를 로드하는 AppClassLoader의 상위 클래스 로더입니다.

AppClassLoader는 사용자 정의 클래스 로더의 상위 클래스이며 클래스 경로 아래에서 클래스 파일 로드를 담당합니다. 시스템 클래스 로더, 스레드 컨텍스트 로더

커스텀 클래스 로더를 구현하기 위해 ClassLoader 상속

상위 위임 모델

상위 위임 모델의 이점:

주된 이유는 사용자가 직접 작성한 클래스에 의해 String과 같은 일부 핵심 Java 클래스가 동적으로 대체되는 것을 방지하기 위한 보안 때문입니다.

동시에 JVM에서 서로 다른 클래스가 클래스 이름을 기준으로 구분될 뿐만 아니라 서로 다른 ClassLoader에 의해 로드된 동일한 클래스 파일이 두 개의 서로 다른 클래스이기 때문에 클래스의 반복 로드를 방지합니다.

GC는 개체가 재활용될 수 있는지 어떻게 판단합니까?

참조 카운팅 방법: 각 객체는 참조 카운팅 속성을 가지며, 참조가 추가되면 카운트가 1 증가하고, 참조가 해제되면 카운트가 1 감소하며, 카운트가 0일 때 재활용할 수 있습니다. : GC Roots에서 시작하여 아래쪽으로 검색합니다. 검색이 따르는 경로를 참조 체인이라고 합니다. 객체가 GC로 갈 때

Roots가 참조 체인으로 연결되어 있지 않으면 개체를 사용할 수 없음을 증명하고 가상 머신은 이를 재활용 가능한 개체로 판단합니다.

참조 카운팅 방법에서 A는 B를 참조하고 B는 A를 참조하는 것처럼 보일 수 있습니다. 이때 더 이상 사용하지 않더라도 상호 참조 카운터 = 1이므로 절대 재활용할 수 없습니다.

GC Roots의 객체는 다음과 같습니다.

가상 머신 스택에서 참조하는 객체의 메서드 영역에서 클래스 정적 속성이 참조하는 객체(스택 프레임의 로컬 변수 테이블)

메서드 영역의 상수가 참조하는 개체

로컬 메서드 스택의 JNI(즉, 일반적으로 네이티브 메서드)가 참조하는 객체 도달 가능성 알고리즘의 도달할 수 없는 객체는 즉시 죽지 않으며 객체는 스스로를 저장할 기회가 있습니다. 시스템에서 죽은 것으로 선언된 개체는 적어도 두 가지 마킹 프로세스를 거쳐야 합니다. 첫 번째는 도달 가능성 분석을 통해 GC Roots에 연결된 참조 체인이 없음을 확인하고 두 번째는 필요한지 여부를 판단하는 것입니다. 가상 머신에 의해 자동으로 설정된 종료자 대기열 finalize() 메서드를 실행합니다.

개체가 (GC Roots) 도달할 수 없게 되면 GC는 개체가 finalize 메서드를 처리했는지 여부를 판단하고 그렇지 않은 경우 직접 재활용합니다. 그렇지 않고 객체가 finalize 메서드를 실행하지 않은 경우 F-Queue 대기열에 넣고 낮은 우선 순위의 스레드가 대기열에 있는 객체의 finalize 메서드를 실행합니다. finalize 메서드를 실행한 후 GC는 개체에 다시 도달할 수 있는지 여부를 판단하여 도달할 수 없으면 재활용하고 그렇지 않으면 개체를 "부활"합니다.

각 개체는 finalize() 메서드를 한 번만 트리거할 수 있습니다.

finalize() 메서드는 실행 비용이 많이 들고 불확실성이 크기 때문에 각 개체의 호출 순서를 보장할 수 없으므로 모든 사람이 사용하는 것은 권장하지 않으며 잊어버리는 것이 좋습니다.

스레드, 동시성

스레드 수명 주기? 스레드에는 여러 상태가 있습니다.

1. 스레드는 일반적으로 생성됨, 준비됨, 실행 중, 차단됨 및 종료됨의 5가지 상태를 가집니다.

2. 차단 상황은 세 가지 유형으로 나뉩니다.

(1) 차단 대기: 실행 중인 스레드가 wait 메서드를 실행하고 스레드가 점유한 모든 리소스를 해제하고 JVM이 스레드를 "대기 풀"에 넣습니다. 이 상태에 들어간 후에는 자동으로 깨울 수 없으며 다른 스레드에 의존하여 notify 또는 notifyAll 메소드를 호출해야 깨울 수 있습니다. 대기는 객체 클래스의 메소드입니다.

(2) 동기 차단: 실행 중인 스레드가 객체의 동기화 잠금을 획득할 때 동기화 잠금이 다른 스레드에 의해 점유된 경우 JVM은 스레드를 "잠금 풀"에 넣습니다.

(3) 기타 차단: 실행 중인 스레드가 절전 또는 조인 메서드를 실행하거나 I/O 요청을 보내면 JVM이 스레드를 차단 상태로 만듭니다.

상태. 휴면 상태가 시간 초과되면 조인은 스레드가 종료될 때까지 기다리거나 시간이 초과되거나 I/O 처리가 완료되면 스레드가 다시 준비 상태로 들어갑니다.

sleep은 Thread 클래스의 메서드입니다.

1. 새 상태(New): 스레드 개체가 새로 생성됩니다.

2. 준비 상태(Runnable): 스레드 객체가 생성된 후 다른 스레드가 해당 객체의 시작 메서드를 호출합니다. 이 상태의 스레드는 실행 가능한 스레드 풀에 위치하여 실행 가능 상태가 되고 CPU 사용 권한을 얻기 위해 대기합니다.

3. 실행 상태(Running): 준비 상태의 스레드가 CPU를 획득하고 프로그램 코드를 실행합니다.

4. 차단된 상태(Blocked): 차단된 상태는 스레드가 어떤 이유로 CPU 사용 권한을 포기하고 일시적으로 실행을 중지하는 것을 의미합니다. 스레드가 준비 상태에 들어갈 때까지 실행 상태로 전환할 기회가 있습니다.

5. 데드 상태(Dead): 예외로 인해 스레드가 실행을 종료하거나 run 메서드를 종료하고 스레드가 수명 주기를 종료합니다.

sleep(), wait(), join(), yield()의 차이점

1. 수영장 잠금

동기화 잠금을 위해 경쟁해야 하는 모든 스레드는 잠금 풀에 배치됩니다. 예를 들어 현재 개체의 잠금이 스레드 중 하나에 의해 획득된 경우 다른 스레드는 이 잠금 풀에서 대기해야 합니다. 이전 스레드 이후 동기화 잠금 해제, 잠금 풀의 스레드 동기화 잠금을 위해 경쟁하기 위해 스레드가 동기화 잠금을 얻으면 준비 큐에 들어가 CPU 리소스 할당을 기다립니다.

2. 대기 풀

wait() 메서드를 호출하면 스레드는 대기 풀에 배치되고 풀에서 대기 중인 스레드는 동기화 잠금을 위해 경쟁하지 않습니다. notify() 또는 notifyAll()을 호출한 후에야 풀에서 대기 중인 스레드가 잠금을 위해 경쟁을 시작합니다. notify()는 대기 중인 풀에서 임의로 스레드를 선택하여 잠금 풀에 넣고, notifyAll()은 대기합니다. 풀의 모든 스레드에 대해 잠금 풀에 넣습니다.

  1. sleep은 Thread 클래스의 정적 네이티브 메서드이고 wait는 Object 클래스의 네이티브 메서드입니다.

  2. sleep 메서드는 잠금을 해제하지 않지만 wait는 잠금을 해제하고 대기 큐에 추가합니다. Sleep은 CPU의 실행 자격과 실행 권한을 해제하고 더 이상 이 스레드를 실행하지 않고 타이머가 만료되면 CPU 리소스를 검색하고 CPU 스케줄링에 참여하고 CPU 리소스를 얻은 후 계속 실행하는 것입니다. 스레드가 휴면 중에 잠금을 가지고 있으면 sleep은 잠금을 해제하지 않고 잠금을 고정 상태로 만듭니다. 즉, 이 잠금이 필요한 다른 스레드가 이 잠금을 획득할 수 없습니다. 즉, 프로그램을 실행할 수 없습니다. 휴면 중에 다른 스레드가 이 스레드의 인터럽트 메서드를 호출하면 이 스레드도 인터럽트 예외를 throw하고 반환하며 대기와 동일합니다.

  3. sleep 메서드는 synchronized에 의존하지 않지만 wait는 synchronized 키워드에 의존해야 합니다.

  4. sleep은 깨울 필요가 없지만(sleep 후 차단) wait는 시간을 지정하지 않고 다른 사람에 의해 중단되어야 합니다.

  5. sleep은 일반적으로 현재 스레드가 잠들거나 라운드 로빈 일시 중지 작업에 사용되는 반면 wait는 주로 여러 스레드 간의 통신에 사용됩니다.

  6. sleep은 CPU 실행 시간을 해제하고 컨텍스트 전환을 강제하지만 대기가 반드시 필요한 것은 아닙니다. 대기 후 잠금이 실행을 계속하기 위해 다시 경쟁할 기회가 여전히 있을 수 있습니다.

yield()가 실행된 후 스레드는 바로 준비 상태로 들어가고 즉시 CPU의 실행 권한을 해제하지만 여전히 CPU의 실행 자격을 유지하므로 CPU에 의한 다음 스레드 스케줄링이 허용할 가능성이 있습니다. 실행 권한을 얻고 실행을 계속하는 스레드

join()이 실행된 후 쓰레드는 블로킹 상태가 되는데, 예를 들어 쓰레드 B가 쓰레드 A의 join()을 호출하면 쓰레드 B는 쓰레드 A가 종료되거나 쓰레드가 중단될 때까지 블로킹 큐에 들어간다.

스레드 안전성의 이해

스레드 안전하지 않음, 메모리 안전해야 함, 힙은 공유 메모리, 모든 스레드에서 액세스 가능

여러 스레드가 개체에 액세스할 때 이 개체를 호출하는 동작이 추가 동기화 제어 또는 기타 조정 작업 없이 올바른 결과를 얻을 수 있는 경우 이 개체를 스레드로부터 안전하다고 합니다.

힙은 프로세스와 쓰레드가 공유하는 공간으로 글로벌 힙과 로컬 힙으로 나뉜다. 전역 힙은 모두 할당되지 않은 공간이고 로컬 힙은 사용자가 할당한 공간입니다. 힙은 운영 체제가 프로세스를 초기화할 때 할당되며, 실행 중인 프로세스 중에 시스템에 추가 힙을 요청할 수도 있지만 다 사용했을 때 운영 체제에 반환해야 합니다. 그렇지 않으면 메모리 누수가 발생합니다.

Java에서 힙은 Java 가상 머신이 관리하는 큰 메모리 조각으로, 모든 스레드가 공유하는 메모리 영역으로 가상 머신이 시작될 때 생성됩니다. 힙이 존재하는 메모리 영역의 유일한 목적은 객체 인스턴스를 저장하는 것이며 거의 모든 객체 인스턴스와 배열이 여기에 메모리를 할당합니다.

스택은 각 스레드에 고유하며 실행 상태 및 로컬 자동 변수를 저장합니다. 스레드가 시작되면 스택이 초기화되고 각 스레드의 스택은 서로 독립적이므로 스택은 스레드로부터 안전합니다. 운영 체제는 스레드를 전환할 때 스택을 자동으로 전환합니다. 고급 언어에서는 스택 공간을 명시적으로 할당하고 해제할 필요가 없습니다.

현재 주류 운영 체제는 모두 멀티태스킹, 즉 여러 프로세스가 동시에 실행됩니다. 안전을 보장하기 위해 각 프로세스는 자신에게 할당된 메모리 공간에만 액세스할 수 있으며 다른 프로세스에는 액세스할 수 없으며 이는 운영 체제에서 보장합니다.

각 프로세스의 메모리 공간에는 일반적으로 힙(메모리)이라고 하는 특별한 공통 영역이 있습니다. 프로세스 내의 모든 스레드는 문제의 잠재적인 원인인 이 영역에 액세스할 수 있습니다.

스레드와 실행 가능의 차이점

Thread와 Runnable의 본질은 상속 관계이며 비교 대상이 아닙니다. Runnable 또는 Thread를 사용하는 것과 상관없이 새로운 것입니다.

Thread를 누른 다음 run 메서드를 실행합니다. 사용법 측면에서 복잡한 스레드 작업 요구 사항이 있는 경우 스레드를 상속하도록 선택하고 단순히 작업을 실행하는 경우 Runnable을 구현합니다.

그 이유는: MyThread는 2개의 인스턴스를 생성하며 자연스럽게 두 번 판매될 것이며 이는 사용 오류입니다.

데몬 스레드의 이해

데몬 스레드: 데몬이 아닌 모든 스레드에 서비스를 제공하는 스레드로 모든 데몬 스레드는 전체 JVM에서 모든 비데몬 스레드의 유모입니다.

데몬 쓰레드는 전체 프로세스의 알 수 없는 작은 소년과 비슷하다; 그 삶과 죽음은 중요하지 않지만 실행하는 전체 프로세스에 달려 있으며, 다른 쓰레드가 종료되면 실행할 것이 없고 프로그램이 종료되며 거기서 이유 데몬 스레드가 아닙니다. 그냥 중단하십시오.

참고: 데몬 스레드의 종료는 자체적으로 제어할 수 없으므로 IO 및 File과 같은 중요한 작업 논리를 할당하지 마십시오.

데몬 스레드의 역할은 무엇입니까? 예를 들어, GC 가비지 수집 스레드: 이것은 고전적인 데몬 스레드입니다.프로그램에서 더 이상 실행 중인 스레드가 없으면 프로그램은 더 이상 가비지를 생성하지 않으며 가비지 수집기는 아무 작업도 수행하지 않으므로 가비지 수집이 스레드 JVM에 남아 있는 유일한 스레드일 때 가비지 수집 스레드는 자동으로 떠납니다. 시스템에서 회수 가능한 리소스의 실시간 모니터링 및 관리를 위해 항상 낮은 수준의 상태에서 실행됩니다.

응용 시나리오: (1) 다른 스레드에 대한 서비스 지원을 제공하기 위해, (2) 어떤 경우든 프로그램이 종료되면 이 스레드는 정상적으로 즉시 닫혀야 하며 데몬 스레드로 사용할 수 있습니다. 특정 작업을 수행하는 스레드는 올바르게 닫혀야 합니다. 그렇지 않으면 나쁜 결과가 발생할 수 있으며 이 스레드는 데몬 스레드가 될 수 없으며 사용자 스레드입니다. 일반적으로 이들은 중요한 트랜잭션(예: 데이터베이스 항목 또는 업데이트)이며 이러한 작업은 중단될 수 없습니다.

thread.setDaemon(true)은 thread.start() 전에 설정되어야 합니다. 그렇지 않으면

IllegalThreadStateException 예외. 실행 중인 일반 스레드를 데몬 스레드로 설정할 수 없습니다.

Daemon 스레드에서 생성된 새 스레드도 Daemon의 스레드입니다.

데몬 스레드는 읽기 및 쓰기 작업 또는 계산 논리와 같은 고유 리소스에 액세스하는 데 사용할 수 없습니다. 작업 도중에도 언제든지 중단될 수 있기 때문입니다.

ExecutorService와 같은 Java 고유의 ​​멀티스레딩 프레임워크는 데몬 스레드를 사용자 스레드로 변환하므로 백그라운드 스레드를 사용하려는 경우 Java의 스레드 풀을 사용할 수 없습니다.

ThreadLocal의 원리 및 사용 시나리오

각 Thread 개체에는 모든 ThreadLocal 개체와 해당 값을 이 스레드에 저장하는 ThreadLocalMap 유형의 멤버 변수 threadLocals가 포함되어 있습니다.

ThreadLocalMap은 Entry 객체로 구성됩니다.

Entry는 WeakReference<ThreadLocal<?>>에서 상속되며, Entry는 ThreadLocal 객체와 Object로 구성됩니다. Entry의 키는 ThreadLocal 객체이며 약한 참조임을 알 수 있습니다. 키에 대한 강력한 참조가 없으면 가비지 수집기에서 키를 재활용합니다.

set 메서드를 실행할 때 ThreadLocal은 먼저 현재 스레드 개체를 가져온 다음 현재 스레드의 ThreadLocalMap 개체를 가져옵니다. 그런 다음 현재 ThreadLocal 개체를 키로 사용하여 ThreadLocalMap 개체에 값을 저장합니다.

get 메서드의 실행 프로세스는 비슷합니다. ThreadLocal은 먼저 현재 스레드 개체를 가져온 다음 현재 스레드의 ThreadLocalMap 개체를 가져옵니다. 그런 다음 현재 ThreadLocal 개체를 키로 사용하여 해당 값을 가져옵니다. 각 스레드에는 자체 전용 ThreadLocalMap 컨테이너가 있으므로 이러한 컨테이너는 서로 독립적이며 서로 영향을 주지 않으므로 스레드 안전 문제가 없으므로 동기화 메커니즘을 사용하여 여러 스레드의 상호 배제를 보장할 필요가 없습니다. 컨테이너에 액세스합니다.

사용할 장면:

  1. 여러 레이어 간에 개체를 전송할 때 ThreadLocal을 사용하면 다중 전송을 방지하고 레이어 간의 제약 조건을 깨뜨릴 수 있습니다.

  2. 스레드 간 데이터 격리

  3. 트랜잭션 작업을 수행하고 스레드 트랜잭션 정보를 저장합니다.

  4. 데이터베이스 연결, 세션 세션 관리.

Spring 프레임워크는 트랜잭션 시작 시 현재 스레드에 Jdbc 연결을 바인딩하고 스레드에 바인딩된 연결을 사용하여 트랜잭션 프로세스 전체에서 데이터베이스 작업을 수행하여 트랜잭션의 격리를 실현합니다. ThreadLocal은 이러한 격리를 달성하기 위해 Spring 프레임워크에서 사용됩니다.

ThreadLocal 메모리 누수 원인 및 방지 방법

메모리 누수는 프로그램이 메모리를 신청한 후 요청된 메모리 공간을 해제할 수 없음을 의미합니다.메모리 누수의 피해는 무시할 수 있지만 메모리 누수 누적의 결과는 매우 심각합니다.아무리 많은 메모리를 사용하더라도 더 빨리 소모됩니다. 또는 나중에.

더 이상 사용되지 않는 개체나 변수가 차지하는 메모리는 회수할 수 없으며, 이는 메모리 누수입니다.

강력한 참조: 범용 참조(신규)를 사용하면 개체에 강력한 참조가 있으며 가비지 수집기에 의해 회수되지 않습니다. 메모리 공간이 부족할 때,

JVM(Java Virtual Machine)은 그러한 객체를 재활용하기보다는 프로그램을 비정상적으로 종료시키기 위해 OutOfMemoryError 오류를 발생시킵니다. 강한 참조와 개체 간의 연결을 취소하려는 경우 JVM이 적절한 시간에 개체를 재활용하도록 명시적으로 참조를 null에 할당할 수 있습니다.

약한 참조: JVM이 가비지 수집을 수행하면 메모리가 충분한지 여부에 관계없이 약한 참조와 연관된 개체가 재활용됩니다. Java에서는 java.lang.ref.WeakReference 클래스로 표시됩니다. 약한 참조는 캐시에서 사용할 수 있습니다.

ThreadLocal의 구현 원리, 각 스레드는 ThreadLocalMap을 유지하고, 키는 약한 참조를 사용하는 ThreadLocal 인스턴스이며, 값은 스레드 변수의 복사본입니다.

hreadLocalMap은 ThreadLocal의 약한 참조를 키로 사용합니다. ThreadLocal에 외부 강한 참조가 없으면 키(ThreadLocal)가 GC에 의해 재활용되어 ThreadLocalMap의 키가 null이 되지만 값은 여전히 강력한 참조, 오직 thead 쓰레드 종료 후 값의 강한 참조 체인이 끊어지지만 현재 스레드가 오랫동안 종료되지 않으면 값에 대한 강력한 참조 체인(빨간색 체인)이 항상 존재합니다. 키가 null인 이러한 항목 키는 강력한 참조를 사용합니다.

hreadLocalMap의 키가 ThreadLocal을 재활용하기 위한 강력한 참조인 경우 ThreadLocalMap은 여전히 ​​ThreadLocal에 대한 강력한 참조를 보유하고 있기 때문에 수동으로 삭제하지 않으면 ThreadLocal이 재활용되지 않아 Entry의 메모리 누수가 발생합니다.

키는 약한 참조를 사용합니다.

ThreadLocalMap의 키가 약한 참조를 위해 ThreadLocal을 재활용하면 ThreadLocalMap이 ThreadLocal의 약한 참조를 보유하고 있기 때문에 수동으로 삭제하지 않더라도 ThreadLocal이 재활용됩니다. 키가 null이면 다음에 ThreadLocalMap이 set(), get() 및 remove() 메서드를 호출할 때 값이 지워집니다.

따라서 ThreadLocal 메모리 누수의 근본 원인은 ThreadLocalMap의 수명 주기가 Thread만큼 길기 때문에 해당 키를 수동으로 삭제하지 않으면 메모리 누수가 발생하는 것이지 약한 참조 때문이 아닙니다.

ThreadLocal의 올바른 사용

ThreadLocal이 사용될 때마다 remove() 메서드가 호출되어 데이터를 지웁니다.

ThreadLocal 변수를 private static으로 정의하면 ThreadLocal에 대한 강력한 참조가 항상 존재하고 언제든지 ThreadLocal의 약한 참조를 통해 Entry 값에 액세스한 다음 지울 수 있습니다.

동시, 병렬 및 직렬의 차이점

串行在时间上不可能发生重叠,前一个任务没搞定,下一个任务就只能等着并行在时间上是重叠的,两个任务在同一时刻互不干扰的同时执行。

并发允许两个任务彼此干扰。统一时间点、只有一个任务运行,交替执行

并发的三大特性

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

那程序中原子性指的是 小的操作单元,比如自增操作,它本身其实并不是原子性操作,分了3步的,包括读取变量的原始值、进行加1操作、写入工作内存。所以在多线程中,有可能一个线程还没自增完,可能才执行到第二部,另一个线程就已经读取了值,导致结果错误。那如果我们能保证自增操作是一个原子性的操作,那么就能保证其他线程读取到的一定是自增后的数据。

关键字:synchronized 可见性

当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。

若两个线程在不同的cpu,那么线程1改变了i的值还没刷新到主存,线程2又使用了i,那么这个i值肯定还是之前的,线程1对变量的修改线程没看到这就是可见性问题。

如果线程2改变了stop的值,线程1一定会停止吗?不一定。当线程2更改了stop变量的值之后,但是还没来得及写入主存当中,线程2转去做其他事情了,那么线程1由于不知道线程2对stop变量的更改,因此还会一直循环下去。

关键字:volatile、synchronized、final

有序性

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

write方法里的1和2做了重排序,线程1先对flag赋值为true,随后执行到线程2,ret直接计算出结果,再到线程1,这时候a才赋值为2,很明显迟了一步

关键字:volatile、synchronized

volatile本身就包含了禁止指令重排序的语义,而synchronized关键字是由“一个变量在同一时刻只允许一条线程对其进行lock操作”这条规则明确的。

synchronized关键字同时满足以上三种特性,但是volatile关键字不满足原子性。

在某些情况下,volatile的同步机制的性能确实要优于锁(使用synchronized关键字或 java.util.concurrent包里面的锁),因为volatile的总开销要比锁低。

我们判断使用volatile还是加锁的唯一依据就是volatile的语义能否满足使用的场景(原子性)

volatile

  1. 保证被volatile修饰的共享变量对所有线程总是可见的,也就是当一个线程修改了一个被volatile修饰共享变量的值,新值总是可以被其他线程立即得知。 如果线程2改变了stop的值,线程1一定会停止吗?不一定。当线程2更改了stop变量的值之后,但是还没来得及写入主存当中,线程2转去做其他事情了,那么线程1由于不知道线程2对stop变量的更改,因此还会一直循环下去。

  2. 禁止指令重排序优化。

write方法里的1和2做了重排序,线程1先对flag赋值为true,随后执行到线程2,ret直接计算出结果,再到线程1,这时候a才赋值为2,很明显迟了一步。

但是用volatile修饰之后就变得不一样了

第一:使用volatile关键字会强制将修改的值立即写入主存;

第二:使用volatile关键字的话,当线程2进行修改时,会导致线程1的工作内存中缓存变量stop的缓存行无效(反映到硬件层的话,就是CPU的L1或者L2缓存中对应的缓存行无效);

第三:由于线程1的工作内存中缓存变量stop的缓存行无效,所以线程1再次读取变量stop的值时会去主存读取。

inc++; 其实是两个步骤,先加加,然后再赋值。不是原子性操作,所以volatile不能保证线程安全。

为什么用线程池?解释下线程池参数?

  1. 降低资源消耗;提高线程利用率,降低创建和销毁线程的消耗。

  2. 提高响应速度;任务来了,直接有线程可用可执行,而不是先创建线程,再执行。

  3. 提高线程的可管理性;线程是稀缺资源,使用线程池可以统一分配调优监控。

corePoolSize 代表核心线程数,也就是正常情况下创建工作的线程数,这些线程创建后并不会消除,而是一种常驻线程

maxinumPoolSize 代表的是 大线程数,它与核心线程数相对应,表示 大允许被创建的线程数,比如当前任务较多,将核心线程数都用完了,还无法满足需求时,此时就会创建新的线程,但是线程池内线程总数不会超过 大线程数

keepAliveTime、unit 表示超出核心线程数之外的线程的空闲存活时间,也就是核心线程不会

消除,但是超出核心线程数的部分线程如果空闲一定的时间则会被消除,我们可以通过

setKeepAliveTime 来设置空闲时间

workQueue 用来存放待执行的任务,假设我们现在核心线程都已被使用,还有任务进来则全部放入队列,直到整个队列被放满但任务还再持续进入则会开始创建新的线程

ThreadFactory 实际上是一个线程工厂,用来生产线程执行任务。我们可以选择使用默认的创建工厂,产生的线程都在同一个组内,拥有相同的优先级,且都不是守护线程。当然我们也可以选择自定义线程工厂,一般我们会根据业务来制定不同的线程工厂

Handler 任务拒绝策略,有两种情况,第一种是当我们调用shutdown 等方法关闭线程池后,这时候即使线程池内部还有没执行完的任务正在执行,但是由于线程池已经关闭,我们再继续想线程池提交任务就会遭到拒绝。另一种情况就是当达到 大线程数,线程池已经没有能力继续处理新提交的任务时,这是也就拒绝

简述线程池处理流程

线程池中阻塞队列的作用?为什么是先添加列队而不是先创建最大线程?

1. 일반 큐는 제한된 길이의 버퍼로만 보장될 수 있으며, 버퍼 길이를 초과하면 현재 태스크를 예약할 수 없으며, 차단 큐는 차단하여 큐에 계속 진입하려는 현재 태스크를 유지할 수 있습니다.

차단 대기열은 작업 대기열에 작업이 없을 때 작업을 획득한 스레드가 차단되어 스레드가 대기 상태에 들어가 CPU 리소스를 해제하도록 할 수 있습니다.

블로킹 큐는 자체 블로킹 및 깨우기 기능이 있으며 추가 처리가 필요하지 않습니다.작업 실행이 없을 때 스레드 풀은 블로킹 큐의 테이크 방법을 사용하여 일시 중단하여 코어의 생존을 유지합니다. 2. 새로운 쓰레드를 생성할 때 이때 global lock을 획득해야 하는데 이때 다른 것들을 차단해야 하므로 전체적인 효율에 영향을 미친다.

회사에 (핵심) 정규직이 10명 있는데 정규직을 10명 더 뽑는 것과 같은 일이 정규직을 초과하면

(task > core)의 경우 공장장(thread pool)이 먼저 작업자를 모집하거나, 이 10명을 채용하는 것은 아니지만, 작업이 약간 밀릴 수 있습니다. 비용). 10명의 정규직은 천천히 일하고 조만간 끝낼 것입니다 작업 수가 계속 증가하고 정규직의 초과 근무 허용 한도를 초과하면(대기열이 가득 찼음) 외주 지원을 고용할 것입니다(그들은 또한 아웃소싱이 여전히 작업을 완료하지 못하면 리더가 새 작업을 거부합니다(스레드 풀의 거부 전략).

스레드 풀의 스레드 재사용 원칙

스레드 풀은 스레드와 작업을 분리하여 스레드는 스레드이고 작업은 작업이므로 스레드를 통해 스레드를 생성할 때 스레드가 작업에 대응해야 한다는 제한을 없앱니다.

스레드 풀에서 동일한 스레드는 블록킹 큐에서 실행할 새로운 작업을 지속적으로 얻을 수 있습니다.핵심 원칙은 스레드 풀이

스레드가 캡슐화되어 작업이 실행될 때마다 새 스레드를 생성하기 위해 Thread.start()를 호출하는 대신 각 스레드가 "순환 작업"을 실행하고 이 "순환 작업"에 작업이 있는지 지속적으로 확인하도록 허용됩니다. 실행이 되어야 하고, 있다면 직접 실행 즉, task에서 run 메소드를 호출하여 일반 메소드처럼 run 메소드를 실행하는 방식으로 고정된 쓰레드만 사용하여 run 메소드를 연결한다. 시리즈의 모든 작업 중.

IOC 컨테이너를 구현하는 방법

  1. 구성 파일 구성 패키지 검사 경로

  2. .class 파일을 가져오기 위한 재귀적 패키지 스캔

  3. IOC 운영진에 인계해야 할 등급 반영 및 결정

  4. 주입해야 하는 클래스에 대한 종속성 주입

구성 파일은 스캔해야 하는 패키지의 경로를 지정하고 각각 액세스 제어 계층, 비즈니스 서비스 계층, 데이터 지속성 계층, 종속성 주입 주석 및 획득 구성 파일 주석을 나타내는 몇 가지 주석을 정의합니다.

구성 파일에서 스캔해야 하는 패키지 경로를 얻고 현재 경로 아래의 파일 정보 및 폴더 정보를 얻습니다 현재 경로에서 .class로 끝나는 모든 파일을 저장용 Set 컬렉션에 추가하고 이 세트를 트래버스합니다. 클래스에 지정된 주석이 있는 클래스가 있고 이를 IOC 컨테이너에 제공하고 안전한 맵을 정의하여 이러한 객체를 저장하고 IOC 컨테이너를 통과하며 각 클래스의 인스턴스를 가져오고 다른 클래스에 대한 종속성이 있는지 판단합니다. 클래스 인스턴스를 생성한 다음 재귀적으로 주입합니다.

봄이란 무엇입니까?

경량 오픈 소스 J2EE 프레임워크. 컨테이너 프레임워크로 javabeans(자바 객체)를 담는 데 사용되며 중간 레이어 프레임워크(universal glue)는 연결 역할을 할 수 있습니다.

Spring은 가벼운 IoC(Inversion of Control) 및 AOP(Aspect-Oriented) 컨테이너 프레임워크입니다.

-- Spring은 크기와 오버헤드 측면에서 가볍습니다.

--IoC(Inversion of Control) 기술을 통해 느슨한 결합의 목적 달성

-- Aspect 지향 프로그래밍에 대한 풍부한 지원을 제공하여 애플리케이션 비즈니스 로직과 시스템 수준 서비스를 분리하여 응집력 있는 개발을 가능하게 합니다.

-- 응용 프로그램 개체(Bean)의 구성 및 수명 주기를 포함하고 관리합니다. 이러한 의미에서 컨테이너입니다.

--간단한 구성 요소를 구성하여 복잡한 응용 프로그램으로 결합한다는 의미의 프레임워크입니다.

AOP에 대한 이해에 대해 이야기하십시오.

시스템은 각각 특정 기능을 담당하는 다양한 구성 요소로 구성됩니다. 이러한 구성 요소는 자체 핵심 기능을 구현하는 것 외에도 추가 책임을 맡는 경우가 많습니다. 로깅, 트랜잭션 관리 및 보안과 같은 핵심 서비스는 종종 고유한 핵심 비즈니스 논리가 있는 구성 요소로 롤링됩니다. 이러한 시스템 서비스는 시스템의 여러 구성 요소에 걸쳐 있기 때문에 교차 절단 문제라고도 합니다.

탈중앙화된 개체에 대한 공개 행동을 도입해야 할 때 OOP는 무력합니다. 즉, OOP를 사용하면 위에서 아래로의 관계를 정의할 수 있지만 왼쪽에서 오른쪽으로의 관계를 정의하는 데는 적합하지 않습니다. 예를 들어 로그 함수.

로깅 코드는 확산되는 개체의 핵심 기능에 관계없이 모든 개체 계층을 통해 수평으로 확산되는 경향이 있습니다.

OOP 설계에서 많은 코드 중복이 발생하여 다양한 모듈의 재사용에 도움이 되지 않습니다.

AOP: 프로그램의 교차 비즈니스 로직(예: 보안, 로그, 트랜잭션 등)을 관점으로 캡슐화한 다음 대상 개체에 주입합니다.

(특정 비즈니스 논리). AOP는 개체 또는 일부 개체의 기능을 향상시킬 수 있습니다. 예를 들어 개체의 메서드를 향상시키고 특정 메서드를 실행하기 전에 몇 가지 추가 작업을 수행할 수 있으며 특정 메서드가 실행된 후 몇 가지 추가 작업을 수행할 수 있습니다.

IOC에 대한 이해에 대해 이야기하십시오.

컨테이너 개념, 제어 반전, 종속성 주입 ioc 컨테이너: 실제로는 맵(키, 값)이며 다양한 객체(xml로 구성된 bean 노드,

@repository, @service, @controller, @component), 프로젝트가 시작되면 구성 파일에서 빈 노드를 읽고 리플렉션을 사용하여 정규화된 클래스 이름에 따라 객체를 생성하고 맵에 배치하고 스캔합니다. 위의 주석이 표시된 클래스에 추가하거나 리플렉션을 통해 객체를 생성하여 맵에 배치합니다.

이때 맵에는 다양한 객체가 있고, 다음으로 코드에서 객체를 사용해야 할 때 DI를 통해 주입할 수 있습니다.

(autowired, 리소스 및 기타 주석, xml의 bean 노드에 있는 ref 속성, 프로젝트가 시작되면 xml 노드의 ref 속성이 id에 따라 읽고 주입되며 이러한 주석도 유형 또는 id에 따라 스캔 및 주입됩니다. ; id는 개체 이름입니다).

통제 역전:

IOC 컨테이너가 도입되기 전에 객체 A는 객체 B에 종속되어 객체 A가 초기화되거나 특정 지점까지 실행될 때 적극적으로 객체 B를 생성하거나 생성된 객체 B를 사용해야 합니다. 객체 B를 생성하든 사용하든 컨트롤은 사용자의 손에 달려 있습니다.

IOC 컨테이너가 도입된 후 개체 A와 개체 B 간의 직접 연결이 끊어지고 개체 A가 개체 B가 필요한 지점까지 실행되면 IOC 컨테이너는 적극적으로 개체 B를 생성하여 개체 A가 필요한 곳에 주입합니다.

전후 비교를 통해 개체 A가 종속 개체 B를 얻는 과정이 능동적 행동에서 수동적 행동으로 바뀌고 통제권이 반전되는 것을 보는 것이 어렵지 않습니다. .

모든 개체의 제어 권한은 모두 "제3자" IOC 컨테이너로 이전되므로 IOC 컨테이너는 전체 시스템의 핵심 핵심이 되며 시스템의 모든 개체를 접착하는 "접착제" 역할을 합니다. 함께 "접착제"가 없으면 개체가 서로 연결되지 않으므로 일부 사람들은 IOC 컨테이너를 "접착제"에 비교합니다.

의존성 주입:

"종속 객체를 얻는 과정이 역전됩니다." 제어가 반전된 후 종속 개체를 얻는 프로세스는 자체 관리에서 IOC 컨테이너에 의한 활성 주입으로 변경됩니다. 종속성 주입은 IOC를 구현하는 방법입니다. 즉, IOC 컨테이너는 런타임 중에 개체에 특정 종속성을 동적으로 주입합니다.

BeanFactory와 ApplicationContext의 차이점은 무엇입니까?

ApplicationContext는 BeanFactory의 하위 인터페이스입니다.

ApplicationContext는 보다 완벽한 기능을 제공합니다.

① MessageSource를 상속받아 국제화를 지원합니다.

②통합 리소스 파일 액세스 방법.

③리스너에 Bean을 등록하는 이벤트를 제공합니다.

④ 여러 구성 파일을 동시에 불러옵니다.

⑤여러 컨텍스트(상속 관계 포함)를 로드하여 각 컨텍스트가 애플리케이션의 웹 레이어와 같은 특정 수준에 집중되도록 합니다.

BeanFactroy는 bean을 주입하기 위해 지연 로딩을 사용합니다. 즉, bean이 사용될 때만(getBean() 호출) bean이 로드되고 인스턴스화됩니다. 이런 식으로 기존 Spring 구성 문제를 찾을 수 없습니다.

질문. Bean의 특정 속성이 주입되지 않으면 BeanFacotry가 로드된 후 getBean 메서드가 처음 호출될 때까지 예외가 발생하지 않습니다.

컨테이너가 시작될 때 한 번에 모든 빈을 생성하는 ApplicationContext. 이와 같이 컨테이너가 시작되면 Spring에서 구성 오류를 찾을 수 있으므로 종속 속성이 주입되었는지 확인하는 데 유용합니다.

ApplicationContext가 시작된 후 모든 단일 인스턴스 빈이 미리 로드됩니다. 단일 인스턴스 빈을 미리 로드하면 필요할 때 이미 생성되었기 때문에 기다릴 필요가 없습니다.

기본 BeanFactory와 비교할 때 ApplicationContext의 유일한 단점은 메모리 공간을 차지한다는 것입니다. 애플리케이션 구성 시

콩이 많으면 프로그램이 느리게 시작됩니다.

BeanFactory는 일반적으로 프로그래밍 방식으로 생성되며 ApplicationContext는 다음과 같이 선언적으로 생성될 수도 있습니다.

컨텍스트로더.

BeanFactory와 ApplicationContext 모두 BeanPostProcessor, BeanFactoryPostProcessor를 지원합니다.

사용하지만 둘의 차이점은 BeanFactory는 수동으로 등록해야 하는 반면 ApplicationContext는 자동으로 등록된다는 것입니다.

Spring Bean의 생명주기에 대해 설명하시오.

  1. 클래스를 구문 분석하여 BeanDefinition을 얻습니다.

  2. 생성자가 여러 개인 경우 생성자를 유추합니다.

  3. 시공방법 결정 후 객체 인스턴스화

  4. 객체에 @Autowired로 주석이 달린 속성의 속성을 채웁니다.

  5. BeanNameAware, BeanFactoryAware와 같은 Aware 메서드를 다시 호출합니다.

  6. BeanPostProcessor 초기화 전에 메소드 호출

  7. 호출 초기화 방법

  8. AOP가 수행될 BeanPostProcessor의 초기화된 메서드를 호출합니다.

  9. 현재 생성된 빈이 싱글톤이면 싱글톤 풀에 들어간다.

  10. 콩을 사용하다

  11. Spring 컨테이너가 닫힐 때 DisposableBean에서 destroy() 메서드를 호출합니다.

Spring에서 지원하는 여러 bean의 범위를 설명하십시오.

싱글톤: 기본적으로 각 컨테이너에는 하나의 빈 인스턴스만 있으며 싱글톤 모드는 BeanFactory 자체에서 유지 관리됩니다. 이 개체의 수명 주기는 Spring IOC 컨테이너와 일치합니다(단, 처음 주입될 때만 생성됨).

프로토타입: 각 빈 요청에 대한 인스턴스를 제공합니다. 주입할 때마다 새 개체가 생성됩니다.

request: bean은 각 HTTP 요청에서 싱글톤 객체를 생성하도록 정의됩니다. 즉, 이 싱글톤 객체는 단일 요청에서 재사용됩니다.

세션: 요청 범위와 유사하게 각 세션에 빈 인스턴스가 있는지 확인하고 세션이 만료된 후 빈이 무효화됩니다.

application: bean은 ServletContext의 라이프 사이클에서 싱글톤 객체를 재사용하도록 정의됩니다.

websocket: bean은 websocket의 생명주기에서 싱글톤 객체를 재사용하도록 정의됩니다. global-session: 글로벌 범위, global-session은 포틀릿 애플리케이션과 관련됩니다. 애플리케이션이 포틀릿 컨테이너에서 작동하도록 배포되면 많은 포틀릿이 포함됩니다. 모든 포틀릿에 대한 글로벌 스토리지 변수를 선언하려면 이 글로벌 변수를 글로벌 세션에 저장해야 합니다. 전역 범위는 Servlet의 세션 범위와 동일한 효과를 가집니다.

Spring 프레임워크의 싱글톤 빈은 스레드로부터 안전합니까?

Spring의 Bean은 기본적으로 싱글톤 모드이며 프레임워크는 Bean의 다중 스레드 캡슐화를 수행하지 않습니다.

Bean이 stateful인 경우 개발자가 직접 스레드 안전성을 확보해야 합니다.간단한 방법은 bean의 범위를 변경하고 "singleton"을 ''protopyte''로 변경하여 Bean에 대한 각 요청이 새 Bean과 동등하도록 하는 것입니다. () 이렇게 하면 스레드 안전성이 보장됩니다.

상태 저장이란 데이터 저장 기능이 있음을 의미합니다.

Stateless는 데이터를 저장하지 않는다는 것을 의미합니다.컨트롤러, 서비스 및 DAO 레이어 자체는 스레드로부터 안전하지 않습니다.

내부에서 메서드를 호출하는 것으로 인스턴스***를 호출하는 멀티스레드 메서드는 메모리에 변수를 복사하는데 이는 자신의 스레드의 작업 메모리로 안전하다.

Dao는 데이터베이스 연결을 운영할 것입니다. 연결은 데이터베이스 트랜잭션과 같은 상태를 유지합니다. Spring의 트랜잭션 관리자는 Threadlocal을 사용하여 서로 다른 스레드에 대한 독립적인 연결 복사본 세트를 유지함으로써 스레드가 서로에게 영향을 미치지 않도록 합니다(Spring은 트랜잭션이 같은 연결)

Bean에 상태 저장 인스턴스 변수 또는 클래스 변수를 선언하지 마십시오. 필요한 경우 ThreadLocal을 사용하여 변수를 만드십시오.

빈의 인스턴스 변수 또는 클래스 변수를 여러 스레드 간에 공유해야 하는 경우 동기화, 잠금, CAS 및 기타 방법만 사용하여 스레드 동기화를 달성할 수 있습니다.

Spring 프레임워크에서 사용되는 디자인 패턴은 무엇입니까?

단순 팩토리: 팩토리 클래스는 전달된 매개변수에 따라 생성해야 하는 제품 클래스를 동적으로 결정합니다.

Spring의 BeanFactory는 단순 팩토리 패턴의 구현으로 Bean 객체는 고유한 식별자를 전달하여 얻어지지만 매개변수를 전달한 후 생성되는지 아니면 매개변수를 전달하기 전에 생성되는지는 특정 상황에 따라 다릅니다.

공장 방법:

FactoryBean 인터페이스를 구현하는 빈은 팩토리라고 불리는 빈의 일종이다. 특징은 bean을 얻기 위해 getBean() 호출을 사용할 때 spring이 자동으로 bean의 getObject() 메서드를 호출하므로 반환되는 것은 factory bean이 아니라 bean.getOjbect() 메서드의 반환값이다. .

싱글톤 모드: 클래스에 인스턴스가 하나만 있는지 확인하고 액세스할 수 있는 전역 액세스 지점을 제공합니다.

Spring의 싱글톤 구현: Spring의 싱글톤 패턴은 문장의 후반부를 완성합니다. 즉, 전역 액세스 지점 BeanFactory를 제공합니다. 그러나 Spring은 임의의 Java 객체를 관리하기 때문에 생성자 수준에서 싱글톤 제어가 없습니다.

어댑터 모드:

Spring은 어댑터 인터페이스를 정의하므로 컨트롤러의 각 유형에는 해당 어댑터 구현 클래스가 있고 어댑터가 대체할 수 있습니다.

컨트롤러는 해당 메서드를 실행합니다. 이와 같이 Controller를 확장할 때 하나의 어댑터 클래스만 추가하면 SpringMVC의 확장이 완료된다.

데코레이터 패턴: 개체에 일부 추가 책임을 동적으로 추가합니다. 데코레이터 패턴은 기능 추가 측면에서 서브클래싱보다 더 유연합니다.

동적 프록시:

관찰자 패턴:

Spring의 이벤트 기반 모델은 관찰자 모드를 사용하며 Spring에서 관찰자 모드의 일반적인 사용은 수신기의 구현입니다.

전략 패턴:

템플릿 메서드: 상위 클래스는 골격(호출되는 메서드 및 순서)을 정의하고 일부 특정 메서드는 하위 클래스에 의해 구현됩니다.

큰 이점: 코드 재사용, 코드 중복 감소. 하위 클래스에 의해 구현되는 특정 메서드를 제외하고 다른 메서드와 메서드 호출 순서는 부모 클래스에 미리 작성되어 있습니다.

Spring 트랜잭션 및 격리 수준의 구현 방법 및 원리?

Spring 프레임워크를 사용할 때 트랜잭션을 사용하는 방법에는 프로그래밍 방식과 선언적 방식의 두 가지가 있습니다.

@Transactional 주석은 선언적입니다.

먼저 트랜잭션의 개념은 데이터베이스 수준인데 Spring은 데이터베이스의 트랜잭션을 기반으로 확장할 뿐이며 프로그래머가 트랜잭션을 보다 편리하게 운영할 수 있는 몇 가지 방법을 제공합니다.

예를 들어 메서드에 @Transactional 주석을 추가하여 트랜잭션을 시작할 수 있습니다. 이 메서드의 모든 SQL은 트랜잭션에서 실행되고 통일된 성공 또는 실패입니다.

메소드에 @Transactional 어노테이션을 추가한 후 Spring은 이 클래스를 기반으로 프록시 오브젝트를 생성하고 이 프록시 오브젝트를 Bean으로 사용합니다.이 프록시 오브젝트의 메소드를 사용할 때 이 메소드에 @Transactional 어노테이션이 있으면 그런 다음 프록시 논리는 먼저 트랜잭션의 자동 커밋을 거짓으로 설정한 다음 원래 비즈니스 논리 메서드를 실행합니다.비즈니스 논리 메서드 실행에 예외가 없으면 프록시 논리에 트랜잭션을 제출합니다. . 비즈니스 로직 메소드 실행에 예외가 있으면 트랜잭션이 롤백됩니다.

물론 예외가 발생한 트랜잭션을 롤백하도록 설정 가능하며, @Transactional 어노테이션의 rollbackFor 속성을 사용하여 설정할 수 있으며, 기본적으로 RuntimeException 및 Error가 롤백된다.

스프링 트랜잭션 격리 수준은 데이터베이스의 격리 수준에 기본 수준을 더한 것입니다.

스프링 트랜잭션 전파 메커니즘

여러 트랜잭션 메서드가 서로를 호출할 때 이러한 메서드 간에 트랜잭션이 전파되는 방식

메서드 A는 트랜잭션 메서드이고 메서드 B는 메서드 A 실행 중에 호출됩니다. 메서드 B에 트랜잭션이 있는지 여부와 메서드 B의 트랜잭션 요구 사항이 다른지 여부는 메서드 A 트랜잭션의 구체적인 실행에 영향을 미칩니다. 메소드 A의 트랜잭션은 메소드 B의 트랜잭션 실행에도 영향을 미치며, 이 영향은 두 메소드에 의해 정의된 트랜잭션 전파 유형에 의해 결정됩니다.

REQUIRED(Spring의 기본 트랜잭션 전파 유형): 현재 트랜잭션이 없으면 직접 새 트랜잭션을 생성하고, 현재 트랜잭션이 있으면 이 트랜잭션에 가입합니다. SUPPORTS: 현재 트랜잭션이 있으면 현재 트랜잭션에 가입합니다. 현재 트랜잭션 없음, 비 트랜잭션 메서드 실행 사용

MANDATORY: 현재 거래가 있고, 현재 거래에 참여하고, 현재 거래가 없으면 예외를 던진다.

REQUIRES_NEW: 새 트랜잭션을 생성하고 현재 트랜잭션이 있으면 일시 중지합니다.

NOT_SUPPORTED: non-transactional 방식으로 실행, 현재 트랜잭션이 있으면 현재 트랜잭션을 중지

NEVER: 트랜잭션을 사용하지 않음, 현재 트랜잭션이 존재하는 경우 예외 발생

NESTED: 현재 트랜잭션이 존재하면 중첩된 트랜잭션에서 실행되며, 그렇지 않으면 REQUIRED의 작업은 동일합니다(트랜잭션 열기).

REQUIRES_NEW와의 차이점

REQUIRES_NEW는 새로운 트랜잭션을 생성하고 새로 열린 트랜잭션은 원래 트랜잭션과 아무 관련이 없으며 NESTED는 현재 트랜잭션(현재 트랜잭션을 상위 트랜잭션이라고 함)이 있을 때 중첩된 트랜잭션(하위 트랜잭션이라고 함)을 여는 것입니다. . NESTED의 경우 상위 트랜잭션이 롤백되면 하위 트랜잭션도 롤백되고 REQUIRES_NEW의 경우 새로 열린 트랜잭션에 영향을 주지 않고 원래 트랜잭션이 롤백됩니다.

필수와 필수의 차이점

REQUIRED의 경우 호출자에게 트랜잭션이 있는 경우 호출자와 호출자가 동일한 트랜잭션을 사용하고, 호출자가 예외가 있는 경우 동일한 트랜잭션을 공유하므로 호출자가 catch 여부에 관계없이 트랜잭션이 롤백됩니다. NESTED에서 이 경우 호출 수신자에서 예외가 발생하면 호출자는 예외를 catch할 수 있으므로 하위 트랜잭션만 롤백되고 상위 트랜잭션은 영향을 받지 않습니다.

스프링 트랜잭션은 언제 실패합니까?

스프링트랜잭션의 원리는 AOP로 여러모로 개선되었으니 이 AOP가 동작하지 않는 것이 실패의 근본원인! 일반적인 상황은 다음과 같습니다

  1. Self-invocation이 발생하고 클래스는 이것을 이용하여 이 클래스의 메서드를 호출합니다.(이것은 보통 생략됩니다.) 이때 this 객체는 프록시 클래스가 아니라 UserService 객체 자체입니다! 솔루션은 매우 간단합니다. 이것이 UserService의 프록시 클래스가 되도록 하십시오!

  2. 방법은 공개되지 않습니다

  3. 데이터베이스가 트랜잭션을 지원하지 않습니다.

  4. 봄에 의해 관리되지 않음

  5. 예외가 발생하고 트랜잭션이 롤백되지 않습니다(또는 발생한 예외가 정의되지 않았으며 기본값은 RuntimeException입니다).

빈 자동 연결이란 무엇이며 방법은 무엇입니까?

autowiring을 활성화하려면 xml 구성 파일에서 "autowire" 속성을 정의하기만 하면 됩니다.

autowire 속성에는 다섯 가지 조립 방법이 있습니다.

Cutomer 생성자의 매개 변수 person의 유형은 Person이며 Spirng는 생성 방법을 통해 자동으로 Person 유형을 조립합니다.

<콩 id="cutomer" class="com.xxx.xxx.Cutomer" autowire="구성자"/> <콩 id="사람" class="com.xxx.xxx.사람"/>

autodetect - 기본 생성자가 있으면 생성자에 의해 자동 조립되고 그렇지 않으면 byType에 의해 자동 조립됩니다.

기본 생성자가 있으면 생성자에 의해 자동 조립되고 그렇지 않으면 byType에 의해 자동 조립됩니다.

@Autowired는 빈을 자동으로 연결하고 필드, 세터 메서드 및 생성자에서 사용할 수 있습니다.

springmvc, springBoot

Spring Boot, Spring MVC 및 Spring의 차이점은 무엇입니까

Spring은 Bean을 관리하는 데 사용되는 IOC 컨테이너이며 종속성 주입을 사용하여 제어 반전을 달성하고 다양한 프레임워크를 쉽게 통합할 수 있으며 AOP 메커니즘을 제공하여 OOP 코드 중복을 보완하고 다양한 클래스 및 메서드에서 공통 처리를 보다 편리하게 추출할 수 있습니다. 로그, 예외 등과 같은 메서드 실행에 자동으로 주입됩니다.

springmvc는 웹 프레임워크에 대한 스프링의 솔루션으로 요청을 수신하기 위한 일반적인 전면 컨트롤러 Servlet을 제공하고 일련의 라우팅 전략(URL에서 핸들로 매핑)을 정의하고 실행 핸들을 조정하여 핸들 결과 보기 분석 기술을 생성합니다. 보고 프런트 엔드에 표시

springboot는 spring에서 제공하는 신속한 개발 툴킷으로 프로그래머가 spring+springmvc 응용 프로그램을 보다 편리하고 빠르게 개발할 수 있도록 하고 구성을 단순화하며(기본 구성은 동의됨) 일련의 솔루션(스타터 메커니즘), redis, mongodb, es, 상자에서 사용할 수 있습니다

스프링 MVC 워크플로우

  1. 사용자는 전면 컨트롤러 DispatcherServlet에 요청을 보냅니다.

  2. DispatcherServlet은 HandlerMapping 프로세서 매퍼 호출 요청을 받습니다.

  3. 프로세서 매퍼는 특정 프로세서(xml 구성 및 주석에 따라 검색 가능)를 찾아 프로세서와 프로세서 인터셉터(있는 경우 생성됨)를 생성하고 DispatcherServlet에 반환합니다.

  4. DispatcherServlet은 HandlerAdapter 핸들러 어댑터를 호출합니다.

  5. HandlerAdapter는 특정 프로세서(컨트롤러, 백엔드 컨트롤러라고도 함)를 호출하도록 조정됩니다.

  6. 컨트롤러는 실행이 완료된 후 ModelAndView로 돌아갑니다.

  7. HandlerAdapter는 컨트롤러 실행 결과 ModelAndView를 DispatcherServlet에 반환합니다. 8) DispatcherServlet은 ModelAndView를 ViewReslover 뷰 파서에 전달합니다.

  8. ViewReslover는 구문 분석 후 특정 보기를 반환합니다.

  9. DispatcherServlet은 View에 따라 View를 렌더링합니다(즉, 모델 데이터를 View에 채움).

  10. DispatcherServlet은 사용자에게 응답합니다.

Spring MVC의 주요 구성 요소?

처리기: 즉, 프로세서입니다. 컨트롤러 계층인 MVC의 C에 직접 해당하며 클래스 또는 메서드가 될 수 있는 많은 특정 형식이 있습니다. Controller 계층에서 @RequestMapping으로 표시된 모든 메서드는 실제로 요청을 처리할 수 있는 한 Handler로 간주될 수 있습니다.

  1. HandlerMapping 프로세서 매퍼인 initHandlerMappings(context)는 사용자가 요청한 리소스 URI에 따라 Handler를 찾습니다. SpringMVC에는 많은 요청이 있을 것이고 각 요청은 처리할 Handler가 필요하며 요청을 받은 후 사용할 Handler는 HandlerMapping이 수행해야 하는 작업입니다.

  2. HandlerAdapter initHandlerAdapters(컨텍스트), 어댑터. SpringMVC의 Handler는 어떤 형태든 될 수 있기 때문에 요청을 처리할 수 있는 한 괜찮지만 Servlet이 요구하는 처리 방식의 구조는 고정되어 있고 모든 방식은 요청과 응답을 매개변수로 사용한다. 고정 서블릿 처리 방법이 처리를 위해 유연한 핸들러를 호출하도록 하는 방법은 무엇입니까? 이것이 HandlerAdapter가 하는 일입니다. Handler는 작업을 위한 도구이고, HandlerMapping은 수행해야 할 작업에 따라 해당 도구를 찾는 데 사용되며, HandlerAdapter는 작업을 위해 도구를 사용하는 사람입니다.

  3. HandlerExceptionResolver initHandlerExceptionResolvers(context), 다른 구성 요소가 작동하는 데 사용됩니다. 작업 과정에서 필연적으로 문제가 발생하는데 문제가 발생한 후에는 어떻게 해야 합니까? 이를 위해서는 SpringMVC의 HandlerExceptionResolver라는 예외를 처리하기 위한 특별한 역할이 필요합니다. 구체적으로 이 구성 요소의 기능은 예외에 따라 ModelAndView를 설정한 다음 렌더링을 위해 렌더링 메서드에 전달하는 것입니다.

  4. ViewResolver initViewResolvers(context), ViewResolver는 문자열 유형 뷰 이름과 로케일을 뷰 유형 뷰로 해석하는 데 사용됩니다. 보기는 페이지를 렌더링하는 데 사용됩니다. 즉, html(또는 다른 유형) 파일을 생성하기 위해 프로그램에서 반환된 매개변수를 템플릿에 입력합니다. 여기에 두 가지 주요 질문이 있습니다. 어떤 템플릿을 사용할 것인가? 매개변수를 채우는 데 사용되는 기술(규칙)은 무엇입니까? 이것이 실제로 ViewResolver의 주요 작업입니다.ViewResolver는 렌더링에 사용되는 템플릿과 렌더링에 사용되는 기술(즉, 뷰 유형)을 찾아야 합니다.특정 렌더링 프로세스는 다른 뷰 자체에서 완료됩니다.

  5. RequestToViewNameTranslator initRequestToViewNameTranslator(context),ViewResolver是根据ViewName查找View,但有的 Handler处理完后并没有设置View也没有设置ViewName,这时就需要从request获取ViewName了,如何从request中获取ViewName就是RequestToViewNameTranslator要做的事情了。 RequestToViewNameTranslator在Spring MVC容器里只可以配置一个,所以所有request到 ViewName的转换规则都要在一个Translator里面全部实现。

  6. LocaleResolver initLocaleResolver(context), 解析视图需要两个参数:一是视图名,另一个是Locale。视图名是处理器返回的,Locale是从哪里来的?这就是LocaleResolver要做的事情。LocaleResolver用于从request 解析出Locale,Locale就是zh-cn之类,表示一个区域,有了这个就可以对不同区域的用户显示不同的结果。SpringMVC主要有两个地方用到了Locale:一是ViewResolver视图解析的时候;二是用到国际化资源或者主题的时候。

  7. ThemeResolver initThemeResolver(context)는 테마를 해결하는 데 사용됩니다. SpringMVC의 테마는 그림, css 스타일 등과 같은 현재 테마와 관련된 모든 리소스를 저장하는 속성 파일에 해당합니다. SpringMVC의 테마는 국제화도 지원하며 동일한 테마의 다른 스타일을 다른 영역에 표시할 수 있습니다. SpringMVC의 테마 관련 클래스는 ThemeResolver, ThemeSource 및 Theme입니다. 테마는 일련의 리소스를 통해 구현되며, 테마 리소스를 얻으려면 먼저 리소스의 이름을 얻어야 하는데 이것이 바로 ThemeResolver의 역할입니다. 그런 다음 ThemeSource의 작업인 테마 이름을 통해 해당 테마(구성으로 이해할 수 있음) 파일을 찾습니다. 그런 다음 테마에서 리소스를 얻을 수 있습니다.

  8. 업로드 요청을 처리하는 데 사용되는 MultipartResolver initMultipartResolver(context). 처리 방법은 일반 요청을 MultipartHttpServletRequest로 랩핑하여 getFile 메소드를 직접 호출하여 File을 얻을 수 있으며, 여러 파일이 업로드된 경우 getFileMap을 호출하여 FileName->File 구조의 Map을 얻을 수도 있습니다. 이 구성 요소에는 업로드 요청인지 여부를 판단하고 요청을 MultipartHttpServletRequest로 패키징하고 처리 후 업로드 프로세스 중에 생성된 임시 리소스를 정리하는 데 사용되는 세 가지 메서드가 있습니다.

  9. FlashMapManager initFlashMapManager(context)는 FlashMap을 관리하는 데 사용되며 FlashMap은 주로 리디렉션에서 매개 변수를 전달하는 데 사용됩니다.

Spring Boot 자동 구성 원리?

@Import + @Configuration + 스프링 스파이

자동 구성 클래스는 각 스타터에서 제공되며 @Configuration + @Bean을 사용하여 구성 클래스를 정의하고 META-에 넣습니다.

INF/spring.factories下使用Spring spi扫描META-INF/spring.factories下的配置类

使用@Import导入自动配置类

如何理解 Spring Boot 中的 Starter

使用spring + springmvc使用,如果需要引入mybatis等框架,需要到xml中定义mybatis需要的bean

starter就是定义一个starter的jar包,写一个@Configuration配置类、将这些bean定义在里面,然后在 starter包的META-INF/spring.factories中写入该配置类,springboot会按照约定来加载该配置类

开发人员只需要将相应的starter包依赖进应用,进行相应的属性配置(使用默认配置时,不需要配

置),就可以直接进行代码开发,使用对应的功能了,比如mybatis-spring-boot--starter,springboot-starter-redis

什么是嵌入式服务器?为什么要使用嵌入式服务器?

节省了下载安装tomcat,应用也不需要再打war包,然后放到webapp目录下再运行只需要一个安装了 Java 的虚拟机,就可以直接在上面部署应用程序了

springboot已经内置了tomcat.jar,运行main方法时会去启动tomcat,并利用tomcat的spi机制加载 springmvc

Mybatis

mybatis的优缺点

优点:

  1. 基于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL 写在 XML 里,解除 sql 与程序代码的耦合,便于统一管理;提供 XML 标签, 支持编写动态 SQL 语句, 并可重用。

  2. 与 JDBC 相比,减少了 50%以上的代码量,消除了 JDBC 大量冗余的代码,不需要手动开关连接;

  3. 很好的与各种数据库兼容( 因为 MyBatis 使用 JDBC 来连接数据库,所以只要JDBC 支持的数据库 MyBatis 都支持)。

  4. Spring과 잘 통합될 수 있습니다.

  5. 개체와 데이터베이스 간의 ORM 필드 관계형 매핑을 지원하는 매핑 태그를 제공하고 개체 관계형 구성 요소 유지 관리를 지원하는 개체 관계형 매핑 태그를 제공합니다.

결점:

  1. SQL 문 작성 작업량은 상대적으로 크며, 특히 많은 필드와 관련 테이블이 있는 경우 개발자가 SQL 문을 작성해야 하는 특정 요구 사항이 있습니다.

  2. SQL 문은 데이터베이스에 의존하므로 데이터베이스 이식성이 좋지 않으며 데이터베이스를 임의로 교체할 수 없습니다.

MyBatis는 Hibernate와 어떻게 다른가요?

SQL과 ORM 간의 논쟁은 끝나지 않을 것입니다.

개발 속도 비교:

Hibernate의 진정한 숙달은 Mybatis보다 더 어렵습니다. Mybatis 프레임워크는 비교적 간단하고 사용하기 쉽지만 비교적 간단합니다.

둘의 개발 속도와 비교하여 둘의 특성과 성능을 고려할 뿐만 아니라 프로젝트 요구 사항에 따라 프로젝트 개발에 어느 것이 더 적합한지 고려해야 합니다. 프로젝트에서 사용되는 쿼리는 간단합니다. 이러한 방식으로 기본 SQL 문이 캡슐화되어 있기 때문에 최대 절전 모드를 선택하는 효율성이 매우 빠르고 SQL 문을 전혀 작성할 필요가 없으므로 많은 시간이 절약됩니다. 그러나 대규모 프로젝트의 경우 복잡한 문장이 많기 때문에 최대 절전 모드를 선택하는 것은 좋지 않으며 mybatis를 선택하면 속도가 훨씬 빨라지고 문장 관리가 더 편리해집니다.

개발 워크로드 비교:

Hibernate와 MyBatis 모두 상응하는 코드 생성 도구를 가지고 있습니다. 간단하고 기본적인 DAO 레이어 방법을 생성할 수 있습니다. 고급 쿼리의 경우

Mybatis는 SQL 문과 ResultMap을 수동으로 작성해야 합니다. 그리고 Hibernate는 우수한 매핑 메커니즘을 가지고 있으므로 개발자가 신경 쓸 필요가 없습니다.

SQL 생성 및 결과 매핑은 비즈니스 프로세스에 더 집중할 수 있습니다.

SQL 최적화 측면:

Hibernate의 질의는 성능을 소비할 테이블의 모든 필드를 질의할 것입니다. Hibernate는 또한 질의가 필요한 필드를 지정하기 위해 자체 SQL을 작성할 수 있지만 이것은 Hibernate 개발의 단순성을 파괴합니다. Mybatis의 SQL은 수동으로 작성되므로 필요에 따라 쿼리 필드를 지정할 수 있습니다.

Hibernate HQL 문의 튜닝은 SQL을 출력해야 하는데, Hibernate의 SQL은 너무 못생겨서 많은 사람들에게 거부당하고 있다.

MyBatis의 SQL은 수동으로 작성되므로 조정이 쉽습니다. 그러나 Hibernate에는 자체 로그 통계가 있습니다. Mybatis 자체에는 로그 통계가 없으며 로깅에 Log4j를 사용합니다.

개체 관리 비교:

Hibernate는 객체 상태 관리(상태 관리) 기능을 제공하는 완전한 객체/관계형 매핑 솔루션이므로 개발자는 더 이상 기본 데이터베이스 시스템의 세부 사항에 신경을 쓸 필요가 없습니다. 즉, 일반적인 JDBC/SQL 지속 계층 솔루션에서 SQL 문을 관리해야 하는 필요성에 비해 Hibernate는 Java 애플리케이션에서 데이터를 유지하기 위해 보다 자연스러운 객체 지향 관점을 채택합니다.

즉, Hibernate를 사용하는 개발자는 SQL문의 실행과 상관없이 항상 객체의 상태에 집중해야 합니다.

세부 사항의 이 부분은 Hibernate에 의해 처리되었으며 시스템 성능 튜닝을 수행할 때 개발자만 이를 이해하면 됩니다. 그리고

MyBatis는 이 분야에 대한 문서가 없으며 사용자는 개체 자체를 자세히 관리해야 합니다.

캐시 메커니즘 비교:

같은 점: 둘 다 자체 캐시를 구현하거나 다른 타사 캐싱 솔루션을 사용할 수 있으며 어댑터를 만들어 캐싱 동작을 완전히 재정의할 수 있습니다.

차이점: Hibernate의 두 번째 수준 캐시 구성은 SessionFactory에 의해 생성된 구성 파일에 자세히 구성되고 특정 테이블-객체 매핑에는 어떤 종류의 캐시가 구성되는지.

MyBatis의 2단계 캐시 구성은 각각의 특정 테이블-객체 매핑에서 자세히 구성되므로 다른 테이블에 대해 다른 캐싱 메커니즘을 사용자 정의할 수 있습니다. 그리고 Mybatis는 Cache-ref를 통해 *** 네임스페이스에서 동일한 캐시 구성 및 인스턴스를 공유할 수 있습니다.

둘의 비교: Hibernate는 질의 객체에 대한 좋은 관리 메커니즘을 가지고 있기 때문에 사용자는 SQL에 대해 신경 쓸 필요가 없습니다. 따라서 두 번째 수준 캐시를 사용할 때 더티 데이터가 있는 경우 시스템에서 오류를 보고하고 메시지를 표시합니다.

이와 관련하여 MyBatis는 2단계 캐시를 사용할 때 매우 주의해야 합니다. 데이터 업데이트 작업의 범위를 완전히 결정할 수 없는 경우 Cache를 맹목적으로 사용하지 마십시오. 그렇지 않으면 더티 데이터의 출현으로 인해 시스템의 정상적인 작동에 큰 위험이 감춰질 수 있습니다.

Hibernate는 강력한 기능, 우수한 데이터베이스 독립성 및 강력한 O/R 매핑 능력을 가지고 있습니다.

Hibernate가 적절하게 캡슐화되면 프로젝트의 전체 지속성 계층 코드는 작성해야 할 코드가 거의 없이 매우 단순해지고 개발 속도가 매우 빨라져 매우 멋집니다.

Hibernate의 단점은 학습의 문턱이 낮지 않고 숙달의 문턱이 높다는 점이며, O/R 매핑을 설계하는 방법, 성능과 객체 모델의 균형을 맞추는 방법, Hibernate를 잘 활용하는 방법 등은 경험이 필요합니다. 그리고 능력.그냥 작동합니다.

iBATIS는 쉽게 시작하고 배우고 즉시 사용할 수 있습니다.데이터베이스 쿼리에 대한 자동 객체 바인딩 기능을 제공하고 SQL 사용에 대한 좋은 경험을 계속합니다.그렇게 높은 객체 모델 요구 사항이 없는 프로젝트에 매우 적합합니다.

iBATIS의 단점은 프레임워크가 여전히 비교적 단순하고 기능이 아직 부족하다는 것입니다.데이터 바인딩 코드가 단순화되었지만 실제로는 전체 기본 데이터베이스 쿼리를 직접 작성해야 하고 작업 부하가 상대적으로 크며 빠른 데이터베이스 수정에 적응하기 쉽지 않습니다.

#{}와 ${}의 차이점은 무엇인가요?

#{}는 사전 컴파일 처리 및 자리 표시자이고 ${}는 문자열 교체 및 접합 문자입니다.

Mybatis가 #{}를 처리할 때 SQL의 #{}를 ? 기호로 바꾸고 PreparedStatement를 호출하여 값을 할당합니다.

Mybatis는 ${}를 처리할 때 ${}를 변수 값으로 바꾸고 Statement를 호출하여 값을 할당합니다.

#{}의 변수 치환은 DBMS에서 변수 치환 후 #{}에 해당하는 변수가 자동으로 작은따옴표로 추가된다.

${}의 변수 대체는 DBMS 외부에 있습니다. 변수 대체 후 ${}에 해당하는 변수는 작은따옴표로 추가되지 않습니다. #{}를 사용하면 효과적으로 SQL 삽입을 방지하고 시스템 보안을 향상시킬 수 있습니다.

마이바티스 플러그인의 동작 원리와 플러그인 작성 방법에 대해 간략히 설명한다.

답변: Mybatis는 ParameterHandler, ResultSetHandler, StatementHandler, Executor만 지원합니다.

4종의 인터페이스 플러그인 Mybatis는 JDK의 동적 프록시를 사용하여 인터페이스 메서드 차단 기능을 구현하기 위해 차단해야 하는 인터페이스에 대한 프록시 개체를 생성합니다.이 4개의 인터페이스 개체의 메서드가 실행될 때마다 차단 메서드에 진입합니다. , 특히 InvocationHandler invoke() 메서드는 가로채기 위해 지정한 메서드를 가로챕니다.

플러그인 작성: Mybatis의 인터셉터 인터페이스를 구현하고 intercept() 메소드를 재정의한 다음 플러그인에 대한 주석을 작성하고 인터셉트할 인터페이스의 메소드를 지정하고 구성 파일에서 작성된 플러그인을 구성하십시오.

MySQL

인덱싱의 기초

인덱스는 특정 값이 있는 레코드를 빠르게 찾는 데 사용됩니다. 인덱스가 없으면 일반적으로 쿼리를 실행할 때 전체 테이블을 순회합니다.

인덱싱의 원칙은 정렬되지 않은 데이터를 정렬된 쿼리로 바꾸는 것입니다.

  1. 인덱싱된 열의 내용 정렬

  2. 정렬된 결과의 반전 목록 생성

  3. 게시 목록의 내용에 데이터 주소 체인 추가

  4. 쿼리할 때 먼저 반전 목록의 내용을 가져온 다음 데이터 주소 체인을 제거하여 특정 데이터를 가져옵니다.

mysql 클러스터형 인덱스와 비클러스터형 인덱스의 차이점

둘 다 B+ 트리 데이터 구조입니다.

Clustered index: 데이터 저장소와 index를 함께 묶어 일정한 순서로 정리하여 index를 찾으면 데이터도 찾는다. 인덱스가 인접하면 해당 데이터도 디스크에 인접하게 저장되어야 합니다.

클러스터되지 않은 인덱스: 리프 노드는 데이터를 저장하지 않고 데이터 행의 주소를 저장합니다. 즉, 인덱스에 따라 데이터 행의 위치를 ​​찾은 다음 디스크를 사용하여 데이터를 찾습니다. 이것은 트리의 디렉토리와 비슷합니다.예를 들어 3장의 첫 번째 섹션 1을 찾고자 하면 이 디렉토리에서 먼저 검색하고 해당 페이지 번호를 찾은 다음 해당 페이지 번호로 이동하여 읽을 수 있습니다. 기사.

이점:

  1. 쿼리는 클러스터형 인덱스를 통해 직접 데이터를 얻을 수 있어 2차 쿼리가 필요한 비클러스터형 인덱스(비커버링 인덱스의 경우)보다 효율적이다.

  2. 클러스터형 인덱스는 데이터가 크기에 따라 정렬되기 때문에 범위 쿼리에 매우 효율적입니다.

  3. 클러스터형 인덱스는 정렬 상황에 적합하고 비클러스터형 인덱스는 적합하지 않습니다.

단점:

  1. 인덱스 유지 관리는 특히 새 행이 삽입되거나 기본 키가 업데이트되어 페이지 분할이 발생할 때 비용이 많이 듭니다. 새로운 행을 많이 삽입한 후에는 이동해야 하는 행 데이터로 인해 조각화가 발생할 수 있으므로 부하가 적은 시간대를 선택하고 OPTIMIZE TABLE을 통해 테이블을 최적화하는 것이 좋습니다. 전용 테이블스페이스를 사용하여 조각화를 약화시킬 수 있습니다.

  2. 테이블은 UUId(임의 ID)를 기본 키로 사용하기 때문에 데이터 저장소가 희박하고 클러스터형 인덱스가 전체 테이블 스캔보다 느릴 수 있으므로 int auto_increment를 기본 키로 사용하는 것이 좋습니다.

  3. 기본 키가 상대적으로 크면 보조 인덱스의 리프가 기본 키 값을 저장하기 때문에 보조 인덱스가 더 커지고 기본 키 값이 너무 길면 비 리프 노드가 더 많은 물리적 공간을 차지하게 됩니다.

InnoDB中一定有主键,主键一定是聚簇索引,不手动设置、则会使用unique索引,没有unique索引,则会使用数据库内部的一个行的隐藏id来当作主键索引。在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找,非聚簇索引都是辅助索引,像复合索引、前缀索引、唯一索引,辅助索引叶子节点存储的不再是行的物理位置,而是主键值

MyISM使用的是非聚簇索引,没有聚簇索引,非聚簇索引的两棵B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树。

如果涉及到大数据量的排序、全表扫描、count之类的操作的话,还是MyISAM占优势些,因为索引所占空间小,这些操作是需要在内存中完成的。

mysql索引的数据结构,各自优劣

索引的数据结构和具体存储引擎的实现有关,在MySQL中使用较多的索引有Hash索引,B+树索引等, InnoDB存储引擎的默认索引实现为:B+树索引。对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能 快;其余大部分场景,建议选择BTree索引。

B+树:

B+树是一个平衡的多叉树,从根节点到每个叶子节点的高度差值不超过1,而且同层级的节点间有指针相互链接。在B+树上的常规检索,从根节点到叶子节点的搜索效率基本相当,不会出现大幅波动,而且基于索引的顺序扫描时,也可以利用双向指针快速左右移动,效率非常高。因此,B+树索引被广泛应用于数据库、文件系统等场景。

哈希索引:

哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可立刻定位到相应的位置,速度非常快

동등한 쿼리인 경우 해시 인덱스는 해당 키 값을 찾기 위해 하나의 알고리즘만 거치면 되기 때문에 절대적인 이점이 있으며 키 값이 고유하다는 전제가 있습니다. 키 값이 고유하지 않은 경우 먼저 키 위치를 찾은 다음 해당 데이터를 찾을 때까지 연결 목록에 따라 역방향으로 스캔해야 합니다.

범위 쿼리 검색인 경우 원래 키 값이 정렬되기 때문에 이때 해시 인덱스는 쓸모가 없으며 해시 알고리즘 후에는 불연속이 될 수 있으며 인덱스를 사용하여 범위 쿼리를 완료할 방법이 없습니다. 검색;

해시 인덱스는 또한 정렬을 완료하기 위해 인덱스를 사용할 수 없으며 'xxx%'와 같은 일부 퍼지 쿼리(이런 종류의 부분 퍼지 쿼리는 실제로 본질적으로 범위 쿼리입니다);

해시 인덱스는 또한 다중 열 결합 인덱스의 왼쪽 일치 규칙을 지원하지 않습니다.

B+ 트리 인덱스의 키워드 검색 효율은 변동폭이 큰 B-트리와 달리 상대적으로 평균적인 수준이며, 중복키 값이 많은 경우 해시 인덱스의 효율성도 매우 낮다. 해시 충돌 문제.

인덱스 디자인의 원리?

더 빠른 쿼리, 더 작은 설치 공간

  1. 인덱싱에 적합한 열은 where 절에 나타나는 열 또는 조인 절에 지정된 열입니다.

  2. 카디널리티가 작은 테이블은 인덱싱 효과가 좋지 않으므로 이 컬럼에 대한 인덱스를 생성할 필요가 없습니다.

  3. 짧은 인덱스 사용 긴 문자열 열을 인덱싱할 경우 접두사 길이를 지정해야 인덱스 공간을 많이 절약할 수 있음 검색어가 인덱스 접두사 길이를 초과하는 경우 인덱스를 사용하여 일치하지 않는 행을 제외하고 확인 나머지 행이 일치할 가능성이 있는지 여부 .

  4. 색인을 과도하게 생성하지 마십시오. 인덱스에는 추가 디스크 공간이 필요하며 쓰기 작업의 성능이 느려집니다. 테이블의 내용을 수정하면 인덱스가 업데이트되거나 재구성되며 인덱스 열이 많을수록 이 시간이 길어집니다. 따라서 쿼리를 용이하게 하는 데 필요한 인덱스만 유지하십시오.

  5. 외래 키로 정의된 데이터 열은 인덱싱되어야 합니다.

  6. 자주 업데이트되는 필드는 인덱스 생성에 적합하지 않습니다.

  7. 데이터를 효과적으로 구분할 수 없는 컬럼이 인덱스 컬럼으로 적합하지 않은 경우(예: 성별, 남성 및 여성 불명, 기껏해야 세 가지 유형만 있고, 판별 정도가 너무 낮음)

  8. 색인을 최대한 확장하고 새 색인을 만들지 마십시오. 예를 들어 테이블에 a의 인덱스가 이미 있고 이제 (a, b)의 인덱스를 추가하려는 경우 원래 인덱스만 수정하면 됩니다.

  9. 쿼리에 거의 관여하지 않는 열의 경우 더 반복되는 값이 있는 열에 대한 인덱스를 생성하지 마십시오.

  10. 텍스트, 이미지 및 비트 데이터 유형으로 정의된 열에 대한 인덱스를 생성하지 마십시오.

가장 왼쪽 접두사 원칙은 무엇입니까? 가장 왼쪽 일치 원리는 무엇입니까

자물쇠의 종류는 무엇입니까?

잠금 기반 속성 분류: 공유 잠금, 배타 잠금.

잠금 기반 세분화된 분류: 행 수준 잠금(INNODB), 테이블 수준 잠금(INNODB, MYISAM), 페이지 수준 잠금(BDB 엔진), 레코드 잠금, 갭 잠금 및 키 잠금.

트랜잭션 A가 성공적으로 잠긴 후 누군가 테이블의 행에 배타적 잠금을 이미 추가했으며 전체 테이블에 공유 또는 배타적 잠금을 추가할 수 없음을 뒤에 있는 사람들에게 알리도록 상태를 설정하면 다음을 수행해야 합니다. 나중에 전체 테이블을 잠급니다. 테이블을 잠그는 사람은 잠금을 위해 전체 인덱스 트리의 각 노드를 스캔하지 않고 테이블을 잠글 수 있는지 여부를 알기 위해 이 상태를 획득하기만 하면 됩니다.

InnoDB 스토리지 엔진의 잠금 알고리즘

관련 지식 포인트:

  1. InnoDB는 행 쿼리에 다음 키 잠금을 사용합니다.

  2. 팬텀 문제 팬텀 판독 문제를 해결하기 위한 다음 잠금 키잉

  3. 쿼리 인덱스에 고유 속성이 포함된 경우 다음 키 잠금을 레코드 키로 다운그레이드

  4. 간격 잠금 설계의 목적은 여러 트랜잭션이 동일한 범위에 레코드를 삽입하여 팬텀 읽기 문제가 발생할 수 있는 것을 방지하는 것입니다.

  5. Gap Lock을 명시적으로 닫는 방법은 두 가지가 있습니다.

트랜잭션 격리 수준을 RC B로 설정합니다. innodb_locks_unsafe_for_binlog 매개변수를 1로 설정합니다.

비즈니스 시스템에서 시간이 많이 걸리는 SQL에 대해 신경써 본 적이 있습니까? 느린 쿼리도 계산하시겠습니까? 느린 쿼리를 어떻게 최적화했습니까?

비즈니스 시스템에서 기본 키를 사용하는 쿼리를 제외하고 다른 쿼리는 테스트 라이브러리에서 테스트되며 느린 쿼리의 통계는 주로 운영 및 유지 관리에서 수행되며 비즈니스의 느린 쿼리는 피드백됩니다. 우리를 정기적으로.

느린 쿼리의 최적화는 먼저 느린 이유가 무엇인지 이해해야 합니까? 쿼리 조건이 인덱스에 도달하지 않습니까? 불필요한 데이터 열을 로드하고 있습니까? 아니면 데이터 양이 너무 많습니까?

그래서 최적화도 이 세 방향을 목표로 하고,

먼저 statement를 분석하여 추가 데이터가 로드되었는지 확인합니다. 여분의 행을 쿼리하여 버린 것일 수 있습니다.

문장의 실행 계획을 분석한 후, 문장이 사용하는 인덱스를 구한 후 문장을 수정하거나 문장이 인덱스에 최대한 적중할 수 있도록 인덱스를 수정한다.

문장의 최적화가 더 이상 불가능할 경우 테이블의 데이터 양이 너무 많은지 고려해볼 수 있으며, 그렇다면 테이블을 가로 또는 세로로 나눌 수 있습니다.

트랜잭션의 기본 특성 및 격리 수준

ACID 트랜잭션의 기본 특성은 다음과 같습니다.

원자성은 트랜잭션의 작업이 모두 성공하거나 모두 실패함을 의미합니다.

일관성은 데이터베이스가 항상 하나의 일관된 상태에서 다른 일관된 상태로 전환됨을 의미합니다. 예를 들어, A가 B에게 100위안을 이체합니다. A가 90위안만 가지고 있다고 가정하면, 우리 데이터베이스의 데이터는 지불 전에는 제약 조건을 준수하지만 거래가 성공적으로 실행되면 우리 데이터베이스 데이터는 제약 조건을 깨뜨릴 것입니다. 트랜잭션이 성공할 수 없습니다.여기서 트랜잭션이 일관성 보장 격리를 제공한다는 것은 트랜잭션의 수정 사항이 최종 커밋될 때까지 다른 트랜잭션에 표시되지 않는다는 것을 의미합니다.

지속성은 트랜잭션이 커밋되면 변경 사항이 데이터베이스에 영구적으로 저장됨을 의미합니다.

격리에는 다음과 같은 4가지 격리 수준이 있습니다.

커밋되지 않은 읽기 커밋되지 않은 읽기, 더티 읽기라고도 하는 다른 트랜잭션의 커밋되지 않은 데이터를 읽을 수 있습니다.

사용자는 id=1인 사용자의 나이가 10세여야 한다고 읽었어야 하는데, 결과적으로 다른 트랜잭션에서 커밋되지 않은 트랜잭션을 읽었고 읽은 결과 age=20, 즉 더티 읽기입니다.

읽기 커밋 읽기가 커밋되었으며 두 읽기의 결과가 일치하지 않는 것을 반복 불가능한 읽기라고 합니다.

반복 불가능한 읽기는 더티 읽기 문제를 해결하며 커밋된 트랜잭션만 읽습니다.

사용자는 id=1인 사용자를 읽기 위해 트랜잭션을 시작하고 쿼리에서 age=10을 찾고 다시 읽어서 결과=20을 찾습니다.

반복 읽기 반복 읽기, 이것은 mysql의 기본 수준입니다. 즉, 각 읽기의 결과는 동일하지만 팬텀 읽기가 발생할 수 있습니다.

직렬화 가능은 일반적으로 사용되지 않으며 각 행에서 읽은 데이터를 잠그므로 많은 시간 초과 및 잠금 경쟁 문제가 발생합니다.

더티 읽기(Dirty Read): 트랜잭션이 데이터 조각을 업데이트했으며 현재 다른 트랜잭션이 동일한 데이터 조각을 읽었습니다.어떤 이유로 이전 롤백 작업에서 후자 트랜잭션이 읽은 데이터가 올바르지 않습니다.

비반복 읽기(Non-repeatable read): 트랜잭션의 두 쿼리 사이에 데이터가 일치하지 않는데 이는 두 쿼리 프로세스 중간에 트랜잭션에 의해 업데이트된 원본 데이터가 삽입되었기 때문일 수 있습니다.

팬텀 읽기: 트랜잭션의 두 쿼리에서 데이터 항목 수가 일치하지 않습니다. 예를 들어 한 트랜잭션은 데이터의 여러 열(Row)을 쿼리하는 반면 다른 트랜잭션은 이때 새로운 데이터 열을 삽입합니다. 이전에 다음 쿼리에서 트랜잭션을 수행하면 이전에는 없었던 여러 데이터 열이 있음을 알 수 있습니다.

ACID는 무엇으로 보장됩니까?

롤백이 필요한 로그 정보를 기록한 언두 로그 로그에 의해 원자성이 보장되며, 트랜잭션이 롤백되면 성공적으로 수행된 SQL은 언두된다.

C 일관성은 다른 세 가지 주요 기능에 의해 보장되며 프로그램 코드는 비즈니스 일관성을 보장해야 합니다.

I 격리는 MVCC에 의해 보장됩니다.

D Persistence는 메모리 + redo log에 의해 보장되며 Mysql은 데이터를 수정하고 이 작업을 메모리와 redo log에 동시에 기록하며 다운 시 redo log에서 복구 가능

InnoDB 리두 로그가 디스크에 기록되고 InnoDB 트랜잭션이 준비 상태가 됩니다.

이전 준비가 성공하면 binlog가 디스크에 기록되고 트랜잭션 로그가 binlog에 지속됩니다.

InnoDB 트랜잭션이 커밋 상태에 진입(리두 로그에 커밋 레코드 쓰기)

redolog의 플러시는 시스템이 유휴 상태일 때 수행됩니다.

MVCC란?

다중 버전 동시 제어: 데이터를 읽을 때 스냅샷과 유사한 방식으로 데이터를 저장하므로 읽기 잠금과 쓰기 잠금이 충돌하지 않습니다.다른 트랜잭션 세션은 고유한 데이터 버전과 버전 체인을 볼 수 있습니다.

MVCC는 READ COMMITTED 및 REPEATABLE READ의 두 격리 수준에서만 작동합니다. 다른 두 격리 수준이면 충분합니다.

READ UNCOMMITTED는 항상 현재 트랜잭션 버전을 준수하는 데이터 행이 아니라 새 데이터 행을 읽기 때문에 MVCC는 호환되지 않습니다. SERIALIZABLE은 읽은 모든 행을 잠급니다.

클러스터형 인덱스 레코드에는 두 개의 필수 숨겨진 열이 있습니다. trx_id: 클러스터형 인덱스 레코드가 수정될 때마다 트랜잭션 ID를 저장하는 데 사용됩니다.

roll_pointer: 클러스터형 인덱스 레코드가 수정될 때마다 이전 버전이 실행 취소 로그에 기록됩니다. 이 roll_pointer는 이 클러스터 인덱스 레코드의 이전 버전의 위치를 ​​가리키는 포인터를 저장하고 이를 통해 이전 버전의 레코드 정보를 얻는다. (삽입 작업의 실행 취소 로그에는 이전 버전이 없기 때문에 이 속성이 없음에 유의하십시오.) 커밋된 읽기와 반복 읽기의 차이점은 ReadView 생성 전략이 다르다는 것입니다.

트랜잭션 시작 시 readview 생성 readView는 현재 활성화된 트랜잭션 id, 즉 커밋되지 않은 트랜잭션 id를 유지하고, 데이터에 접근하기 위한 배열을 정렬 및 생성하고, 데이터에서 트랜잭션 id를 획득(큰 transaction id를 가진 레코드를 획득) ) readview와 비교: readview의 왼쪽(readview보다 작음)에 있는 경우 액세스 가능(왼쪽은 트랜잭션이 커밋되었음을 의미)

readview의 오른쪽(readview보다 큼)에 있거나 readview에 있는 경우 액세스할 수 없습니다. roll_pointer를 가져와서 재비교를 위해 이전 버전을 가져옵니다(오른쪽은 readview가 생성된 후 트랜잭션이 나타나는 것을 의미합니다. readview에서 트랜잭션이 아직 커밋되지 않았음을 의미합니다.)

커밋된 읽기 격리 수준 아래의 트랜잭션은 각 쿼리 시작 시 독립적인 ReadView를 생성하는 반면, 반복 가능한 읽기 격리 수준은 첫 번째 읽기에서 ReadView를 생성하고 후속 읽기는 이전 ReadView를 재사용합니다.

이것은 여러 버전, 동시 읽기-쓰기, 쓰기-읽기를 달성하기 위한 버전 체인을 통한 Mysql의 MVCC입니다. 다른 ReadView 생성 전략을 통해 다른 격리 수준이 달성됩니다.

테이블 파티셔닝 후 non-sharding_key 쿼리를 처리하고 테이블 파티셔닝 후 정렬하는 방법은 무엇입니까?

  1. 매핑 테이블을 만들 수 있는데, 예를 들어 이때 판매자가 주문 목록을 조회하려면 어떻게 해야 할까요? user_id로 쿼리하지 않고 전체 테이블을 스캔할 수 없습니까? 따라서 가맹점과 사용자의 관계를 저장하기 위한 매핑 관계 테이블을 만들 수 있는데, 질의 시 먼저 가맹점을 통해 사용자 목록을 질의한 후 user_id를 질의합니다.

  2. 와이드 테이블, 주문 목록 쿼리와 같이 높은 실시간 데이터가 필요하지 않은 시나리오는 주문 테이블을 오프라인(실시간) 데이터 웨어하우스에 동기화한 다음 데이터 웨어하우스를 기반으로 와이드 테이블을 생성할 수 있습니다. 그런 다음 es와 같은 다른 서비스를 기반으로 쿼리 서비스를 제공합니다.

  3. 백그라운드에서 일부 쿼리와 같이 데이터 양이 그리 많지 않은 경우 여러 스레드로 테이블을 스캔한 다음 결과를 집계하여 수행할 수도 있습니다. 또는 비동기 형식도 가능합니다.

노동 조합

정렬 필드는 고유 인덱스입니다.

첫째, 첫 번째 페이지의 쿼리: 각 테이블의 결과 집합을 병합한 다음 두 번째 페이지와 후속 쿼리를 다시 정렬하고 이전 페이지의 정렬 필드의 마지막 값과 정렬 방법을 전달해야 합니다.

정렬 방법과 이 값에 따라 쿼리합니다. 예를 들어 정렬 필드 날짜는 이전 페이지 이후의 값이 3이고 정렬 방법은 내림차순입니다. 쿼리할 때 SQL은 select ... from table where date < 3 order by date desc limit 0,10입니다. 이러한 방식으로 여러 테이블의 결과를 병합하고 정렬할 수 있습니다.

Mysql 마스터-슬레이브 동기화 원리

mysql 마스터-슬레이브 동기화 프로세스:

Mysql의 마스터-슬레이브 복제에는 마스터(binlog 덤프 스레드), 슬레이브(I/O 스레드, SQL 스레드), 마스터에 스레드 1개, 슬레이브에 스레드 2개의 세 가지 주요 스레드가 있습니다.

마스터-슬레이브 복제의 기본인 마스터 노드 binlog는 마스터 데이터베이스가 데이터베이스의 모든 변경 기록을 binlog에 기록한다는 것입니다. Binlog는 데이터베이스 서버가 시작된 순간부터 데이터베이스 구조 또는 내용에 대한 모든 수정 사항을 저장하는 파일입니다.

마스터 노드의 로그 덤프 스레드는 binlog가 변경되면 로그 덤프 스레드가 내용을 읽고 슬레이브 노드로 보냅니다.

노드 I/O 스레드에서 binlog 내용을 받아 릴레이 로그 파일에 기록합니다.

슬레이브 노드의 SQL 스레드는 릴레이 로그 파일의 내용을 읽고 데이터 업데이트를 재생하여 최종적으로 마스터-슬레이브 데이터베이스의 일관성을 보장합니다.

참고: 마스터-슬레이브 노드는 binglog 파일 + 위치 오프셋을 사용하여 마스터-슬레이브 동기화 위치를 찾습니다.슬레이브 노드는 수신한 오프셋을 저장합니다.슬레이브 노드가 충돌하고 다시 시작하면 자동으로 시작됩니다. 위치 동기화의 위치.

mysql의 기본 복제 방식은 비동기식이므로 마스터 라이브러리는 로그를 슬레이브 라이브러리로 보낸 후 슬레이브 라이브러리가 로그를 처리했는지 여부를 신경쓰지 않으며, 메인 라이브러리 이후에는 로그가 손실됩니다. 여기에서 두 가지 개념이 발생합니다.

전체 동기식 복제

메인 라이브러리가 binlog에 쓴 후 로그는 슬레이브 라이브러리에 강제로 동기화되고 모든 슬레이브 라이브러리는 클라이언트로 반환되기 전에 실행되지만 분명히 이 방법의 성능에 심각한 영향을 미칩니다.

반동기식 복제

전체 동기화와 달리 반 동기식 복제의 논리는 다음과 같습니다.슬레이브 라이브러리가 성공적으로 로그에 쓴 후 마스터 라이브러리에 ACK 확인을 반환합니다.마스터 라이브러리는 다음과 같이 수신하면 쓰기 작업이 완료된 것으로 간주합니다. 슬레이브 라이브러리에서 최소한 하나의 확인.

MyISAM과 InnoDB의 차이점을 간략히 설명하십시오.

MyISAM:

트랜잭션을 지원하지 않지만 각 쿼리는 원자적입니다. 테이블 수준 잠금을 지원합니다. 즉, 각 작업은 전체 테이블을 잠급니다. 테이블의 총 행 수를 저장합니다. MYISAM 테이블에는 인덱스 파일, 테이블 구조 파일의 세 파일이 있습니다. , 데이터 문서;

비클러스터형 인덱스를 사용하면 인덱스 파일의 데이터 필드에 데이터 파일에 대한 포인터가 저장됩니다. 보조 인덱스는 기본적으로 메인 인덱스와 동일하지만 보조 인덱스는 고유성을 보장할 필요가 없습니다.

이노디비:

ACID 트랜잭션 지원, 트랜잭션의 4가지 격리 수준 지원, 행 수준 잠금 및 외래 키 제약 조건 지원: 동시 쓰기 지원 가능, 총 행 수를 저장하지 않음, InnoDb 엔진이 파일 공간(공유 테이블 공간)에 저장됨 , 테이블 크기는 영향을 받지 않음 운영 체제에 의해 제어됨, 테이블은 여러 파일에 분산될 수 있음) 또는 다중(독립적인 테이블 비어 있음으로 설정, 테이블 크기는 운영 체제 파일의 크기에 의해 제한됨, 일반적으로 2G), 운영 체제 파일의 크기에 의해 제한됩니다.

기본 키 인덱스는 클러스터형 인덱스(인덱스의 데이터 필드에는 데이터 파일 자체 저장)를 채택하고 보조 인덱스의 데이터 필드에는 기본 키의 값을 저장하므로 보조 인덱스에서 데이터를 찾으려면 다음이 필요합니다. Secondary Index를 통해 Primary Key 값을 먼저 찾은 후 Secondary Index에 접근하여 사용하기 쉬움 Auto-Increment Primary Key는 대용량 파일 조정을 방지하여 데이터 삽입 시 B+ 트리 구조를 유지합니다.

mysql의 인덱스 유형과 데이터베이스 성능에 미치는 영향을 간략하게 설명

일반 인덱스: 인덱싱된 데이터 열에 중복 값이 ​​포함될 수 있습니다.

고유 인덱스: 데이터 레코드의 고유성을 보장할 수 있습니다.

기본키(Primary Key): 특별한 고유 인덱스로, 하나의 테이블에 하나의 기본키 인덱스만 정의할 수 있다.

공동 인덱스: 인덱스는 INDEX(columnA, columnB) 인덱스와 같은 여러 데이터 열을 포함할 수 있습니다.

Full-text index: Inverted index를 설정함으로써 검색 효율을 크게 높일 수 있으며 필드가 포함되어 있는지 판단하는 문제는 현재 검색 엔진에서 사용하는 핵심 기술이다. ALTER TABLE table_name ADD FULLTEXT(열)로 전체 텍스트 인덱스를 생성할 수 있습니다.

인덱싱은 데이터 쿼리 속도를 크게 향상시킬 수 있습니다.

인덱스를 사용하면 쿼리 프로세스 중에 최적화 숨기기를 사용하여 시스템 성능을 향상시킬 수 있습니다.

그러나 이러한 쓰기 작업을 수행할 때 인덱스 파일도 함께 작동하기 때문에 테이블 삽입, 삭제 및 업데이트 속도가 느려집니다.

인덱스는 물리적 공간을 점유해야 합니다.데이터 테이블이 차지하는 데이터 공간 외에도 각 인덱스는 일정량의 물리적 공간을 차지합니다.클러스터형 인덱스를 구축하려면 필요한 공간이 더 커집니다.여러 개가 있는 경우 인덱스는 물리적 공간을 차지합니다. 비클러스터형 인덱스, 일단 클러스터링되면 인덱스가 변경되면 모든 비클러스터형 인덱스도 그에 따라 변경됩니다.

mysql 실행 계획을 보는 방법

실행 계획은 SQL이 쿼리를 실행하는 순서, 인덱스 쿼리를 사용하는 방법 및 반환된 결과 집합의 행 수입니다.

설명 SELECT * from A where X=? 그리고 Y=?

1. id : 쿼리의 일련번호인 일련번호이며 선택이 여러 개인 경우 몇 줄이 표시됩니다. id의 순서는 select가 나타나는 순서대로 증가합니다. id 컬럼의 값이 클수록 실행 우선순위가 높아 먼저 실행되며, id 컬럼의 값이 같으면 위에서 아래로 실행되며, id 컬럼의 값은

NULL 이후에 실행합니다.

2. selectType은 쿼리에서 각 선택 절의 유형을 나타냅니다.

SIMPLE: 이 쿼리에 UNION 쿼리 또는 하위 쿼리가 포함되어 있지 않음을 나타냅니다.

PRIMARY: 이 쿼리가 외부 쿼리임을 나타냅니다(하위 쿼리 포함).

SUBQUERY: 서브쿼리의 첫 번째 SELECT

UNION: 이 쿼리가 UNION의 두 번째 또는 후속 쿼리임을 나타냅니다.

DEPENDENT UNION: UNION의 두 번째 또는 후속 쿼리 문은 외부 쿼리에 따라 다릅니다.

UNION 결과, UNION 결과

DEPENDENT SUBQUERY: 하위 쿼리의 첫 번째 SELECT는 외부 쿼리에 따라 달라집니다. 즉, 하위 쿼리는 외부 쿼리의 결과에 따라 달라집니다.

DERIVED: 내보낸 테이블의 SELECT를 나타내는 파생됨(FROM 절의 하위 쿼리)

3.table: 문에서 쿼리한 테이블을 나타냅니다.

4.type: sql 최적화를 위한 중요한 필드이며 sql 성능 및 최적화 정도를 판단하는 중요한 지표이기도 합니다. 가치 유형의 범위:

const: 인덱스 적중을 통해 데이터 행 일치 시스템: 테이블에 시스템 테이블과 동일한 행이 하나만 있음 eq_ref: 고유한 인덱스 스캔, 각 인덱스 키에 대해 테이블의 레코드 하나만 ref와 일치 : 고유하지 않은 인덱스 스캔, 값과 일치하는 모든 항목 반환

범위: 주어진 범위의 행만 검색, 색인을 사용하여 행 선택, 일반적으로 <, > 사이에 사용됨 색인: 색인 트리만 트래버스;

ALL: 表示全表扫描,这个类型的查询是性能 差的查询之一。 那么基本就是随着表的数量增多,执行效率越慢。

执行效率:

ALL < index < range< ref < eq_ref < const < system。最好是避免ALL和index

5.possible_keys:它表示Mysql在执行该sql语句的时候,可能用到的索引信息,仅仅是可能,实际不一定会用到。

6.key:此字段是 mysql 在当前查询时所真正使用到的索引。 他是possible_keys的子集

7.key_len:表示查询优化器使用了索引的字节数,这个字段可以评估组合索引是否完全被使用,这也是我们优化sql时,评估索引的重要指标

9.rows:mysql 查询优化器根据统计信息,估算该sql返回结果集需要扫描读取的行数,这个值相关重要,索引优化之后,扫描读取的行数越多,说明索引设置不对,或者字段传入的类型之类的问题,说明要优化空间越大

10.filtered:返回结果的行占需要读到的行(rows列的值)的百分比,就是百分比越高,说明需要查询到数据越准确, 百分比越小,说明查询到的数据量大,而结果集很少

11.extra

using filesort :表示 mysql 对结果集进行外部排序,不能通过索引顺序达到排序效果。一般有 using filesort都建议优化去掉,因为这样的查询 cpu 资源消耗大,延时大。

using index:覆盖索引扫描,表示查询在索引树中就可查找所需数据,不用扫描表数据文件,往往说明性能不错。

using temporary:查询有使用临时表, 一般出现于排序, 分组和多表 join 的情况, 查询效率不高,建议优化。

using where :sql使用了where过滤,效率较高。

redis

RDB 和 AOF 机制

RDB:Redis DataBase

在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。

优点:

  1. 整个Redis数据库将只包含一个文件 dump.rdb,方便持久化。

  2. 容灾性好,方便备份。

  3. 性能 大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO 大化。使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能

4.相对于数据集大时,比 AOF 的启动效率更高。

缺点:

  1. 数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候)

  2. 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟。

AOF:Append Only File

以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录 优点:

  1. 数据安全,Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。。

  2. 通过 append 模式写文件,即使中途服务器宕机也不会破坏已经存在的内容,可以通过 redischeck-aof 工具解决数据一致性问题。

  3. AOF 机制的 rewrite 模式。定期对AOF文件进行重写,以达到压缩的目的

缺点:

  1. AOF 文件比 RDB 文件大,且恢复速度慢。

  2. 数据集大的时候,比 rdb 启动效率低。

  3. 运行效率没有RDB高

AOF文件比RDB更新频率高,优先使用AOF还原数据。

AOF比RDB更安全也更大

RDB性能比AOF好

如果两个都配了优先加载AOF

Redis的过期键的删除策略

Redis는 키-값 데이터베이스이므로 Redis에 캐시된 키의 만료 시간을 설정할 수 있습니다. Redis의 만료 전략은 언제

Redis에 캐시된 키가 만료되면 Redis에서 이를 어떻게 처리합니까?

지연 만료: 키에 액세스할 때만 키가 만료되었는지 여부를 판단하고 만료되면 삭제됩니다. 이 전략은 CPU 리소스를 최대한 절약할 수 있지만 메모리에 매우 비우호적입니다. 극단적인 경우 많은 수의 만료된 키에 다시 액세스할 수 없으므로 지워지지 않고 많은 양의 메모리를 차지합니다.

주기적 만료: 일정한 간격으로 특정 수의 데이터베이스의 expires 사전에 있는 특정 수의 키를 스캔하고 만료된 키를 지웁니다. 이 전략은 타협입니다. 예약된 검색의 시간 간격과 각 검색의 제한된 시간 소비를 조정하여 다양한 상황에서 CPU 및 메모리 리소스의 균형을 최적으로 유지할 수 있습니다.

(expires 사전은 만기 시간이 설정된 모든 키의 만기 시간 데이터를 저장합니다. 여기서 키는 키 공간의 키에 대한 포인터이고 값은 UNIX 타임스탬프로 표현되는 만기 시간이며 밀리초 단위의 정밀도를 가집니다. 키 공간 Redis 클러스터에 저장된 모든 키를 의미합니다.)

지연 만료와 주기적 만료의 두 가지 만료 전략이 Redis에서 동시에 사용됩니다.

Redis 스레딩 모델, 싱글 스레드가 빠른 이유

Redis는 Reactor 모델을 기반으로 네트워크 이벤트 핸들러를 개발했으며, 이 핸들러를 파일 이벤트 핸들러라고 합니다.

이 파일 이벤트 프로세서는 단일 스레드이므로 Redis는 단일 스레드 모델이라고 하며 IO 다중화 메커니즘을 사용하여 여러 소켓을 동시에 모니터링하고 소켓의 이벤트 유형에 따라 해당 이벤트 프로세서를 선택합니다. 이번 행사. 고성능 네트워크 통신 모델을 실현할 수 있으며 다른 내부 단일 스레드 모듈과도 연결할 수 있어 Redis 내부의 스레딩 모델의 단순성을 보장합니다. 파일 이벤트 핸들러의 구조는 다중 소켓, IO 멀티플렉서, 파일 이벤트 디스패처 및 이벤트 핸들러의 4개 부분으로 구성됩니다.

(명령 요청 처리기, 명령 응답 처리기, 연결 응답 처리기 등).

다중 소켓은 동시에 다른 작업을 생성할 수 있으며 각 작업은 다른 파일 이벤트에 해당하지만 IO 다중화 프로그램은 여러 소켓을 수신하고 소켓을 대기열에 넣고 소켓이 주어질 때마다 대기열에서 하나를 가져옵니다. 이벤트 디스패처와 이벤트 디스패처는 소켓을 해당 이벤트 핸들러로 보냅니다.

그런 다음 Socket 이벤트가 처리된 후 IO 다중화 프로그램은 큐에 있는 다음 Socket을 이벤트 발송자에게 제공합니다. 파일 이벤트 디스패처는 각 소켓에서 생성된 현재 이벤트에 따라 처리할 해당 이벤트 핸들러를 선택합니다.

단일 스레드가 빠른 이유:

  1. 순수 메모리 작업

  2. 코어는 논블로킹 IO 멀티플렉싱 메커니즘을 기반으로 합니다.

  3. 단일 스레드는 멀티스레딩의 빈번한 컨텍스트 전환으로 인한 성능 문제를 방지합니다.

Redis 트랜잭션 구현에 대해 간략하게 설명

  1. 트랜잭션 시작 MULTI 명령의 실행은 트랜잭션의 시작을 표시합니다. MULTI 명령은 클라이언트 상태의 flags 속성에서 REDIS_MULTI 플래그를 켜면 완료됩니다.

  2. 명령 대기열에 넣기 클라이언트가 트랜잭션 상태로 전환되면 서버는 클라이언트가 보낸 명령에 따라 다른 작업을 수행합니다. 클라이언트가 보낸 명령이 MULTI, EXEC, WATCH, DISCARD 중 하나이면 이 명령을 즉시 실행하고, 그렇지 않으면 명령을 트랜잭션 대기열에 넣은 다음 QUEUED 응답을 클라이언트에 반환 클라이언트가 보낸 명령이 EXEC인 경우 , DISCARD , WATCH, MULTI 네 가지 명령을 입력하면 서버에서 즉시 이 명령을 실행합니다. 클라이언트가 4개의 명령 이외의 명령을 보내면 서버는 명령을 즉시 실행하지 않습니다. 먼저 이 명령의 형식이 올바른지 확인하고 그렇지 않은 경우 서버는 클라이언트 상태(redisClient)의 flags 속성에서 REDIS_MULTI 플래그를 끄고 클라이언트에 오류 메시지를 반환합니다. 맞으면 이 명령을 트랜잭션 큐에 넣은 다음 QUEUED를 클라이언트에 반환합니다.응답 트랜잭션 큐는 큐에 넣은 명령을 FIFO 형식으로 저장하는 것입니다.

  3. 트랜잭션 실행

클라이언트는 EXEC 명령을 보내고 서버는 EXEC 명령의 논리를 실행합니다.

클라이언트 상태의 flags 속성에 REDIS_MULTI 플래그가 없거나 REDIS_DIRTY_CAS가 포함된 경우 또는

REDIS_DIRTY_EXEC 플래그를 지정한 다음 트랜잭션 실행을 직접 취소합니다.

그렇지 않으면 클라이언트는 트랜잭션 상태(플래그에 REDIS_MULTI 플래그 있음)에 있고 서버는 클라이언트의 트랜잭션 큐를 순회한 다음 트랜잭션 큐의 모든 명령을 실행한 다음 반환된 모든 결과를 클라이언트에 반환합니다.

Redis는 트랜잭션 롤백 메커니즘을 지원하지 않지만 각 트랜잭션의 명령이 잘못되었는지 여부를 확인합니다.

Redis 트랜잭션은 프로그래머의 논리 오류 확인을 지원하지 않습니다. 예를 들어 String 유형의 데이터베이스 키에서 HashMap 유형에 대한 작업을 수행합니다!

WATCH 명령은 Redis 트랜잭션에 대한 CAS(확인 및 설정) 동작을 제공하는 낙관적 잠금입니다. 하나 이상의 키를 모니터링할 수 있으며 키 중 하나가 수정(또는 삭제)되면 후속 트랜잭션이 실행되지 않으며 EXEC 명령이 실행될 때까지 모니터링이 계속됩니다.

MULTI 명령은 트랜잭션을 시작하는 데 사용되며 항상 OK를 반환합니다. MULTI가 실행된 후 클라이언트는 계속해서 서버에 여러 명령을 보낼 수 있습니다. 이러한 명령은 즉시 실행되지 않고 대기열에 배치됩니다. EXEC 명령이 호출되면 대기열의 모든 명령이 전송됩니다. 실행.

EXEC: 트랜잭션 블록 내의 모든 명령을 실행합니다. 명령이 실행된 순서대로 정렬된 트랜잭션 블록의 모든 명령의 반환 값을 반환합니다. 작업이 중단되면 nil을 반환합니다.

클라이언트는 DISCARD를 호출하여 트랜잭션 대기열을 지우고 트랜잭션 실행을 포기할 수 있으며 클라이언트는 트랜잭션 상태를 종료합니다.

UNWATCH 명령은 시계의 모든 키 모니터링을 취소할 수 있습니다.

Redis 클러스터 체계

주인 노예

센티넬 모드:

sentinel, sentinel은 redis 클러스터에서 매우 중요한 구성 요소이며 주로 다음과 같은 기능을 가지고 있습니다.

클러스터 모니터링: Redis 마스터 및 슬레이브 프로세스가 정상적으로 작동하는지 모니터링하는 역할을 합니다.

메시지 알림: Redis 인스턴스가 실패하면 Sentinel은 관리자에게 알람 알림으로 메시지를 보냅니다.

장애 조치: 마스터 노드가 중단되면 자동으로 슬레이브 노드로 전환됩니다.

구성 센터: 장애 조치가 발생하면 클라이언트에 새 마스터 주소를 알립니다.

Sentry는 Redis 클러스터의 고가용성을 확보하기 위해 사용되며 분산형으로도 사용되며 Sentinel 클러스터로 실행되며 서로 연동됩니다.

故障转移时,判断一个 master node 是否宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的

哨兵通常需要 3 个实例,来保证自己的健壮性。

哨兵 + redis 主从的部署架构,是不保证数据零丢失的,只能保证 redis 集群的高可用性。

对于哨兵 + redis 主从这种复杂的部署架构,尽量在测试环境和生产环境,都进行充足的测试和演练。

Redis Cluster是一种服务端Sharding技术,3.0版本开始正式提供。采用slot(槽)的概念,一共分成

16384个槽。将请求发送到任意节点,接收到请求的节点会将查询请求发送到正确的节点上执行方案说明

通过哈希的方式,将数据分片,每个节点均分存储一定哈希槽(哈希值)区间的数据,默认分配了

16384 个槽位

每份数据分片会存储在多个互为主从的多节点上数据写入先写主节点,再同步到从节点(支持配置为阻塞同步) 同一分片多个节点间的数据不保持强一致性读取数据时,当客户端操作的key没有分配在该节点上时,redis会返回转向指令,指向正确的节点扩容时需要需要把旧节点的数据迁移一部分到新节点

在 redis cluster 架构下,每个 redis 要放开两个端口号,比如一个是 6379,另外一个就是 加1w 的端口号,比如 16379。

16379 端口号是用来进行节点间通信的,也就是 cluster bus 的通信,用来进行故障检测、配置更新、故障转移授权。cluster bus 用了另外一种二进制的协议,gossip 协议,用于节点间进行高效的数据交换,占用更少的网络带宽和处理时间。

优点

无中心架构,支持动态扩容,对业务透明

具备Sentinel的监控和自动Failover(故障转移)能力

客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可高性能,客户端直连redis服务,免去了proxy代理的损耗缺点

运维也很复杂,数据迁移需要人工干预只能使用0号数据库

배치 작업(파이프라인 파이프라인 작업), 분산 논리 및 스토리지 모듈 결합 등을 지원하지 않습니다.

Redis Sharding은 Redis Cluster가 나오기 전에 업계에서 일반적으로 사용되던 다중 Redis 인스턴스 클러스터 방식입니다. 주요 아이디어는 해시 알고리즘을 사용하여 Redis 데이터의 키를 해시하고 해시 함수를 통해 특정 키를 특정 Redis 노드에 매핑하는 것입니다. Java redis 클라이언트는 jedis를 구동하고 Redis Sharding 기능 즉, ShardedJedis를 지원하고 캐시 풀과 결합합니다.

ShardedJedisPool의 장점

매우 간단하다는 장점이 있습니다. 서버 측의 Redis 인스턴스는 서로 독립적이며 서로 관련이 없습니다. 각 Redis 인스턴스는 단일 서버처럼 실행됩니다. 선형 확장이 매우 쉽고 시스템이 매우 유연합니다. .단점

샤딩 프로세스는 클라이언트에 배치되므로 규모가 더 확장되면 운영 및 유지 관리에 문제가 발생합니다.

클라이언트 측 샤딩은 노드의 동적 추가 및 삭제를 지원하지 않습니다. 서버 측 Redis 인스턴스 그룹의 토폴로지 구조가 변경되면 각 클라이언트를 업데이트하고 조정해야 합니다. 연결을 공유할 수 없음 애플리케이션 규모가 커지면 리소스 낭비로 인해 최적화가 제한됨

redis 마스터-슬레이브 복제의 핵심 원칙

slaveof 명령을 실행하거나 slaveof 옵션을 설정하여 한 서버가 다른 서버의 데이터를 복제하도록 합니다. 마스터 데이터베이스는 읽기 및 쓰기 작업을 수행할 수 있으며 쓰기 작업으로 인해 데이터가 변경되면 자동으로 데이터를 슬레이브 데이터베이스에 동기화합니다. 슬레이브 데이터베이스는 일반적으로 읽기 전용이며 마스터 데이터베이스에서 동기화된 데이터를 받아들입니다. 마스터 데이터베이스는 여러 개의 슬레이브 데이터베이스를 가질 수 있으며 슬레이브 데이터베이스는 하나의 마스터 데이터베이스만 가질 수 있습니다.

전체 사본:

  1. 마스터 노드는 CPU, 메모리(페이지 테이블 복사), 하드 디스크 IO를 많이 소모하는 bgsave 명령어 포크 자식 프로세스를 통해 RDB 지속성을 수행합니다.

  2. 마스터 노드는 네트워크를 통해 RDB 파일을 슬레이브 노드로 전송하며, 이는 마스터 및 슬레이브 노드의 많은 대역폭을 소비합니다.

  3. 슬레이브 노드에서 이전 데이터를 지우고 새 RDB 파일을 로드하는 프로세스가 차단되어 클라이언트 명령에 응답할 수 없습니다. 슬레이브 노드가 bgrewriteaof를 실행하면 추가 소비 및 부분 복사도 발생합니다.

  4. 복제 오프셋: 복제를 수행하는 양 당사자인 마스터 및 슬레이브 노드는 복제 오프셋 오프셋을 유지합니다.

  5. 복제 백로그 버퍼: 마스터 노드는 내부적으로 고정 길이, 선입선출(FIFO) 대기열을 복제 백로그 버퍼로 유지합니다.마스터와 슬레이브 노드 사이의 오프셋 간격이 버퍼 길이를 초과하면 부분 복제가 불가능합니다. 전체 복사만 수행합니다.

  6. 서버 실행 ID(runid): 각 Redis 노드에는 실행 ID가 있습니다. 실행 ID는 노드가 시작할 때 노드에서 자동으로 생성됩니다. 마스터 노드는 자신의 실행 ID를 슬레이브 노드로 보내고, 슬레이브 노드는 실행 ID를 전송합니다. 마스터 노드 저장의 ID입니다. 슬레이브 노드 Redis가 연결 해제되었다가 다시 연결되면 실행 중인 ID에 따라 동기화 진행이 판단됩니다.

슬레이브 노드가 저장한 runid가 마스터 노드의 현재 runid와 같다면 마스터-슬레이브 노드가 이전에 동기화된 적이 있다는 의미이며, 마스터 노드는 계속해서 부분 복제를 시도할 것입니다(가능한지 여부). 부분 복제는 오프셋 및 복제 백로그 버퍼에 따라 다름);

슬레이브 노드가 저장한 runid가 마스터 노드의 현재 runid와 다른 경우, 연결 해제 전 슬레이브 노드가 동기화한 Redis 노드는 현재 마스터 노드가 아니며 전체 복사만 수행할 수 있음을 의미합니다.

공정 원리:

캐시 사태, 캐시 침투, 캐시 고장

캐시 사태는 캐시의 넓은 영역이 동시에 실패하여 후속 요청이 데이터베이스에 떨어지게 되어 단기간에 많은 요청으로 인해 데이터베이스가 붕괴되는 것을 말합니다.

해결책:

캐시된 데이터의 만료 시간은 임의로 설정되어 많은 양의 데이터가 동시에 만료되는 것을 방지합니다.

캐시된 각 데이터에 해당 캐시 태그를 추가하고 캐시가 유효하지 않은지 기록하고 캐시 태그가 유효하지 않은 경우 데이터 캐시를 업데이트합니다.

캐시 워밍업 뮤텍스

캐시 침투는 캐시나 데이터베이스에 없는 데이터로 인해 모든 요청이 데이터베이스에 떨어지게 되어 단기간에 많은 요청으로 인해 데이터베이스가 붕괴되는 것을 말합니다.

해결책:

인터페이스 계층은 사용자 인증 검증, id 기본 검증, id<=0 직접 가로채기와 같은 검증을 추가합니다.

캐시에서 검색할 수 없는 데이터는 데이터베이스에서 검색하지 않습니다. 이때 키-값 쌍도 키-널로 쓸 수 있습니다. 캐시의 유효 시간은 다음과 같이 더 짧은 지점으로 설정할 수 있습니다. 30초(너무 길게 설정하면 정상 상태가 됩니다. 또한 사용할 수 없음). 이렇게 하면 공격하는 사용자가 동일한 ID를 반복적으로 사용하여 Bloom 필터가 가능한 모든 데이터를 충분히 큰 비트맵으로 해시하고 존재하지 않아야 하는 데이터가 이 비트맵에 의해 가로채기 때문에 기본 쿼리에 대한 쿼리 압력을 피할 수 있습니다. 스토리지 시스템

캐시 고장은 캐시가 아닌 데이터베이스에 있는 데이터를 말하며(일반적으로 캐시 시간이 만료됨) 이때 동시 사용자가 많기 때문에 읽기 캐시가 동시에 데이터를 읽지 못하고, 동시에 데이터베이스로 이동하여 데이터를 가져오면 데이터베이스에 대한 압력이 순간적으로 증가하여 과도한 압력이 발생합니다. Cache Avalanche는 Cache Avalanche와 달리 동일한 데이터를 동시에 확인하는 것을 말하며, Cache Avalanche는 서로 다른 데이터가 만료되어 찾을 수 없는 데이터가 많아 데이터베이스를 검색하는 것을 의미합니다.

해결책

만료되지 않도록 핫스팟 데이터를 설정합니다.

뮤텍스 추가

분산/마이크로서비스

CAP 이론, BASE 이론

일관성:

즉, 업데이트 작업이 성공하여 클라이언트로 반환된 후 동시에 모든 노드의 데이터가 완전히 일치합니다.

클라이언트의 경우 일관성은 동시 액세스 중에 업데이트된 데이터를 얻는 방법을 의미합니다. 서버의 관점에서 데이터의 최종 일관성을 보장하기 위해 전체 시스템에 업데이트를 복제하고 배포하는 방법입니다.

가용성(가용성):

즉, 서비스는 항상 사용 가능하며 정상적인 응답 시간을 갖습니다. 시스템은 사용자에게 매우 좋은 서비스를 제공할 수 있으며 사용자 조작 실패 또는 액세스 시간 초과와 같은 나쁜 사용자 경험이 없습니다.

파티션 허용(파티션 내결함성):

즉, 분산 시스템이 노드 또는 네트워크 파티션 장애를 만나더라도 일관성과 가용성을 만족하는 외부 서비스를 계속 제공할 수 있습니다. 파티션 허용 오차는 애플리케이션이 분산 시스템임에도 불구하고 작동하는 단일체처럼 보이도록 만드는 기능을 필요로 합니다. 예를 들어, 현재 분산 시스템의 하나 또는 여러 대의 시스템이 다운되고 나머지 시스템은 시스템 요구 사항을 충족하기 위해 계속 정상적으로 작동할 수 있으며 이는 사용자 경험에 영향을 미치지 않습니다.

CP 및 AP: 파티션 내결함성이 보장되어야 하며, 네트워크 파티션 발생 시 서비스를 지속하려면 강력한 일관성과 가용성이 2개 중 1개만 선택 가능

BASE는 기본적으로 사용 가능(기본적으로 사용 가능), 소프트 상태(소프트 상태) 및 최종 일관성(최종 일관성)

BASE 이론은 CAP에서 일관성과 가용성 사이의 trade-off 결과로, 대규모 인터넷 시스템의 분산 실행을 요약한 것에서 파생되었으며 CAP 정리를 기반으로 점차 진화하고 있습니다. BASE 이론의 핵심 아이디어는 강력한 일관성을 달성할 수 없더라도 각 애플리케이션이 자체 비즈니스 특성에 따라 적절한 방법을 사용하여 시스템이 최종 일관성을 달성하도록 할 수 있다는 것입니다.

기본적으로 사용 가능:

응답 시간 손실: 정상적인 상황에서 사용자 요청을 처리하기 위해 결과를 반환하는 데 0.5초가 걸리지만 시스템 오류로 인해 사용자 요청을 처리하는 데 걸리는 시간은 3초가 됩니다.

시스템 기능 상실: 정상적인 상황에서 사용자는 시스템의 모든 기능을 사용할 수 있지만 시스템 방문이 갑자기 증가하여 시스템의 일부 비핵심 기능을 사용할 수 없습니다.

소프트 상태: 데이터 동기화는 특정 지연을 허용합니다.

최종 일관성: 시스템의 모든 데이터 사본은 실시간 동기화가 필요하지 않은 동기화 기간 후에 최종적으로 일관된 상태에 도달할 수 있습니다.

부하 분산 알고리즘, 유형

  1. 폴링 방식은 백엔드 서버에 순차적으로 요청을 분배하고 백엔드의 각 서버를 실제 서버 연결 수와 현재 시스템 부하에 관계없이 균형있게 처리합니다.

  2. 무작위 방법은 시스템의 무작위 알고리즘을 사용하여 백엔드 서버의 목록 크기 값에 따라 액세스할 서버 중 하나를 무작위로 선택합니다. 클라이언트가 서버를 호출하는 횟수가 증가할수록 그 실제 효과는 백엔드에서 각 서버에 대한 호출의 평균 분포에 점점 더 가까워지는 것을 확률 및 통계 이론에서 알 수 있으며, 이는 결과입니다. 투표의.

  3. 소스 주소 해시 방식 소스 주소 해시의 개념은 클라이언트의 IP 주소를 기반으로 해시 함수로 계산된 값을 얻고 이 값을 사용하여 서버 목록의 크기에 대해 모듈로 연산을 수행하는 것입니다. 액세스 서버 번호. 소스 주소 해싱 방법은 로드 밸런싱에 사용됩니다.동일한 IP 주소를 가진 클라이언트의 경우 백엔드 서버 목록이 변경되지 않은 경우 매번 액세스할 수 있도록 동일한 백엔드 서버에 매핑됩니다.

  4. 서로 다른 가중 라운드 로빈 방법을 사용하는 백엔드 서버는 시스템 구성과 현재 시스템 로드가 다를 수 있으므로 스트레스 저항 기능도 ​​다릅니다. 구성이 높고 부하가 낮은 시스템에 더 높은 가중치를 할당하여 더 많은 요청을 처리할 수 있도록 하고 구성이 낮고 부하가 높은 시스템에 낮은 가중치를 할당하여 시스템 부하를 줄이고 가중 폴링이 잘 작동함 이 문제를 적절하게 처리하고 무게에 따라 순서대로 백엔드.

  5. 가중 랜덤 방식은 가중 라운드 로빈 방식과 동일하며, 가중 랜덤 방식도 백엔드 머신의 구성과 시스템의 부하에 따라 다른 가중치를 부여합니다. 차이점은 순서가 아닌 가중치에 따라 임의로 백엔드 서버를 요청한다는 것입니다.

  6. 최소 연결 수

적은 수의 연결 알고리즘은 더 유연하고 지능적입니다.백엔드 서버의 구성이 다르기 때문에 요청 처리가 빠르거나 느릴 수 있습니다.백엔드의 현재 연결 상태에 따라 현재 연결 상태를 동적으로 선택합니다. 최종 서버

연결 백로그가 적은 서버를 사용하여 현재 요청을 처리하고 백엔드 서비스의 활용 효율성을 최대한 높이고 각 서버에 합리적인 분배를 담당합니다.

유형:

로드 밸런싱을 달성하기 위한 DNS 방식

硬件负载均衡:F5 和 A10 软件负载均衡:

Nginx、HAproxy、LVS。其中的区别:

Nginx:七层负载均衡,支持 HTTP、E-mail 协议,同时也支持 4 层负载均衡;

HAproxy:支持七层规则的,性能也很不错。OpenStack 默认使用的负载均衡软件就是

HAproxy;

LVS:运行在内核态,性能是软件负载均衡中 高的,严格来说工作在三层,所以更通用一些,适用各种应用服务。

分布式架构下,Session 共享有什么方案

  1. 采用无状态服务,抛弃session

  2. 存入cookie(有安全风险)

  3. 服务器之间进行 Session 同步,这样可以保证每个服务器上都有全部的 Session 信息,不过当服务器数量比较多的时候,同步是会有延迟甚至同步失败;

  4. IP 绑定策略 使用 Nginx (或其他复杂均衡软硬件)中的 IP 绑定策略,同一个 IP 只能在指定的同一个机器访问,但是这样做失去了负载均衡的意义,当挂掉一台服务器的时候,会影响一批用户的使用,风险很大;

  5. 使用 Redis 存储

把 Session 放到 Redis 中存储,虽然架构上变得复杂,并且需要多访问一次 Redis ,但是这种方案带来的好处也是很大的:

实现了 Session 共享;

可以水平扩展(增加 Redis 服务器);

服务器重启 Session 不丢失(不过也要注意 Session 在 Redis 中的刷新/失效机制);不仅可以跨服务器 Session 共享,甚至可以跨平台(例如网页端和 APP 端)。

简述你对RPC、RMI的理解

RPC:在本地调用远程的函数,远程过程调用,可以跨语言实现 httpClient

RMI:远程方法调用,java中用于实现RPC的一种机制,RPC的java版本,是J2EE的网络调用机制,跨

JVM调用对象的方法,面向对象的思维方式

直接或间接实现接口 java.rmi.Remote 成为存在于服务器端的远程对象,供客户端访问并提供一定的服务

원격 객체는 java.rmi.server.UniCastRemoteObject 클래스를 구현해야 클라이언트가 원격 객체에 액세스할 때 원격 객체가 자신의 복사본을 소켓 형식으로 클라이언트에 전송할 수 있습니다. "스텁" 및 서버 자체에 이미 존재하는 원격 객체를 "스켈레톤"이라고 합니다. 사실 이때 스텁은 서버와 통신하는 데 사용되는 클라이언트의 프록시이며 스켈레톤도 서버의 프록시로 간주될 수 있으며 수신 후 클라이언트의 요청에 응답하기 위해 원격 메서드를 호출하는 데 사용됩니다. 클라이언트의 요청.

분산 ID 생성 체계

1. 현재 날짜 및 시간 타임스탬프

2. 시계 순서. 카운터

3. 전역적으로 고유한 IEEE 머신 식별 번호 네트워크 카드가 있으면 네트워크 카드의 MAC 주소에서 가져오고, 네트워크 카드가 없으면 다른 방법으로 얻습니다.

장점: 간단한 코드, 우수한 성능(로컬 생성, 네트워크 소비 없음), 보장된 고유성(상대적으로 말하면 중복 가능성이 매우 낮고 무시할 수 있음)

결점:

매번 생성되는 ID는 순서가 맞지 않고 모든 숫자가 아니며 추세가 증가한다고 보장할 수 없습니다.

UUID는 문자열을 생성하여 저장 성능이 떨어지고 쿼리 효율이 느리며, 쓰기 시 순차적 추가 작업을 생성할 수 없기 때문에 삽입 작업이 필요하여 페이지 분할이 빈번하게 발생하며, 이 작업은 레코드가 많은 공간을 차지하는 경우에 사용됩니다. 이 경우 성능이 크게 떨어지고 디스크 읽기 횟수도 증가합니다.

UUID의 길이가 너무 길어 스토리지에 적합하지 않고 데이터베이스 성능을 소모합니다.

ID는 특정 비즈니스 의미가 없으며 가독성이 떨어집니다.

정보 보안 문제가 있으며 MAC 주소가 유출될 수 있습니다.

분산 잠금 솔루션

이 잠금은 서비스 내부가 아니라 각 서비스와 독립적이어야 합니다.

데이터베이스: 기본 키 충돌을 사용하여 한 번에 하나의 스레드만 제어하여 잠금, 비블로킹, 비재진입, 단일 지점 및 만료 시간 획득

Zookeeper 분산 잠금:

ZK는 임시 노드를 통해 교착 상태 문제를 해결하며, 클라이언트가 잠금을 획득한 후 갑자기 끊기면(세션 연결이 끊어짐) 임시 노드는 자동으로 삭제되고 다른 클라이언트는 자동으로 잠금을 획득합니다. 천둥 무리 효과를 해결하기 위한 임시 순차 노드

Redis 분산 잠금: setNX, 단일 스레드 처리 네트워크 요청, 동시성 보안을 고려할 필요 없음 모든 서비스 노드가 동일한 키 설정, 반환이 0이면 잠금 획득 실패

잠금 삭제: 스레드의 고유 플래그를 판단한 다음 삭제

재진입 및 잠금 갱신이 구현되지 않고 redisson으로 해결됨(AQS 구현과 유사, 워치독 모니터링 메커니즘)

redlock: 단일 노드에서만 동작한다는 의미의 메커니즘 Redis가 Sentinel을 통해 고가용성을 보장하더라도 어떤 이유로 마스터 노드가 마스터에서 슬레이브로 전환되면 잠금이 해제됩니다(redis 동기화 설정으로 인해 데이터 손실이 발생할 수 있음). Redlock은 여러 노드의 잠금에 적용되며 절반 이상의 노드가 성공적으로 획득되면 잠금이 성공한 것으로 간주됩니다.Redission에는 해당 구현이 있습니다.

분산 트랜잭션 솔루션

XA 사양: 분산 트랜잭션 모델을 정의하는 분산 트랜잭션 사양

네 가지 역할: 트랜잭션 관리자(코디네이터 TM), 자원 관리자(참가자 RM), 애플리케이션 프로그램 AP, 통신 자원 관리자 CRM 글로벌 트랜잭션: 여러 데이터베이스에 걸친 트랜잭션, 모두 제출되거나 모두 반환된 롤

JTA 트랜잭션 중 Java의 XA 사양 구현은 JDBC의 단일 데이터베이스 트랜잭션에 해당합니다.

2단계 계약:

첫 번째 단계( 준비 ): 각 참가자는 로컬 트랜잭션을 실행하지만 커밋하지 않고 준비 상태에 들어가 코디네이터에게 준비되었음을 알립니다.

두 번째 단계(커밋) 코디네이터가 각 참가자가 준비되었음을 확인하면 참가자에게 커밋하도록 알리고 참가자 중 하나라도 실패하면 롤백 명령을 보내고 각 참가자는 롤백합니다.

질문:

단일 실패 지점: 트랜잭션 관리자가 실패하면 전체 시스템을 사용할 수 없습니다(참가자는 차단됨).

데이터 불일치: 2단계에서 트랜잭션 관리자가 커밋 메시지의 일부만 보내고 이때 네트워크가 비정상인 경우 일부 참가자만 커밋 메시지를 수신합니다. 즉, 일부 참가자만 트랜잭션을 제출하여 시스템 데이터가 일치하지 않습니다.

긴 응답 시간: 참가자와 코디네이터 리소스가 모두 잠겨 있으며 커밋 또는 롤백 후에만 해제할 수 있습니다.

불확실성: 공동 트랜잭션 관리자가 커밋을 보낸 후 현재 한 참가자만 커밋을 받은 다음 참가자와 트랜잭션 관리자가 동시에 다운되면 재선출된 트랜잭션 관리자는 메시지가 다음과 같은지 여부를 확인할 수 없습니다. 성공적으로 제출되었습니다.

3단계 프로토콜: 주로 2단계 최적화를 위해 2PC 단일 실패 지점 문제를 해결하지만 성능 문제와 불일치는 여전히 근본적으로 해결되지 않습니다.

참가자 차단 문제를 해결하기 위해 시간 초과 메커니즘 도입, 시간 초과 후 로컬 제출, 2pc만 코디네이터가 시간 초과 메커니즘을 가짐

첫 번째 단계: CanCommit 단계에서 코디네이터는 트랜잭션 참여자에게 트랜잭션을 완료할 수 있는지 여부를 묻습니다.

모두 예라고 대답하면 두 번째 단계로 들어갑니다.

有一个返回no或等待响应超时,则中断事务,并向所有参与者发送abort请求

第二阶段:PreCommit阶段,此时协调者会向所有的参与者发送PreCommit请求,参与者收到后开始执行事务操作。参与者执行完事务操作后(此时属于未提交事务的状态),就会向协调者反馈

“Ack”表示我已经准备好提交了,并等待协调者的下一步指令。

第三阶段:DoCommit阶段, 在阶段二中如果所有的参与者节点都返回了Ack,那么协调者就会从

“预提交状态”转变为“提交状态”。然后向所有的参与者节点发送"doCommit"请求,参与者节点在收到提交请求后就会各自执行事务提交操作,并向协调者节点反馈“Ack”消息,协调者收到所有参与者的Ack消息后完成事务。 相反,如果有一个参与者节点未完成PreCommit的反馈或者反馈超时,那么协调者都会向所有的参与者节点发送abort请求,从而中断事务。

TCC(补偿事务):Try、Confirm、Cancel

针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作

Try操作做业务检查及资源预留,Confirm做业务确认操作,Cancel实现一个与Try相反的操作既回滚操作。TM首先发起所有的分支事务的try操作,任何一个分支事务的try操作执行失败,TM将会发起所有分支事务的Cancel操作,若try操作全部成功,TM将会发起所有分支事务的Confirm操作,其中

Confirm/Cancel操作若执行失败,TM会进行重试。

TCC模型对业务的侵入性较强,改造的难度较大,每个操作都需要有 try、confirm、cancel三个接口实现

confirm 和 cancel 接口还必须实现幂等性。

消息队列的事务消息:

发送prepare消息到消息中间件发送成功后,执行本地事务

如果事务执行成功,则commit,消息中间件将消息下发至消费端(commit前,消息不会被消费)

如果事务执行失败,则回滚,消息中间件将这条prepare消息删除

소비자는 메시지를 받아 소비하며, 소비에 실패하면 계속해서 재시도한다.

인터페이스의 멱등성을 실현하는 방법

고유 아이디 각각의 오퍼레이션은 오퍼레이션과 내용에 따라 고유한 id를 생성하고 실행하기 전에 id의 존재 여부를 판단하여 존재하지 않는 경우 후속 오퍼레이션을 수행하여 데이터베이스나 redis에 저장한다.

서버는 토큰 전송을 위한 인터페이스를 제공하며, 비즈니스가 인터페이스를 호출하기 전에 먼저 토큰을 획득한 후 비즈니스 인터페이스 요청을 호출할 때 토큰을 넘겨주고, 서버는 토큰이 redis에 존재하는지 판단합니다. 첫 번째 요청을 의미하며 비즈니스를 계속 실행할 수 있습니다. 비즈니스가 완료된 후 redis의 토큰을 삭제해야 합니다.

중복 제거 테이블을 생성합니다. 중복 제거 테이블에 비즈니스 고유 식별자가 있는 필드를 저장하고, 테이블에 존재하면 버전 관리가 완료된 것입니다. 버전 번호를 높이십시오. 버전 번호가 일치하면 데이터를 업데이트할 수 있습니다.

상태 제어. 예를 들어 결제완료 상태의 주문이 결제완료 상태이고 결제 중 결제가 실패하여 미결제 상태일 경우 결제로 변경이 가능합니다.

ZAB 프로토콜에 대해 간단히 설명

ZAB 프로토콜은 충돌 복구를 지원하고 분산 데이터 일관성을 달성하기 위해 분산 조정 서비스 Zookeeper용으로 특별히 설계된 원자 브로드캐스트 프로토콜입니다.

모든 클라이언트 요청은 리더 프로세스에 기록된 다음 리더가 팔로워라고 하는 다른 노드와 동기화됩니다. 클러스터 데이터 동기화 과정에서 추종자 노드가 충돌하거나 리더 프로세스가 충돌하면 데이터 일관성을 보장하기 위해 Zab 프로토콜이 사용됩니다.

ZAB 프로토콜에는 크래시 복구와 메시지 브로드캐스트라는 두 가지 기본 모드가 있습니다.

메시지 방송:

클러스터 내의 모든 트랜잭션 요청은 Leader 노드에서 처리하고, 나머지 서버는 Follower이며, Leader는 클라이언트의 트랜잭션 요청을 트랜잭션 Proposal로 변환하여 클러스터 내 다른 모든 Follower에게 Proposal을 배포합니다.

브로드캐스트 완료 후 Leader는 Follower의 피드백을 기다리다가 Follower의 절반 이상이 피드백을 하면 클러스터 내 Follower에게 다시 Commit 메시지를 브로드캐스트합니다. 이전 제안.

리더 노드 쓰기는 2단계 작업으로 첫 번째 단계는 브로드캐스트 트랜잭션 작업이고 두 번째 단계는 브로드캐스트 제출 작업이며 그 중 절반 이상이 피드백 노드의 수 >=N/2+를 나타냅니다. 1, N은 모두 팔로워 노드 수입니다.

충돌 복구:

방금 시작할 때 클러스터 초기화

실패로 인한 리더 충돌

리더는 시스템 지원의 절반을 잃었고 클러스터의 절반 이상의 노드에서 연결이 끊겼습니다.

이때 새로운 Leader 선거가 시작되고, 선출된 Leader는 Follower의 절반 이상과 동기화하여 데이터의 일관성을 유지하며, 절반 이상의 머신과의 동기화가 완료되면 복구를 종료합니다. 모드를 입력하고 메시지 방송 모드로 들어갑니다.

전체 ZooKeeper 클러스터의 일관성 보장은 위의 두 상태 사이를 전환하는 것입니다.Leader 서비스가 정상인 경우 일반 메시지 브로드캐스트 모드이고, Leader가 사용할 수 없는 경우 충돌 복구 모드로 들어가고 데이터 동기화가 수행됩니다. 충돌 복구 단계 중에 수행됩니다. , 메시지 브로드캐스트 단계를 다시 입력하십시오.

Zxid는 Zab 프로토콜의 트랜잭션 번호입니다.Zxid는 64비트 숫자이며 하위 32비트는 단순 증가 카운터입니다. 클라이언트의 각 트랜잭션 요청에 대해 카운터는 1씩 증가하고 상위 32비트는 비트는 리더 주기 연령 번호를 나타냅니다.

리더 주기(epoch)는 현재 클러스터의 나이 또는 주기로 이해할 수 있습니다.새로운 리더 선출이 발생할 때마다 로컬 로그에 있는 큰 트랜잭션의 Zxid는 리더 서버에서 가져와서 읽습니다.epoch 값, 그런 다음 새 주기 ID로 1을 추가합니다. 상위 32비트는 각 Leader 세대의 고유성을 나타내고 하위 32비트는 각 Leader 세대의 트랜잭션 고유성을 나타냅니다.

zab 노드의 세 가지 상태:

따르다: 지도자의 명령에 따르다

선도 : 조정 업무를 담당

선거/보고: 선거 상태

zk의 데이터 모델 및 노드 유형

데이터 모델: 트리 구조

zk가 관리하는 데이터는 주로 클라이언트 세션(세션) 상태 및 데이터 노드(dataNode) 정보를 포함합니다.

zk는 메모리에 DataTree 데이터 구조를 구성하고 경로에서 dataNode로의 매핑과 dataNode 간의 트리와 같은 계층적 관계를 유지합니다. 읽기 성능을 향상시키기 위해 클러스터의 각 서비스 노드는 모든 데이터를 메모리에 저장합니다. 따라서 zk는 더 많이 읽고 덜 쓰고 가벼운 데이터를 사용하는 애플리케이션 시나리오에 적합합니다.

메모리에만 데이터를 저장하는 것은 안전하지 않습니다.ZK는 트랜잭션 로그 파일과 스냅샷 파일을 사용하여 데이터를 디스크에 저장하므로 데이터 손실 없이 빠르게 복구할 수 있습니다.

트리의 각 노드는 Znode라고 합니다.

Znode는 파일과 디렉토리의 특성을 모두 가지고 있습니다. 경로 식별, 데이터 저장 및 자식 Znode에 사용할 수 있습니다. 추가, 삭제, 수정 및 확인과 같은 작업이 있습니다.

Znode에는 원자성 작업이 있으며 읽기 작업은 노드와 관련된 모든 데이터를 가져오고 쓰기 작업은 노드의 모든 데이터를 대체합니다. 또한 각 노드에는 사용자의 권한을 지정하는 고유한 ACL(액세스 제어 목록)이 있습니다. 즉, 특정 사용자가 대상 노드에서 수행할 수 있는 작업을 제한합니다.

Znode 스토리지 데이터 크기는 제한되어 있습니다. 각 Znode의 데이터 크기는 최대 1M이며, 이는 정상적인 사용 시 이 값보다 훨씬 작아야 합니다.

Znode는 Unix의 파일 경로와 같이 경로로 참조됩니다. 경로는 절대 경로여야 하므로 슬래시 문자로 시작해야 합니다. 또한 고유해야 합니다. 즉, 각 경로에는 하나의 표현만 있으므로 이러한 경로를 변경할 수 없습니다. 존재하다

ZooKeeper에서 경로는 일부 제한 사항이 있는 유니코드 문자열로 구성됩니다. "/zookeeper" 문자열은 키 할당량 정보와 같은 관리 정보를 저장하는 데 사용됩니다.

영구 노드: 데이터 노드는 일단 생성되면 클라이언트와 노드를 생성한 서버 간의 세션이 종료되더라도 노드가 삭제되지 않고 항상 zk 서버에 저장됩니다.

임시 노드: 노드를 생성한 클라이언트 세션이 타임아웃 또는 예외로 인해 닫히면 그에 따라 노드도 zk에서 삭제됩니다.

정렬된 노드: 별도의 노드 유형이 아니라 영구 노드와 임시 노드를 기반으로 노드의 정렬된 특성이 추가됩니다.

zk의 이름 지정 서비스, 구성 관리 및 클러스터 관리에 대해 간략히 설명하십시오.

命名服务: 通过指定的名字来获取资源或者服务地址。Zookeeper可以创建一个全局唯一的路径,这个路径就可以作为一个名字。被命名的实体可以是集群中的机器,服务的地址,或者是远程的对象等。一些分布式服务框架(RPC、RMI)中的服务地址列表,通过使用命名服务,客户端应用能够根据特定的名字来获取资源的实体、服务地址和提供者信息等配置管理:

实际项目开发中,经常使用.properties或者xml需要配置很多信息,如数据库连接信息、fps地址端口等等。程序分布式部署时,如果把程序的这些配置信息保存在zk的znode节点下,当你要修改配置,即

znode会发生变化时,可以通过改变zk中某个目录节点的内容,利用watcher通知给各个客户端,从而更改配置。集群管理:

集群管理包括集群监控和集群控制,就是监控集群机器状态,剔除机器和加入机器。zookeeper可以方便集群机器的管理,它可以实时监控znode节点的变化,一旦发现有机器挂了,该机器就会与zk断开连接,对应的临时目录节点会被删除,其他所有机器都收到通知。新机器加入也是类似。

讲下Zookeeper watch机制

客户端,可以通过在znode上设置watch,实现实时监听znode的变化

Watch事件是一个一次性的触发器,当被设置了Watch的数据发生了改变的时候,则服务器将这个改变发送给设置了Watch的客户端

父节点的创建,修改,删除都会触发Watcher事件。

子节点的创建,删除会触发Watcher事件。

一次性:一旦被触发就会移除,再次使用需要重新注册,因为每次变动都需要通知所有客户端,一次性可以减轻压力,3.6.0默认持久递归,可以触发多次

轻量:只通知发生了事件,不会告知事件内容,减轻服务器和带宽压力

Watcher 机制包括三个角色:客户端线程、客户端的 WatchManager 以及 ZooKeeper 服务器

  1. 客户端向 ZooKeeper 服务器注册一个 Watcher 监听,

  2. 把这个监听信息存储到客户端的 WatchManager 中

  3. ZooKeeper의 노드가 변경되면 클라이언트에 알리고 클라이언트는 해당 Watcher 개체에서 콜백 메서드를 호출합니다. 시계 콜백은 직렬 동기식입니다.

zk와 유레카의 차이점

zk: CP 설계(강력한 일관성), 목표는 리소스의 통합 관리를 위한 분산 조정 시스템입니다.

노드 충돌 시 리더 선거가 필요하며 이 기간 동안 zk 서비스를 사용할 수 없습니다.

eureka: AP 설계(고가용성), 목표는 마이크로 서비스의 서비스 검색 등록에 특별히 사용되는 서비스 등록 검색 시스템입니다.

Eureka의 모든 노드는 동등하며 여러 노드의 장애는 일반 노드의 작업에 영향을 미치지 않으며 나머지 노드는 여전히 등록 및 쿼리 서비스를 제공할 수 있습니다. 단, 유레카 클라이언트는 특정 유레카로 등록 시 연결 실패를 발견하면 자동으로 다른 노드로 전환하게 되는데, 하나의 유레카가 있는 한 등록 서비스는 보장(가용성 보장)할 수 있지만, 찾은 정보가 새롭지 않을 수 있음(강력한 일관성을 보장하지 않음)

동시에 유레카 서버는 서비스의 85% 이상이 하트비트가 없다는 것을 알게 되면 네트워크에 문제가 있다고 생각하고

이러한 heartbeat-lost 서비스를 서비스 목록에서 삭제하면 eureka의 클라이언트도 서비스 정보를 캐시합니다. Eureka는 서비스 등록 검색에 아주 좋은 선택입니다.

스프링 클라우드와 Dubbo의 차이점

기본 프로토콜: springcloud는 http 프로토콜 기반, dubbo는 Tcp 프로토콜 기반으로 dubbo의 성능이 상대적으로 더 좋을 것으로 판단 등록 센터: Spring Cloud에서 사용하는 eureka, dubbo는 zookeeper 사용 권장

모델 정의: dubbo는 인터페이스를 서비스로 정의하고 SpringCloud는 애플리케이션을 서비스로 정의합니다.

SpringCloud는 생태학이고, Dubbo는 SpringCloud 생태계에서 서비스 호출을 위한 솔루션입니다(서비스 거버넌스).

히스트릭스란? 구현 메커니즘을 간략히 설명하십시오.

분산 내결함성 프레임워크

결함의 연쇄 반응을 방지하고, 퓨즈 빠른 고장을 실현하고, 정상적인 성능 저하를 실현 실시간 모니터링 및 경보 제공

리소스 격리: 스레드 격리, 세마포어 격리

스레드 격리: Hystrix는 각 명령에 별도의 스레드 풀을 할당하므로 단일 서비스 호출을 수행할 때 다른 스레드 풀에 영향을 주지 않고 독립적인 스레드 풀에서 수행할 수 있습니다. 종속 서비스인 경우 실제로 호출을 시작하려면 먼저 세마포어를 가져와야 합니다. 세마포어의 수에 제한이 있기 때문에 동시 요청 수가 세마포어 수를 초과하면 후속 요청은 바로 거부되고 폴백 프로세스에 들어갑니다. 세마포 격리는 주로 동시 요청의 양을 제어하고 요청 스레드가 넓은 영역에서 차단되는 것을 방지하여 현재 제한 및 눈사태 방지의 목적을 달성합니다.

회로 차단 및 성능 저하: 서비스 호출 실패 후 빠른 실패

휴즈는 비정상적인 비확산을 방지하고 시스템의 안정성을 확보하기 위한 것입니다.

다운그레이드: 호출 실패에 대한 수정 논리를 작성한 다음 서비스를 직접 중지하여 이러한 인터페이스를 정상적으로 호출할 수 없지만 직접 오류를 보고하지는 않지만 서비스 수준이 떨어집니다.

HystrixCommand 또는 HystrixObservableCommand를 통해 모든 외부 시스템(또는 종속성)을 래핑하면 전체 래퍼 개체가 단일 스레드에서 실행됩니다(이는 일반적인 명령 모드임).

제한 시간 요청은 정의된 임계값을 초과해야 합니다.

각 종속성에 대해 작은 스레드 풀(또는 세마포어)이 유지되며, 가득 차면 종속성의 요청이 대기하는 대신 즉시 거부됩니다.

성공, 실패(클라이언트에서 발생한 예외), 시간 초과 및 스레드 거부를 계산합니다.

회로 차단기를 열면 일정 기간 동안 특정 서비스에 대한 모든 요청이 중지되고 서비스의 오류 비율이 임계값을 초과하면 수동 또는 자동으로 회로 차단기가 닫힙니다.

요청이 거부되거나 연결 시간이 초과되거나 회로 차단기가 열리면 폴백 논리가 직접 실행됩니다.

거의 실시간으로 메트릭 및 구성 변경을 모니터링합니다.

Springcloud 핵심 구성 요소 및 기능

유레카: 서비스 등록 및 검색

등록: 각 서비스는 서비스의 IP 주소, 포트 번호, 버전 번호, 통신 프로토콜 등을 포함하여 제공하는 서비스의 메타데이터를 Eureka에 등록합니다. Eureka는 서비스 목록에서 각 서비스를 유지 관리합니다(이중 계층 맵, 첫 번째 수준 키는 서비스 이름, 두 번째 수준 키는 인스턴스 이름, 값은 서비스 주소와 포트임). 동시에 서비스에 대한 하트비트는 유지되고 사용 불가능한 서비스는 제거됩니다.eureka 클러스터의 각 노드는 서로 등록되며 각 인스턴스는 동일한 서비스 목록을 가집니다.

发现:eureka注册的服务之间调用不需要指定服务地址,而是通过服务名向注册中心咨询,并获取所有服务实例清单(缓存到本地),然后实现服务的请求访问。

Ribbon:服务间发起请求的时候,基于Ribbon做负载均衡,从⼀个服务的多台机器中选择⼀台 (被调用方的服务地址有多个),Ribbon也是通过发起http请求,来进行的调用,只不过是通过调用服务名的地址来实现的。虽然说Ribbon不用去具体请求服务实例的ip地址或域名了,但是每调用一个接口都还要手动去发起Http请求

Feign:基于Feign的动态代理机制,根据注解和选择的机器,拼接请求URL地址,发起请求 ,简化服务间的调用,在Ribbon的基础上进行了进一步的封装。单独抽出了一个组件,就是Spring Cloud Feign。在引入Spring Cloud Feign后,我们只需要创建一个接口并用注解的方式来配置它,即可完成对服务提供方的接口绑定。

调用远程就像调用本地服务一样

Hystrix:发起请求是通过Hystrix的线程池来⾛的,不同的服务⾛不同的线程池,实现了不同服务调⽤的隔离,通过统计接口超时次数返回默认值,实现服务熔断和降级

Zuul:如果前端、移动端要调⽤后端系统,统⼀从Zuul⽹关进⼊,由Zuul⽹关转发请求给对应的服务,通过与Eureka进行整合,将自身注册为Eureka下的应用,从Eureka下获取所有服务的实例,来进行服务的路由。Zuul还提供了一套过滤器机制,开发者可以自己指定哪些规则的请求需要执行校验逻辑,只有通过校验逻辑的请求才会被路由到具体服务实例上,否则返回错误提示。

Dubbo 的整体架构设计及分层

五个角色:

注册中心registry:服务注册与发现服务提供者provider:暴露服务服务消费者consumer:调用远程服务

监控中心monitor:统计服务的调用次数和调用时间容器container:服务允许容器调用流程:

1:container容器负责启动、加载、运行provider

2: 공급자가 시작할 때 제공하는 서비스를 등록 센터에 등록합니다.

3: 소비자가 시작할 때 필요한 서비스를 등록 센터에 등록합니다.

4: 레지스트리는 서비스 공급자 목록을 소비자에게 반환합니다. 변경 사항이 있는 경우 레지스트리는 긴 연결을 기반으로 변경된 데이터를 소비자에게 푸시합니다.

소비자

5: 소비자는 공급자 서비스를 호출하고 로드 밸런싱 알고리즘을 기반으로 호출합니다.

6: 짧은 링크 타이밍을 기반으로 공급자를 호출하는 소비자의 통계는 모니터 계층에 대해 분당 한 번 계산됩니다.

인터페이스 서비스 계층(Service): 개발자용, 비즈니스 코드, 인터페이스, 구현 등

구성 계층(Config): ServiceConfig 및 ReferenceConfig를 중심으로 하는 외부 구성 인터페이스

서비스 프록시 계층(프록시): 생산자, 소비자 및 더보를 위해 프록시 클래스가 생성되어 호출 세부 정보를 캡슐화하며 비즈니스 계층은 원격 호출에 대한 감각이 없습니다.

서비스 등록 레이어(레지스트리): 서비스 URL을 중심으로 서비스 주소 등록 및 탐색을 캡슐화 라우팅 레이어(클러스터): 여러 공급자의 라우팅 및 로드 밸런싱을 캡슐화하고 레지스트리 모니터링 레이어 연결(모니터): RPC 개수 통화 및 통화 시간 모니터링

원격 호출 계층(Protocal): RPC 호출을 캡슐화합니다.

정보 교환 계층(Exchange): 캡슐화 요청 응답 모드, 동기식에서 비동기식으로

네트워크 전송 계층(Transport): 통합 인터페이스로서의 추상 미나 및 네티, 통합 네트워크 전송 인터페이스 데이터 직렬화 계층(Serialize): 데이터 전송의 직렬화 및 역직렬화

MQ

Queue: RabbitMQ의 내부 개체인 Queue는 메시지를 저장하는 데 사용됩니다. RabbitMQ의 메시지는 대기열에만 저장할 수 있습니다. 생산자는 메시지를 대기열에 게시하고 소비자는 대기열에서 메시지를 가져와 소비합니다. 여러 소비자가 동일한 큐에 가입할 수 있습니다. 이때 각 소비자가 소비를 위해 모든 메시지를 받는 대신 큐의 메시지가 소비를 위해 여러 소비자에게 균등하게 배포(폴링)됩니다. (참고: RabbitMQ는 대기열 수준에서 브로드캐스트 소비를 지원하지 않습니다. 브로드캐스트 소비가 필요한 경우 스위치를 사용하여 라우팅 키를 통해 여러 대기열을 바인딩할 수 있으며 여러 소비자가 이러한 대기열을 구독할 수 있습니다.

교환: 교환. 생산자는 메시지를 하나 이상의 대기열로 라우팅하는 Exchange로 메시지를 보냅니다. 경로가 실패하면 생산자에게 반환하거나 직접 폐기하거나 다른 처리를 수행하십시오.

RoutingKey: 라우팅 키. 생성자가 교환기에 메시지를 보낼 때 일반적으로 메시지에 대한 라우팅 규칙을 지정하기 위해 RoutingKey를 지정합니다. 이 라우팅 키는 스위치 유형 및 바인딩 키(BindingKey)와 함께 사용해야 평생 유효합니다.

교환 유형과 바인딩 키가 고정되면 생산자는 메시지를 교환기에 보낼 때 RoutingKey를 지정하여 메시지가 흐르는 위치를 결정할 수 있습니다.

바인딩(Binding): 스위치와 큐는 바인딩을 통해 연결되며, 바인딩 시 일반적으로 바인딩 키를 지정하여 RabbitMQ가 큐에 올바르게 라우팅하는 방법을 지정할 수 있습니다.

교환 및 대기열은 실제로 다대다 관계입니다. 관계형 데이터베이스의 두 테이블과 같습니다. BindingKey(다대다 관계 테이블)를 통해 연결됩니다. 메시지를 전달할 때 Exchange 및 RoutingKey(BindingKey에 해당)를 통해 해당 큐를 찾을 수 있습니다.

채널: 채널은 Connection에서 설정된 가상 연결입니다. 애플리케이션이 Rabbit Broker와 TCP 연결을 설정하면 클라이언트는 AMQP 채널(채널)을 생성할 수 있으며 각 채널에는 고유한 D가 할당됩니다. RabbitMQ에서 처리하는 모든 AMQP 명령은 채널을 통해 수행됩니다. 채널은 케이블의 섬유 다발과 같습니다. 단일 케이블에는 많은 광섬유 가닥이 포함되어 있어 모든 연결이 여러 가닥을 통해 전송 및 수신될 수 있습니다.

RabbitMQ는 메시지 전달을 어떻게 보장합니까? 메시지 받음?

발신자 확인 메커니즘:

수신자 확인 메커니즘:

소비자가 대기열을 선언할 때 noAck 매개변수를 지정할 수 있습니다.noAck=false인 경우 RabbitMQ는 메모리(또는 디스크, 영구 메시지)에서 메시지를 제거하기 전에 소비자가 명시적으로 ack 신호를 다시 보낼 때까지 기다립니다. 그렇지 않으면 메시지는 사용 후 즉시 삭제됩니다.

소비자는 각 메시지를 받은 후 확인해야 합니다(메시지 수신과 메시지 확인은 서로 다른 작업입니다). 소비자가 메시지를 확인한 경우에만

RabbitMQ는 대기열에서 메시지를 안전하게 삭제할 수 있습니다.

RabbitMQ는 확인되지 않은 메시지에 대해 시간 초과 기간을 설정하지 않습니다. 메시지를 소비자에게 다시 전달해야 하는지 여부를 판단하는 유일한 기준은 메시지를 소비하는 소비자 연결이 끊어졌는지 여부입니다. 이 디자인의 이유는 RabbitMQ가 소비자가 오랫동안 메시지를 사용할 수 있도록 하기 때문입니다. 데이터의 최종 일관성을 보장합니다.

소비자가 ack를 반환하기 전에 연결을 끊으면 RabbitMQ는 구독한 다음 소비자에게 재배포합니다. (중복 제거가 필요한 메시지를 반복적으로 사용하는 숨겨진 위험이 있을 수 있음)

RabbitMQ 트랜잭션 메시지

채널 설정으로 실현

  1. channel.txSelect(); 트랜잭션 모드를 활성화하도록 서버에 알립니다. 서버는 Tx.Select-Ok를 반환합니다.

  2. channel.basicPublish; 메시지 보내기, 여러 개일 수 있음, ack를 제출하기 위해 메시지를 소비할 수 있음

  3. channel.txCommit() 트랜잭션을 커밋합니다.

  4. channel.txRollback()은 트랜잭션을 롤백하고 소비자는 트랜잭션을 소비합니다.

  5. autoAck=false, 트랜잭션 커밋 또는 롤백에 따라 수동으로 ack를 제출합니다.

  6. autoAck=true, 트랜잭션을 지원하지 않습니다. 즉, 메시지를 받은 후 트랜잭션을 롤백하더라도 도움이 되지 않습니다. 큐에서 메시지를 제거했습니다.

링크에 문제가 있으면 IoException이 발생하고 사용자는 예외를 가로채 트랜잭션을 롤백하거나 메시지를 반복할지 여부를 결정할 수 있습니다.

트랜잭션 메시지는 rabbitmq의 성능을 저하시킵니다.

RabbitMQ 데드 레터 큐, 지연 큐

  1. 메시지는 channel.basicNack 또는 channel.basicReject를 사용하여 소비자에 의해 부정적으로 승인되며 이때 requeue 속성은 false로 설정됩니다.

  2. 대기열에서 메시지의 생존 시간이 설정된 TTL 시간을 초과합니다.

  3. 메시지 대기열의 메시지 수가 최대 대기열 길이를 초과했습니다.

그러면 메시지가 "데드 레터"가 됩니다. "데드 레터" 메시지는 RabbitMQ에서 특별히 처리합니다. 데드 레터 큐 정보가 구성되면 메시지가 데드 레터 큐에 던져지고 구성되지 않으면 메시지가 삭제됩니다.

데드 레터를 사용해야 하는 각 비즈니스 큐에 대한 데드 레터 스위치를 구성합니다.여기서 동일한 프로젝트의 데드 레터 스위치는 하나를 공유한 다음 각 비즈니스 큐에 별도의 라우팅 키를 할당할 수 있습니다.데드 레터 큐는 데드 레터 교환 대기열, 데드 레터 교환

기계는 특별한 스위치가 아니라 데드레터를 받는데 사용하는 스위치일 뿐이니 어떤 종류든 가능합니다 [직접,

팬아웃, 주제]

TTL: 메시지 또는 큐에 있는 모든 메시지의 최대 수명

메시지에 TTL 속성이 설정되어 있거나 TTL 속성이 설정된 상태로 대기열에 들어가면 메시지가 TTL에서 설정한 시간 내에 소비되지 않으면 "데드 레터"가 됩니다. 대기열 TTL과 메시지 TTL이 모두 구성된 경우 더 작은 값이 사용됩니다.

소비자만 배달 못한 편지 대기열의 메시지를 계속 소비하면 됩니다.

RabbitMQ 미러 큐 메커니즘

미러 큐에는 마스터 노드와 슬레이브 노드가 있습니다. 마스터와 슬레이브는 모든 큐의 마스터인 노드와 슬레이브인 다른 노드 대신 큐를 위한 것입니다. 큐에 의해 처음 생성되는 노드가 마스터 노드이고 나머지 노드는 슬레이브 노드입니다.

클라이언트의 요청이 마스터 또는 슬레이브에 도달하는지 여부에 관계없이 최종 데이터는 마스터 노드에서 가져옵니다. 요청이 마스터 노드에 도달하면 마스터 노드는 메시지를 클라이언트에 직접 반환하고 마스터 노드는 GM(Guaranteed Multicast) 프로토콜을 통해 슬레이브 노드에 대기열의 새로운 상태를 브로드캐스트합니다. GM은 브로드캐스트 메시지의 원자성, 즉 모든 업데이트 또는 없음을 보장합니다.

요청이 슬레이브 노드에 도달하면 슬레이브 노드는 먼저 요청을 마스터 노드로 리디렉션해야 하며 마스터 노드는 메시지를 클라이언트에 반환하고 마스터 노드는 다음을 통해 슬레이브 노드에 대기열의 새로운 상태를 브로드캐스트합니다. GM 프로토콜.

새 노드가 가입하면 RabbitMQ는 이전 기록 데이터를 동기화하지 않으며 새 노드는 노드가 클러스터에 가입한 후에 추가된 새 메시지만 복사합니다.

kafka 아키텍처 설계에 대해 간단히 설명

소비자 그룹: 소비자 그룹, 소비자 그룹의 각 소비자는 소비 용량을 향상시키기 위해 서로 다른 파티션의 데이터 소비를 담당합니다. 논리적으로 가입자입니다.

주제: 큐로 이해할 수 있습니다. 주제는 메시지를 분류합니다. 생산자와 소비자는 동일한 주제에 직면합니다.

Partition: 확장성과 동시성 향상을 위해 하나의 Topic이 여러 Partition의 형태로 여러 Broker에 배포됩니다.

위에서 각 파티션은 순서가 지정된 대기열입니다. 주제의 각 파티션에는 여러 복사본(Replica)이 있습니다.

지도자와 여러 추종자. 생산자가 데이터를 보내는 개체와 소비자가 데이터를 소비하는 개체는 모두 리더입니다. Follower는 Leader의 데이터를 실시간으로 동기화하고 Leader 데이터와의 동기화를 유지하는 역할을 합니다. 리더가 실패하면

팔로워도 새로운 리더가 됩니다.

오프셋: 소비자 소비 위치 정보, 데이터 소비 위치를 모니터링하고 소비자가 전화를 끊었다가 재개하면 소비 위치에서 계속 소비할 수 있습니다.

Zookeeper: Kafka 클러스터가 제대로 작동하려면 Kafka가 클러스터 정보를 저장하고 관리하는 데 도움이 되는 Zookeeper에 의존해야 합니다.

Kafka는 메시지 순서, 반복 전송, 반복 사용 및 메시지 손실을 어떻게 처리합니까?

Kafka는 어떤 상황에서 메시지를 잃어버리고 해결합니까?

  1. 문자 보내

  2. 소비

  3. 브로커의 브러시 플레이트는 브러시 플레이트 간격을 줄입니다.

카프카는 풀? 푸시? 장점과 단점 분석

풀 모드:

데이터 풀은 소비자의 소비 능력에 따라 이루어지며 속도 조절 가능

배치로 가져오거나 개별적으로 가져올 수 있습니다.다른 제출 방법을 설정하여 다른 전송 의미론을 달성할 수 있습니다.단점: Kafka에 데이터가 없으면 소비자에서 빈 루프가 발생하고 리소스를 소비합니다.해결책: 매개변수 설정을 통해, 소비자가 가져온 데이터가 비어 있거나 일정량에 도달하지 않으면 차단됩니다.

푸시 모드: 소비자가 루프에서 기다리지 않습니다. 단점: 속도가 고정되어 소비자의 소비 능력을 무시하여 서비스 거부 또는 네트워크 정체 등으로 이어질 수 있습니다.

Kafka에서 zk의 역할

/brokers/ids: 임시 노드, 모든 브로커 노드 정보 저장, 브로커 물리적 주소, 버전 정보, 시작 시간 등 저장, 노드 이름은 brokerID, 브로커는 정기적으로 zk에 하트비트를 전송, 연결이 끊어지면 brokerID가 삭제됨

/brokers/topics: 임시 노드, 노드는 브로커 노드 아래에 모든 주제 정보를 저장하고 각 주제 노드에는 고정 파티션 노드가 포함되며 파티션의 하위 노드는 주제 파티션이며 각 파티션은 상태 노드를 저장하고 현재 리더 파티션을 저장합니다. 와 ISR의 brokerID, 상태 노드는 리더에 의해 생성되며, 리더가 다운되면 새 리더가 선출되고 상태 노드가 재생성될 때까지 노드가 삭제됩니다.

/consumers/[group_id]/owners/[topic]/[broker_id-partition_id]: 소비자와 파티션 간의 등록 관계 유지

/consumers/[group_id]/offsets/[topic]/[broker_id-partition_id]: 파티션 메시지의 소비 진행 오프셋

클라이언트는 토픽을 통해 토픽 트리 아래의 상태 노드를 찾아 리더의 브로커 ID를 얻고 브로커 트리에서 브로커의 물리적 주소를 찾지만 클라이언트는 zk에 직접 연결하지 않고 정보를 얻는다. 구성된 브로커를 통해 zk에서

kafka의 재조정 메커니즘에 대해 간략하게 설명

소비자 그룹의 소비자와 주제 아래의 파티션을 다시 일치시키는 프로세스는 언제 재조정을 생성합니까?

소비자 그룹의 구성원 수가 변경됨 소비자 소비 제한 시간이 변경됨 그룹에서 구독하는 항목의 수가 변경됨 그룹에서 구독하는 항목 파티션의 수가 변경됨 코디네이터: 일반적으로 파티션의 리더 노드가 있는 브로커 , 그룹 내 소비자의 생존을 모니터링하는 역할을 담당하며, 코디네이터의 심장 박동을 유지하고 소비자의 소비 시간 제한을 판단합니다.

코디네이터는 하트비트 리턴을 통해 컨슈머에게 리밸런싱을 알립니다.

컨슈머는 코디네이터에게 그룹 가입을 요청하고, 코디네이터는 리더 컨슈머를 선출하며, 리더 컨슈머는 코디네이터로부터 모든 컨슈머를 얻어 코디네이터에게 syncGroup(할당 정보)을 보낸다.

코디네이터는 리밸런싱을 완료하기 위해 하트비트 메커니즘을 통해 syncGroup을 컨슈머에게 전송하고, 리더 컨슈머는 주제 변경을 모니터링하고 리밸런싱을 트리거하도록 코디네이터에게 알립니다.

C1이 메시지를 초과 사용하면 재조정이 발생하고 재할당 후 다른 소비자가 메시지를 소비하게 되는데 이때 C1이 오프셋을 소비하여 제출하여 오류 발생

솔루션: 코디네이터가 균형을 재조정할 때마다 세대를 표시하고 소비자에게 제공합니다.

Generation은 +1이 되며 Consumer가 offset을 제출하면 Coordinator는 이를 Generation과 비교하여 일치하지 않는 경우 제출을 거부합니다.

Kafka의 성능은 어디에 좋은가요?

Kafka는 메모리를 기반으로 하지 않고 하드디스크 저장공간이기 때문에 메시지를 축적하는 능력이 더 강하다.

순차적 쓰기: 디스크의 순차적 액세스 속도는 메모리에 근접할 수 있습니다.Kafka의 메시지는 모두 추가 작업이며 파티션이 정렬되어 디스크 탐색 시간을 절약함과 동시에 쓰기 횟수를 절약합니다. 배치 작업을 통해 쉽게 삭제할 수 있도록 파티션을 물리적으로 다중 세그먼트 저장소로 나눕니다.

전통:

커널 버퍼에 디스크 파일 데이터 읽기, 커널 버퍼에 있는 데이터를 사용자 버퍼에 복사, 사용자 버퍼에 있는 데이터를 소켓의 송신 버퍼에 복사, 소켓의 송신 버퍼에 있는 데이터를 네트워크로 송신 제로 카피 전송을 수행합니다.

운영 체제의 명령 지원을 사용하여 전송을 위해 커널 버퍼의 데이터를 네트워크 카드로 직접 전송

Kafka는 jvm에 크게 의존하지 않는데 주로 운영 체제의 pagecache 때문입니다.

끝 (투표)

 

Guess you like

Origin blog.csdn.net/m0_63947499/article/details/127218727