个人总结的java2023常见面试题和简易回答总结

文章目录

一:java基础

😄1. JDK 和 JRE 有什么区别?

具体来说 JDK 其实包含了 JRE,同时还包含了编译 java 源码的编译器 javac,简单来说:如果你需要运行 java 程序,只需安装 JRE 就可以了,如果你需要编写 java 程序,需要安装 JDK。

😄2. == 和 equals 的区别是什么?

对于基本类型来说比较的是值,对于引用类型来说是比较的是引用;而 equals 默认情况下是引用比较,只是很多类重写了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。

😄3. 两个对象的 hashCode()相同,则 equals()也一定为 true,对吗?

不对,hashCode() 方法仅仅是返回对象的哈希码,而equals() 方法应该判断对象的各个属性值是否相等,保证两个对象在所有属性值都相等的情况下才返回 true,而不仅仅只是判断哈希码是否相等。

😄4. final 在 java 中有什么作用?

  • final 修饰的类叫最终类,该类不能被继承。
  • final 修饰的方法不能被重写。
  • final 修饰的变量叫常量,常量必须初始化,初始化之后值就不能被修改。

😄5. java 中的 Math.round(-1.5) 等于多少?

等于 -1,因为在数轴上取值时,中间值(0.5)向右取整,所以正 0.5 是往上取整,负 0.5 是直接舍弃。

😄6. String 属于基础的数据类型吗?

String 不属于基础类型,基础类型有 8 种:byte、boolean、char、short、int、float、long、double,而 String 属于对象。

😄7. java 中操作字符串都有哪些类?它们之间有什么区别?

操作字符串的类有:String、StringBuffer、StringBuilder。

String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。

StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。

😄8. String str="i"与 String str=new String(“i”)一样吗?

不一样,因为内存的分配方式不一样。String str="i"的方式,java 虚拟机会将其分配到常量池中;而 String str=new String(“i”) 则会被分到堆内存中。

😄9. 如何将字符串反转?

使用 StringBuilder 或者 stringBuffer 的 reverse() 方法。

😄10. String 类的常用方法都有那些?

  • trim():去除字符串两端空白。

  • split():分割字符串,返回一个分割后的字符串数组。

  • length():返回字符串长度。

  • equals():字符串比较。

  • getBytes():返回字符串的 byte 类型数组。

😄11. 抽象类必须要有抽象方法吗?

不需要,抽象类不一定非要有抽象方法。

😄12. 普通类和抽象类有哪些区别?

  • 普通类不能包含抽象方法,抽象类可以包含抽象方法。
  • 抽象类不能直接实例化,普通类可以直接实例化。

😄15. java 中 IO 流分为几种?

按功能来分:输入流(input)、输出流(output)。

按类型来分:字节流和字符流。

字节流和字符流的区别是:字节流按 8 位传输以字节为单位输入输出数据,字符流按 16 位传输以字符为单位输入输出数据。

😄16. BIO、NIO、AIO 有什么区别?

BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。

😄17.什么是重载(Overload)和重写(Override) ?

重载:发生在同一个类中,方法名相同参数列表不同,与方法返回值和访问修饰符无关,即重载的方法不能根据返回类型进行区分

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

😄18.什么是反射机制?

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

😄19.反射机制优缺点

优点: 运行期类型的判断,动态加载类,提高代码灵活度。

缺点:Java反射机制比较耗时,会降低程序的运行效率,反射机制较为复杂,需要熟悉相关的API,并且在安全性上也存在一定的问题

😄20.在你进行项目开发的过程中有没有用到过反射

在我们的项目中经常会使用反射 + 自定义注解的方式去实现一些功能

1.在前后端交互的时候, 后端Long类型返回前端后会产生精度丢失 , 我们的处理方式就是在服务端, 通过配置修改Jackson的序列化规则, 将一些Long类型字段转化为字符串返回给前端, 这个时候我们自定义了一个@IdEncrpt注解 , 通过反射获取类的属性, 判断属性上是否添加了@IdEncrpt注解, 如果添加了 , 就会通过反射获取属性值, 转化为字符串

2.在我们项目开发中经常使用的一些框架, 例如 : Mybatis , Spring , SpringMVC 等, 以及一些常用的工具库都大量使用到了反射机制

😄21.java常见的集合类有哪些

1.Collection接口的子接口包括:Set接口和List接口

2.Map接口的实现类主要有:HashMap、TreeMap、Hashtable等

3.Set接口的实现类主要有:HashSet、TreeSet、LinkedHashSet等

4.List接口的实现类主要有:ArrayList、LinkedList、Vector等

其中Vector和HashTable是线程安全的,但是已经不推荐使用了

😄22.ArrayList 和 LinkedList 的区别是什么?

1.数据结构:ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。

2.随机访问效率:ArrayList 比 LinkedList 在随机访问时的效率要高,因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。

3.增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响数组内的其他数据的下标。

并且他们都不是线程安全的

😄23.说一下HashMap的实现原理?

HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。

HashMap 基于 Hash 算法实现的 :

​ 1.当我们往HashMap中put元素时,利用key的hashCode重新通过hash算法计算出当前对象的元素在数组中的下标

​ 2.存储时,如果出现hash值相同的key,此时有两种情况。

​ 1.如果key相同,则覆盖原始值;

​ 2.如果key不同(出现冲突),则将当前的key-value放入链表中

​ 3.获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值。

HashMap JDK1.8之前

​ 采用的是拉链法,也就是将链表和数组结合,床架你一个链表数组,数组中每一格就是一个链表,如果遇到哈希冲突,就会将冲突的值加入到链表中

JDK1.8之后

​ 相比于之前的版本,jdk1.8在解决哈希冲突时有了较大的变化,当链表长度大于阈值8的时候,将链表转化为红黑树,以减少搜索时间。

😄24.讲一讲HashMap的扩容机制

  1. 哈希表初始化:创建一个空桶数组,其长度为2的幂次方。

  2. 插入新的键值对:将新的键值对插入哈希表。如果键已经存在,那么会更新对应键的值。

  3. 检查负载因子:计算当前哈希表中键值对的数量与桶数组长度的比值(即负载因子)。如果负载因子大于指定的阈值(默认为0.75),则进行扩容操作。

  4. 扩容:新建一个长度为当前桶数组长度2倍的桶数组,并将原桶数组中的元素重新映射到新数组中。

  5. 重新哈希:将扩容后的新桶数组中的元素重新计算哈希值,然后插入到新的桶中

😄25.创建线程的四种方式

  1. 继承 Thread 类;

  2. 实现 Runnable 接口;

  3. 实现 Callable 接口;

  4. 使用匿名内部类方式

😄26.runnable 和 callable 有什么区别

  • Runnable 接口 run 方法无返回值;Callable 接口 call 方法有返回值,是个泛型
  • Runnable 接口 run 方法只能抛出运行时异常,且无法捕获处理;Callable 接口 call 方法允许抛出 异常,可以获取异常信息

😄27.加锁的方式有哪些 ?

使用synchronized关键字

使用Lock锁

synchronized和Lock有什么区别 ?

首先synchronized是Java内置关键字,在JVM层面,Lock是个Java类;

synchronized 可以给类、方法、代码块加锁;而 lock 只能给代码块加锁。

synchronized 不需要手动获取锁和释放锁,使用简单,发生异常会自动释放锁,不会造成死锁; 而 lock 需要自己加锁和释放锁,如果使用不当没有 unLock()去释放锁就会造成死锁。

😄28.如果你提交任务时,线程池队列已满,这时会发生什么

有两种情况把

1.如果使用的是无界队列的话,那么没有关系,会继续添加任务到 阻塞队列中等待执行。

2.如果使用的是有界队列,那么就可能拒绝已经处理满了的任务

😄29.在你们的项目中有没有使用到线程池

我们的项目中很多地方使用了线程池 , 使用的场景经常有如下几种情况

比如说业务层处理分多个业务线 , 多条业务线的优先级有高有低 , 我们会使用异步线程池执行优先级较低的业务

比如: 搜索历史记录的异步保存 , 用户行为数据的异步入库

😄30.你了解的线程池的种类有哪些 ?

  1. newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回 收空闲线程,若无可回收,则新建线程。

  2. newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列 中等待。

  3. newScheduledThreadPool 创建一个周期性线程池,支持定时及周期性任务执行。

  4. newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任 务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

😄31.线程池的核心参数有哪些 ?

  1. 核心线程数(corePoolSize):线程池中的常驻线程数,即在没有任务时也会保持存活的线程数量。

  2. 最大线程数(maximumPoolSize):线程池中允许的最大线程数,当任务数量超过核心线程数时,线程池会创建新的线程来处理任务,但不会超过最大线程数。

  3. 空闲线程存活时间(keepAliveTime):当线程池中的线程数量超过核心线程数时,空闲线程在被回收之前等待新任务的最长时间。

  4. 队列容量(workQueue):线程池中的任务队列,用于存放等待执行的任务,当任务数量超过核心线程数时,新的任务将被放入队列中等待执行。

  5. 线程工厂(threadFactory):用于创建新线程的工厂对象。

  6. 饱和策略(handler):当线程池队列和线程池都达到限制时,处理新任务的策略,常用的策略有抛出异常、丢弃任务、丢弃队列中最早的任务和将任务交给调用者线程来执行等。

😄32.你们项目中使用线程池, 核心线程数如何配置 ?

  1. IO密集型任务 : 核心线程数的数量 约等于 CPU核心数 * 2-3倍

  2. 计算密集型任务 : 核心线程数 约等于 CPU核心数+1

😄33.线程池的执行原理

提交一个任务到线程池中,线程池的处理流程如下:

  1. 判断线程池里的核心线程是否都在执行任务,如果不是则创建一个新的工作线程来执行任务。如果核心线程都在执行任务,则进入下个 流程。

  2. 线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队 列里。如果工作队列满了,则进入下个流程。

  3. 判断线程池里的线程是否都处于工作状态,如果没有,则创建一个新的工作线程来执行任 务。如果已经满了,则交给饱和策略来处理这个任务。

😄34.新建 T1、T2、T3 三个线程,如何保证它们按顺序执行?

1.我们可以使用join()方法:比如在T1线程中通过调用T2.join()方法,然后在T2线程中又调用T3的join方法,这样可以确保三个线程按顺序执行

2.我们也可以使用wait()和notify()方法:在每个线程的run()方法中,使用synchronized(lock)获取同步锁,然后通过wait()方法等待前一个线程执行完毕并唤醒下一个线程。

二:JVM

😄35…jvm的作用

  • jvm其实就是java虚拟机,它的作用其实就是执行java字节码,过程就是通过编译器把java代码翻译成字节码,然后类加载器把字节码加载到内存中,将其存放到运行时数据区的方法区中,但是底层操作系统并不能直接运行这个字节码,然后需要特定的执行引擎来将字节码翻译成底层系统指令,再交由CPU去执行,这就是jvm的执行流程.

😄36.JVM的组成部分

主要有①类加载器,②运行时数据区,③执行引擎,①类加载器主要负责从文件系统或网络中加载字节码文件,并将其转换为可执行代码。②用于存放程序运行时所需要的数据,包括方法区、堆、栈、本地方法栈和程序计数器等。其中堆是最大的运行时数据区,用于存放对象实例和数组,并且在JVM启动时就已经确定了其大小。③负责执行java字节码,将其翻译成机器码执行

😄37.说一下 JVM 运行时数据区

Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域,这些区域都有各自的用途,以及创建和销毁的时间,主要被划分为这几个区域,程序计数器,java虚拟机栈,本地方法栈,java堆和方法区

  • 程序计数器:主要用来跟踪当前线程执行的环境,即当前指令的地址,当程序需要暂停执行时,可以将下一条执行指令位置保存到程序计数器中,等到线程恢复执行后再从相应位置继续执行。
  • Java 虚拟机栈:每个方法在执行的同时都会在Java 虚拟机栈中创 建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息; 栈帧就是Java虚拟机栈中的下一个单位。
  • **本地方法栈:**与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java 方法的,而本地方法栈是为虚拟机调用 Native 方法服务的; Native 方法的源码大部分都是 C和C++ 的代码
  • Java 堆(Java Heap):Java 虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实例都在这里分配内存
  • 方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的 代码等数据。

😄37:堆栈的区别是什么?

  1. 分配方式:堆内存空间是通过Java虚拟机动态分配的,而栈空间则是在编译器静态分配的。
  2. 空间大小:堆的内存空间一般比栈大。堆的大小只受限于操作系统能给出的内存大小,而栈的大小则一般在几MB的数量级。
  3. 存储内容:堆主要用于存储Java对象,具有较强的动态扩展性,而栈主要用于存储局部变量,具有较快的访问速度和更简洁的内存布局。
  4. 内存的回收方式:堆采用垃圾回收的方式进行内存的回收,栈则采用自动弹栈的方式进行内存回收。

😄38.什么是类加载器,类加载器有哪些?

主要有一下四种类加载器:

  1. 启动类加载器用来加载java核心类库,无法被java程序直接引用。
  2. 扩展类加载器:它用来加载 Java 的扩展库。
  3. 系统类加载器:它根据 Java 应用的类路径来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。
  4. 用户自定义类加载器,通过继承 java.lang.ClassLoader类的方式实现

😄 39.什么是双亲委派模型

双亲委派模型:如果一个类加载器收到了类加载的请求,它首先不会自己去加载这个类,而是把这个请求委派给父类加载器去完成,每一层的类加载器都是如此,这样所有的加载请求都会被传送到 顶层的启动类加载器中,只有当父加载无法完成加载请求时, 子加载器才会尝试去加载类。

总结就是: 当一个类收到了类加载请求时,不会自己先去加载这个类,而是将其委派给父类,由父类去加 载,如果此时父类不能加载,反馈给子类,由子类去完成类的加载。

😄40.java内存泄漏

内存泄漏是指不再被使用的对象或者变量一直占据在内存中,严格来说,只有对象不在被程序用到了,但是GC又不能回收他们的情况,才叫内存泄漏。理论上来说有java有GC机制,但是依然会存在内存泄漏的情况,原因也很明确,比如长生命周期的对象持有短生命周期的引用,就很可能发生内存泄漏。

😄41.四种引用

  • 强引用:强引用是我们使用最广泛的引用,如果一个对象具有强引用,那么垃圾回收期绝对不会回收它,当内存空间不足时,垃圾回收器宁愿抛出OutOfMemoryError,也不会回收具有强引用的对象,比如new出一个实例
  • 软引用:描述一些有用但不是必须的对象,当一个对象只有一个软引用,只有当内存不足时,才会回收它;
  • 弱引用:描述一些可有可无的对象,不管内存够不够都会被回收
  • 虚引用:虚引用就是一种可有可无的引用,无法用来表示对象的生命周期,任何时候都可能被回收,主要用来跟踪对象被垃圾回收的活动,跟其他两种引用区别在与:虚引用必须跟引用队列联合使用,如果发现一个对象只有虚引用,那么就会将这个对象加入到引用队列中,程序可以通过引用队列中是否加入的虚引用,来了解被引用的对象是否需要被进行垃圾回收
  • 终结期引用:

😄42.垃圾回收算法

  • 标记清除算法:标记有用对象,然后进行清除回收,速度快,但是会产生垃圾碎片

  • 标记整理算法:标记无用对象,让所有存活的对象向一段移动,然后使其余内存变得连续起来

  • 复制算法:按照容量划分为两个大小相等的内存区域,当一块用完的时候将活着的对象移动到另一块上,然后一次性清除掉已使用的内存空间,这种的缺点就是由于分成了两段空间,所以比较消耗内存。

  • 分代算法:根据对象存活周期的不同将内存划分为几块,,一般是新生代和老年代,新生代一般是垃圾对象,所以使用复制算法就可以一次性清除垃圾对象,然后老年代种对象存活率较高,所以使用标记清除或者标记整理算法

😄43.垃圾回收器

主要分为串行垃圾回收器(Serial),并行垃圾回收器(Parallel),并发垃圾回收器(CMS)和G1垃圾回收器。

  • 串行:它为单线程环境设计并且只使用一个线程进行垃圾回收,不适合服务器环境。
  • 并行:吞吐量优先,多个垃圾回收线程并行工作,此时用户线程是暂停的,适用于科学计算/大数据处理等弱交互场景。
  • 并发:响应时间优先,用户线程和垃圾回收线程同时进行,不需要去暂停用户线程,互联网公司一般使用它,适用于对响应有要求的场景。
  • G1:G1垃圾回收器将堆内存分割成不同的区域然后并发的进行垃圾回收

😄44.CMS垃圾清理的过程

CMS垃圾清理的过程主要分为四个阶段,初始标记阶段,并发标记阶段,重新标记阶段,并发清除阶段

😄45.请你说一说类加载的执行过程?

类加载的过程主要分为五个阶段,加载,验证,准备,解析和初始化

  • 加载:根据查询路径找到相应的class文件然后装载到内存中
  • 验证:检查加载的class文件的正确性
  • 准备:给类中的静态变量分配内存空间
  • 解析:虚拟机将常量池中的符号引用替换成直接引用的过程
  • 初始化:就是对静态变量和静态代码块执行初始化工作

😄46.常用的JVM调优的参数有哪些?

  • -Xss: 规定了每个线程虚拟机栈的大小
  • -Xms:规定了堆的初始值
  • -Xmx:堆能达到的最大值

😄47.学习jvm用到的工具

堆的内存诊断工具有 jmap,jconsole,jconsole

😄1.jps工具

  • 查看当前系统有哪些java进程

😄2.jmap工具

  • 查看堆内存占用情况 jmap -head 进程id

😄3.jconsole工具

  • 图形界面的,多功能的监测工具,可以连续监测

😄48.讲一讲stream流中的常用方法

  1. filter:根据指定条件过滤出符合条件的元素,常用于数据筛选和过滤。

  2. map:将每个元素根据指定的规则进行转化,常用于数据类型转换或属性提取。

  3. foreach:对流中的元素逐个执行操作,常用于数据的遍历和输出。

  4. collect:将流中的元素收集到一个集合或数组中,常用于结果的汇总和输出。

  5. reduce:将流中的元素经过指定操作进行累计处理,最终输出一个结果值,常用于数据的聚合处理。

😄49.java8中的新特性

  1. Lambda表达式:可以使Java变得更加函数式,简化代码。
  2. Stream 流对象:通过流式的方式对集合进行大数据量的操作,提高代码性能
  3. 方法引用和接口默认方法:使Java中的方法能够更好地重用。
  4. Optional类:解决了空指针异常问题。
  5. 新的日期和时间API:提供了更好的时间和日期处理方式。等等

三:SSM框架

😄50.什么是Spring IOC 和DI ?

IOC : 控制翻转 , 它把程序代码直接操控的对象的调用权交给spring容器,通过容器来实现对象组件的管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。

DI : Spring 的 DI 具体就是通过反射实现注入的,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中,这就是依赖注入。

😄51.有哪些不同类型的依赖注入实现方式?

依赖注入分为接口注入,Setter方法注入和构造器注入以及注解注入

  • 构造器注入 : 顾名思义, 就是在类中提供有参构造方法, 创建Bean的时候会自动执行构造方法将依赖数据注入进去

  • Setter方法注入 : 就是提供属性对应的setter方法 , 创建Bean的时候会自动执行Setter方法将依赖数据注入进去

  • 注解注入 : 就是在属性上使用一些注入数据, 经常用的有 @Autowired , @Resource注解

😄52.Spring支持的几种bean的作用域 Scope

  1. singleton:单例模式,整个应用中只有一个Bean实例,默认情况下Spring容器中的Bean都是单例的。

  2. prototype:原型模式,每次请求都会创建一个新的Bean实例。

  3. request:每次HTTP请求都会创建一个新的Bean实例,适合Web应用中的Bean。

  4. session:每个HTTP会话中只会创建一个Bean实例,适合有状态的Web应用中的Bean。

  5. global-session:

😄53.Spring框架中的单例bean是线程安全的吗?

不是,Spring框架中的单例bean不是线程安全的 , spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线程的封装处理。

但是我们一般在使用单例Bean的时候, 不会设置共享数据, 所以也就不会存在线程安全问题 ! 从这个角度讲单例bean也是线程安全的

😄54.spring 自动装配 bean 有哪些方式?

在Spring框架xml配置中共有5种自动装配:

  • byName:通过bean的名称进行自动装配,如果一个bean的 property 与另一bean的name 相同,就进行自动装配。
  • byType:通过参数的数据类型进行自动装配。
  • constructor:利用构造函数进行装配,并且构造函数的参数通过byType进行装配。
  • setter方法 : 根据属性的setter方法注入
  • 注解注入

😄55.什么是AOP , 你们项目中有没有使用到AOP

AOP一般称为面向切面编程,作为面向对象的一种补充,用于 将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并封装为一个可重用的模块,这个模块被命名为“切面”,减少系统中的重复代码,同时提高了系统的可维护性。

在平时的学习中在记录日志、和处理全局异常的地方用过aop机制,并且我们使用的很多框架的底层都是基于AOP机制的。

😄56.SpringMVC的执行流程

  1. 用户发送请求至前端控制器DispatcherServlet
  2. 前端控制器根据请求URL的映射信息找到对应的处理器(HandlerMapping)
  3. 处理器解析请求,生成对应的ModelAndView视图模型。
  4. 然后将生成的视图模型传回前端控制器DispatcherServlet。
  5. 最后DispatcherServlet进过一系列的分析处理后生成响应并返回给客户端。

这就是MVC的主要流程

😄57.Spring MVC常用的注解有哪些?

@RequestMapping

@RequestBody

@ResponseBody

@Controller

@GetMapping

@PathVariable

@RequestParam

😄58.Mybatis #{}和${}的区别

#{}是占位符,${}是拼接符

同时#{} 可以有效的防止SQL注入,提高系统安全性;${} 不能防止SQL 注入

😄59.Mybatis 如何获取生成的主键

我知道的有二种方式

  1. 在insert标签上, 使用 useGeneratedKeys="true"keyProperty="userId"
  2. 在insert表内部, 使用 selectKey标签 , 里面使用select last_insert_id()查询生成的ID返回

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

第1种: 通过在查询的SQL语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。

第2种: 通过 ResultMap来映射字段名和实体类属性名

😄61.Mybatis如何实现多表查询

Mybatis是新多表查询的方式也有二种 :

第一种是 : 编写多表关联查询的SQL语句 , 使用ResultMap建立结果集映射

第二种是 : 将多表查询分解为多个单表查询, 使用ResultMap表的子标签associationcollection标签的select属性指定另外一条SQL的定义去执行, 然后执行结果会被自动封装

😄62.Mybatis都有哪些动态sql?能简述一下动态sql的执行原理吗?

Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能,其中有 trim|where|set|foreach|if|choose|when等等

它的原理是在执行SQL语句之前,通过动态SQL标签的处理将不同的SQL语句生成出来,然后交给JDBC执行

😄63.Mybatis是否支持延迟加载?

MyBatis支持延迟加载,它通过Java的代理模式,在需要访问延迟加载对象属性时,才动态生成对象的代理类,减少了查询时间

MyBatis支持两种类型的延迟加载:

  1. 延迟加载属性:即在需要使用某个属性时才加载该属性。

  2. 延迟加载关联对象:即在需要使用某个关联对象时才加载该对象。

MyBatis也可以通过设置lazyLoading属性、注释@Lazy、使用事务等方式实现延迟加载

😄64.如何使用Mybatis实现批量插入 ?

我们可以使用foreach标签 , 它可以在SQL语句中进行迭代一个集合

😄65.Mybatis 批量插入是否能够返回主键

可以, 返回的主键在传入集合的每个对象属性中封装的有

😄66.Mybatis的一级、二级缓存 ?

一级缓存: 基于SqlSession级别的缓存 , 默认开启

二级缓存 : 基于SqlSessionFactory的NameSpace级别缓存 , 默认没有开启, 需要手动开启

手动开启我们需要去配置cacheEnabled为true

四:Mysql篇

😄67.Mysql查询语句的书写顺序

Select <字段名称> from 表1 join 表2 on <join条件> ] where <where条件> group by <字段>

having <having条件> order by <排序字段> limit <起始偏移量,行数>

😄68.Mysql查询语句的执行顺序

(1)from 表1

(2)on <join条件>

(3)<join类型>join 表2

(4)where <where条件>

(5)group by <字段>

(6)having <having条件>

(8)Select

(10)order by <排序字段>

(11)limit <起始偏移量,行数>

😄69.Mysql 如何实现多表查询

主要分为一下三种

  • 内连接
    • 隐式内连接 : Select 字段 From 表A , 表B where 连接条件
    • 显式内连接 : Select 字段 From 表A inner join 表B on 连接条件
  • 外连接
    • 左外连接 : Select 字段 From 表A left join 表B on 连接条件
    • 右外连接 : Select 字段 From 表A right join 表B on 连接条件
    • 全外连接:(很少用)
  • 子查询

😄71.CHAR和VARCHAR的区别?

  1. char的长度是不可变的,而varchar的长度是可变的。

  2. char的存取速度比varchar要快得多

  3. char的存储方式是:对英文字符占用1个字节,对一个汉字占用两个字节。
    varchar的存储方式是:对英文和汉字都占用2个字节。

😄72.了解Mysql的索引吗?

MYSQL索引主要有 : 单列索引 , 组合索引空间索引,用的比较多的就是单列索引和组合索引

单列索引 : 在MYSQL数据库表的某一列上面创建的索引叫单列索引 , 单列索引又分为

  • 普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。

  • 唯一索引:索引列中的值必须是唯一的,但是允许为空值

  • 主键索引:是一种特殊的唯一索引,不允许有空值

  • 全文索引: 只有在MyISAM引擎、InnoDB(5.6以后)上才能使⽤用,而且只能在CHAR,VARCHAR,TEXT类型字段上使⽤用全⽂文索引。

组合索引 : 在MYSQL数据库表的多个字段组合创建的索引 , 称为组合索引也叫联合索引

  • 组合索引的使用,需要遵循左前缀原则

  • 一般情况下,建议使用组合索引代替单列索引(主键索引除外)

1). 创建索引

CREATE  [ UNIQUE | FULLTEXT ]  INDEX  index_name  ON  table_name  ( index_col_name,... ) ;

2). 查看索引

SHOW  INDEX  FROM  table_name ;

3). 删除索引

DROP  INDEX  index_name  ON  table_name ;

😄73.索引的底层数据结构 ?

索引是在存储引擎中实现的,也就是说不同的存储引擎,会使用不同的索引

MyISAM和InnoDB存储引擎:只⽀支持B+ TREE索引, 也就是说默认使用BTREE,不能够更换

MEMORY/HEAP存储引擎:支持HASH和BTREE索引

😄74.MYSQL支持的存储引擎有哪些, 有什么区别 ?

MYSQL存储引擎有很多, 常用有二种 : MyISAMInnerDB , 两种存储引擎的区别 ;

  • MyISAM支持256TB的数据存储 , InnerDB只支持64TB的数据存储
  • MyISAM 不支持事务 , InnerDB支持事务
  • MyISAM 不支持外键 , InnerDB支持外键

😄75.什么是聚簇索引什么是非聚簇索引 ?

聚簇索引

在使用InnoDB存储引擎的时候, 主键索引B+树叶子节点会存储数据行记录,简单来说数据和索引在一起存储 , 这就是聚簇索引

非聚簇索引

在使用MyISAM存储引擎的时候, B+树叶子节点只会存储数据行的指针,简单来说数据和索引不在一起 , 这就是非聚簇索引

😄76.在一个非主键字段上创建了索引, 想要根据该字段查询到数据, 需要查询几次 ?

需要查询二次

如果使用MyISAM存储引擎 , 会首先根据索引查询到数据行指针, 再根据指针获取数据

如果是InnoDB存储引擎 , 会根据索引查找指定数据关联的主键ID , 再根据主键ID去主键索引中查找数据

😄77.什么是回表查询?

简单来说就是先定位主键值,通过这个主键值再定位行记录就是所谓的回表查询,它的性能较低,我们需要尽量去避免或减轻回表查询的影响。

  1. 创建合适的索引
  2. 避免使用“SELECT *
  3. 减少多表关联查询
  4. 使用缓存

😄78.什么是覆盖索引?

覆盖索引是指只需要在一棵索引树上就能获取SQL所需的所有列数据 , 因为无需回表查询效率更高

实现覆盖索引的常见方法是:将被查询的字段,建立到联合索引里去。

😄79.什么是左前缀原则?

在mysql建立联合索引时会遵循左前缀匹配的原则,即最左优先,在检索数据时从组合索引的最左边开始匹配,并且组合索引的第一个字段必须出现在查询组句中,这个索引才会被用到 ;

😄80.什么情况下索引会失效?

  1. 在列上使用函数和进行运算会导致索引失效
  2. 使用 != 或 not in等否定操作符会导致索引失效
  3. 尽量避免使用 or 来连接条件
  4. 建立组合索引代替多个单列索引, 可以避免回表查询

😄81.索引是越多越好嘛? 什么样的字段需要建索引, 什么样的字段不需要 ?

索引会占用内存,不是越多越好

需要创建索引情况

  1. 主键自动建立主键索引

  2. 频繁作为查询条件的字段应该创建索引

  3. 多表关联查询中,关联字段应该创建索引 (on 两边都要创建索引)

  4. 查询排序的字段,应该创建索引

  5. 频繁查找字段 , 应该创建索引

  6. 查询中统计或者分组字段,应该创建索引

不要创建索引情况

  1. 表记录太少

  2. 经常进⾏增删改操作的表

  3. 频繁更新的字段

  4. where条件里使用频率不高的字段

  5. 区分度不高的字段

😄82.mysql的性能优化

  1. 从设计方面,选择合适的存储引擎 , 合适的字段类型 , 遵循范式(反范式设计)

    1. 存储引擎 :
      不需要事务, 不需要外键读写较多的的使用MyIsam
      需要事务, 需要外键的使用InnoDB

    2. 合适的字段类型 , 例如 :
      定长字符串用char , 不定长用varchr
      状态, 性别等有限数量值的用tinyint

    3. 遵循范式 :
      第一范式1NF,原子性
      第二范式2NF,消除部分依赖
      第三范式3NF,消除传递依赖

2.从功能方面可以对索引优化,采用缓存缓解数据库压力,分库分表。

3.从架构方面可以采用主从复制,读写分离,负载均衡

😄83.MYSQL超大分页怎么处理 ?

为了解决超大分页的问题,常见的处理方式包括:

  1. 根据索引进行分页,尽可能地使用 ORDER BY呀 升序和降序排列
  2. MySQL 中使用子查询等方式:可以使用临时表,子查询或者内连接等方式来分段获取数据。
  3. 增量式查询数据:首先查询第一页数据,然后以最后一个 row id 为基准查询下一页数据。

😄84.一个SQL语句执行很慢, 如何分析

首先可以开启慢查询, 通过慢查询日志或者命令, 获取到执行慢的SQL语句,其次可以使用explain命令分析SQL语句的执行过程,我们也可以去看看是否采用了正确的索引设计。

😄85.Mysql锁和分库分表

MySQL 通过锁机制来保证数据的一致性和隔离性。在 MySQL 中,锁分为两种类型:行级锁和表级锁。

行级锁是指锁定表中的每一行数据,其他事务只有等待该行锁释放才可以访问该行数据。这种锁机制可以提高并发访问的效率,避免了锁定整个表,但对于高并发访问的场景下,需要占用很多的系统资源。

表级锁是指锁定整个表,其他事务都无法访问该表中的数据。这种锁机制能够保证数据的一致性和完整性,但在高并发的环境中,会阻塞大量的请求,降低系统性能。

MySQL 提供了多种锁机制,如行级锁、页级锁、元数据锁和表级锁等,可以根据具体的业务场景选择合适的锁机制。

MySQL 分库分表

MySQL 是一个关系型数据库管理系统,支持大型数据库和高并发访问。但随着数据量的增加以及业务需求的变化,单一数据库可能无法满足业务需求。

解决这个问题的方法就是对 MySQL 数据库进行分库分表。分库分表是指将一个大型数据库拆分为多个小型数据库,或将单一数据表分成多个小型数据表,以提高数据库的扩展性和可用性。

常用的分库分表方案有垂直分表和水平分表两种方式,垂直分表是根据业务实体对大型数据表进行逻辑切割,将相同类型的数据存储到不同的表中。这种分表方式可以提高查询效率,但增加了查询的难度。水平分表是指使用按照某种规则划分到不同的表中,同一张表在不同的表中存储不同的数据。这种分表方式可以将大表拆分为多个小表,减小单个表的数据量,提高数据查询效率。

总之,在实际的开发场景下,MySQL 锁和分库分表是实现高并发访问、大数据量处理的重要手段。根据实际情况进行选择合适的分表方案,可以更好地优化 MySQL 数据库性能和稳定性。

😄86.MYSQL实现事物的原理 有了解过吗 ?

MySQL 实现事务的原理主要涉及到 ACID(原子性、一致性、隔离性和持久性)特性和事务的隔离级别

ACID 特性保证了 MySQL 数据库的数据操作具有原子性、一致性、隔离性和持久性等特性,而事务的隔离级别则控制了 MySQL 数据库事务与其他事务之间的互动。

MySQL 实现事务的原理包括以下几个方面:

  1. 原子性:只有在所有的 SQL 语句都成功完成之后,才会提交事务。
  2. 一致性:MySQL 事务机制通过约束和触发器等手段来实现数据的一致性。一旦发现数据存在异常,就会进行事务回滚操作,并修改数据为正确的状态
  3. 隔离性:MySQL 事务机制采用锁机制来实现事务之间的隔离性。四种隔离级别,(读未提交,读已提交,可重复读,串行化),以控制事务之间的互动。
  4. 持久性:MySQL 事务通过使用 Redo 日志和Binlog 日志来保证事务的持久性,其中,Redo 日志记录事务对数据的修改,Binlog 日志记录数据修改语句,以便在服务器崩溃时,可以从 Binlog 日志文件中恢复数据。

五.redis

😄87.你们项目中哪里用到了Redis ?

在我们的项目中很多地方都用到了Redis , Redis在我们的项目中主要有三个作用 :

  1. 使用Redis做热点数据缓存/接口数据缓存
  2. 使用Redis存储一些业务数据 , 例如 : 验证码 , 用户信息 , 用户行为数据 , 数据计算结果 , 排行榜数据等
  3. 使用Redis实现分布式锁 , 解决并发环境下的资源竞争问题

Redis 实现分布式锁主要是通过 SET 指令实现的,获取锁成功之后,进行业务处理,处理完毕后使用 DEL 命令释放锁。

😄88.Redis的常用数据类型有哪些 ?

Redis 有 5 种基础数据结构,它们分别是:

  • string(字符串)
  • list(列表)
  • hash(字典)
  • set(集合)
  • zset(有序集合)

😄89.Redis的数据持久化策略有哪些 ?

Redis 提供了两种方式,实现数据的持久化到硬盘。

  1. RDB 持久化(全量),是指在指定的时间间隔内将内存中的数据集快照写入磁盘。
  2. AOF持久化(增量),以日志的形式记录服务器所处理的每一个写、删除操作

😄90.Redis的数据过期策略有哪些 ?

惰性删除 :只会在取出 key 的时候才对数据进行过期检查。这样对 CPU 最友好,但是可能会造成太多过期 key 没有被删除。

数据到达过期时间,不做处理。等下次访问该数据时,我们需要判断

  1. 如果未过期,返回数据
  2. 发现已过期,删除,返回null

定期删除 : 每隔一段时间抽取一批 key 执行删除过期 key 操作。并且,Redis 底层会通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响。

定期删除对内存更加友好,惰性删除对 CPU 更加友好。两者各有千秋,所以 Redis 采用的是 定期删除+惰性删除

😄91.Redis的数据淘汰策略有哪些 ?

lru淘汰算法:根据访问的频率来的,不怎么访问的key就会被淘汰掉,经常访问的就会被存储到那个内存里面

lfu淘汰算法:lru有一个缺点嘛,当一个很长时间的key没有被访问到然后突然有一个访问的时候,它就会变成一个热点key,但它实际并不是一个热点key,所以 lfu 为了解决这样的弊端,就增加的key的一个访问的次数,根据次数来绝对是不是热点key

😄92.你们使用Redis是单点还是集群 ? 哪种集群 ?

我们Redis使用的是哨兵集群 , 一主二从 , 三个哨兵 , 三台Linux机器

😄93.Redis集群有哪些方案?

我所了解的Redis集群方案

  1. 主从复制集群 : 读写分离, 一主多从 , 解决高并发读的问题
  2. 哨兵集群 : 主从集群的结构之上 , 加入了哨兵用于监控集群状态 , 主节点出现故障, 执行主从切换 , 解决高可用问题
  3. Cluster分片集群 : 多主多从 , 解决高并发写的问题, 以及海量数据存储问题 , 每个主节点存储一部分集群数据

😄94.什么是 Redis 主从同步?

redis的主从复制其实就是将主redis节点的数据复制到其他从redis节点进行存储,通过复制,实现redis的高可用性和对数据进行冗余备份,保证数据和服务的可靠性。

主从数据同步主要分二个阶段 :

第一阶段 : 全量复制阶段

第二阶段 : 增量复制阶段

😄95.Redis的内存用完了会发生什么?

如果达到设置的上限,Redis 的写命令会返回错误信息( 但是读命令还可以正常返回。)
也可以配置内存淘汰机制, 当 Redis 达到内存上限时会冲刷掉旧的内容。

😄96.Redis和Mysql如何保证数据⼀致?

  1. 先更新Mysql,再更新Redis,如果更新Redis失败,可能仍然不⼀致

  2. 先删除Redis缓存数据,再更新Mysql,再次查询的时候在将数据添加到缓存中

    这种⽅案能解决1 ⽅案的问题,但是在⾼并发下性能较低,⽽且仍然会出现数据不⼀致的问题,
    ⽐如线程1删除了 Redis缓存数据,正在更新Mysql,
    此时另外⼀个查询再查询,那么就会把Mysql中⽼数据⼜查到 Redis中

  3. 使用MQ异步同步, 保证数据的最终一致性

😄97.什么是缓存穿透 ? 怎么解决 ?

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大

解决方案 :

  • 热点数据提前预热
  • 设置热点数据永远不过期。
  • 加锁 , 限流

😄98.什么是缓存雪崩 ? 怎么解决 ?

缓存雪崩/缓存失效 指的是大量的缓存在同一时间失效,大量请求落到数据库 导致数据库瞬间压力飙升。

造成这种现象的 原因是,key的过期时间都设置成一样了。

解决方案是,key的过期时间引入随机因素

😄99.数据库有1000万数据 ,Redis只能缓存20w数据, 如何保证Redis中的数据都是热点数据 ?

配置Redis的内容淘汰策略为LFU算法 , 这样会把使用频率较低的数据淘汰掉 , 留下的数据都是热点数据

😄100.Redis分布式锁如何实现 ?

Redis 实现分布式锁主要是通过 setnxDELexpire 指令实现的,具体实现步骤如下:

  1. 客户端发送 SETNX 指令到 Redis,尝试获取锁。如果 setnx 操作成功,返回 1,代表获取锁成功。

  2. 如果获取锁失败,客户端可以选择等待一段时间后重试获取锁,或者直接放弃获取锁。

  3. 在获取锁成功后,客户端需要在一定的时间内完成业务操作,并在业务操作完成后发送 DEL 指令到 Redis,释放锁。

  4. 防止业务操作时间过长而无法释放锁的情况,客户端可以使用 expire 指令为锁设置一个过期时间,确保即使业务操作时间超长也能自动释放锁

😄101.你的项目中哪里用到了分布式锁

  1. 订单号生成:在高并发场景下,订单号生成可能会出现重复的情况,可以通过分布式锁来保证订单号的唯一性。

  2. 用户注册:在进行用户注册时,有可能存在并发注册的情况,可以通过分布式锁来保证同一时间只有一个用户注册

  3. 防止超卖:在进行某些售卖活动时,为了防止库存被超卖,可以使用分布式锁来保证写入库存时只有一个节点进行操作。

六:springboot & springcloud

😄102.讲一讲SpringBoot自动装配的原理

在SpringBoot项目的启动引导类上都有一个注解@SpringBootApplication

这个注解其实是由三个注解构成的:

@SpringBootConfiguration :标注当前类是一个SpringBoot的配置类

@ComponentScan :开启组件扫描, 默认扫描的是当前启动类所在包以及子包

@EnableAutoConfiguration : 开启自动配置(自动配置核心注解)

😄103.讲一讲SpringBoot启动流程

springboot项目在启动的时候, 首先会执行启动引导类里面的SpringApplication.run(AdminApplication.class, args)方法

这个run方法主要做的事情可以分为三个部分 :

第一部分进行SpringApplication的初始化模块,配置一些基本的环境变量、资源、构造器、监听器

第二部分实现了应用具体的启动方案,包括启动流程的监听模块、加载配置环境模块、及核心的创建上下文环境模块

第三部分是自动化配置模块,该模块作为springboot自动配置核心

😄104.SpringBoot起步依赖有哪些

- spring-boot-starter:Spring Boot 的基础依赖包,包含了自动配置、日志、测试、和 Jackson 等核心依赖。

- spring-boot-starter-web:提供Web服务相关的依赖,

- spring-boot-starter-aop:AOP 功能的启动依赖。

- spring-boot-starter-jdbc:使用 JDBC 连接数据库的依赖。

- spring-boot-starter-security:提供安全认证和授权的依赖。

- spring-boot-starter-test:提供 Spring Boot 测试环境所需的依赖。

😄105.springBoot支持的配置文件有哪些 ? 加载顺序是什么样的

1 properties文件
2 YAML文件
3 系统环境变量
4 命令行参数

  1. bootstrap.yml
  2. application.yml
  3. application-{profile}

如果存在相同的属性,高优先级的配置文件会覆盖低优先级的配置文件的相同属性

如果有相同的配置参数, 后加载的会覆盖先加载的

😄106.Spring Boot的核心注解是哪个?他由哪几个注解组成的?

Spring Boot的核心注解是@SpringBootApplication , 他由几个注解组成 :

  • @SpringBootConfiguration: 组合了- @Configuration注解,实现配置文件的功能;
  • @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项
  • @ComponentScan:Spring组件扫描

😄107.Spring Boot 中如何解决跨域问题 ?

SpringMVC项目中使用@CrossOrigin注解来解决跨域问题 , 本质是CORS

在SpringCloud项目中一般都会有网关 , 在网关中可以配置CORS跨域, 这样所有通过网关的请求都解决了跨域问题

😄108.你们项目中使用的SpringBoot是哪个版本 ?

  • SpringBoot : 2.3.4.RELEASE

  • SpringCloud : Hoxton.SR10

  • SpringCloudAlibaba : 2.2.5.RELEASE

😄109.Spring Cloud 5大组件有哪些?

  • 注册中心/配置中心 Nacos:Nacos 作为默认的服务注册中心和配置中心,Nacos 不仅具备服务发现、服务注册、服务配置管理等基本功能,还支持动态配置更新、流量管理以及分布式任务调度等高级功能。

  • 负载均衡 Ribbon:

  • 服务调用 Feign

  • 服务保护 sentinel

  • 服务网关 Gateway:服务网关是一种用于管理微服务的应用程序,它主要的作用是将客户端请求转发到相应的微服务中。

    执行流程如下:

😄110.什么是微服务?微服务的优缺点是什么?

随着业务发展,单体应用变得越来越庞大,代码逻辑也会变得复杂,难以理解和维护,在这种情况之下,我们采用微服务架构

  • 微服务架构就是将单体的应用程序分成多个应用程序,这多个应用程序就成为微服务,每个微服务运行在自己的进程中,并使用轻量级的机制通信。这些服务围绕业务能力来划分,并通过自动化部署机制来独立部署。

微服务就是一个独立的职责单一的服务应用程序

1.优点:松耦合,聚焦单一业务功能,无关开发语言,团队规模降低 , 扩展性好, 天然支持分库
2.缺点:随着服务数量增加,管理复杂,部署复杂,服务器需要增多,服务通信和调用压力增大

😄111.你们项目中微服务之间是如何通讯的?

1.同步通信:通过Feign发送http请求调用

2.异步:消息队列,如RabbitMq、KafKa等

😄112.服务注册和发现是什么意思?Spring Cloud 如何实现服务注册发现?

服务注册和发现是分布式系统架构中的关键组件之一,它是将服务信息注册到服务注册中心,而服务发现则是指服务消费方从服务注册中心获取可用的服务信息,以便进行服务调用。

spring cloud是利用 Eureka 来实现服务注册和发现的。

😄113.你们项目中使用的注册中心是什么 ? 有没有了解过原理 ?

我的项目中注册中心用的是Nacos , 基本上所有的注册中心的核心功能都包括服务注册 , 服务发现, 服务状态监控这三个功能

Nacos 是一个基于云原生理念构建的动态服务发现、配置管理和服务治理中心

服务提供方启动后会把服务信息注册到 Nacos 中心,服务消费方启动后会从 Nacos 中心获取服务信息,从而实现服务之间的通信。

Nacos 通过集成 Ribbon 和 Spring Cloud LoadBalancer 来实现负载均衡

😄114.你们项目负载均衡如何实现的 ?

服务调用过程中的负载均衡一般使用SpringCloud的Ribbon 组件实现 , Feign的底层已经自动集成了Ribbon , 使用起来非常简单

客户端调用的话一般会通过网关, 通过网关实现请求的路由和负载均衡

内容持续输出中…

  • 服务调用 Feign

  • 服务保护 sentinel

  • 服务网关 Gateway:服务网关是一种用于管理微服务的应用程序,它主要的作用是将客户端请求转发到相应的微服务中。

    执行流程如下:

😄110.什么是微服务?微服务的优缺点是什么?

随着业务发展,单体应用变得越来越庞大,代码逻辑也会变得复杂,难以理解和维护,在这种情况之下,我们采用微服务架构

  • 微服务架构就是将单体的应用程序分成多个应用程序,这多个应用程序就成为微服务,每个微服务运行在自己的进程中,并使用轻量级的机制通信。这些服务围绕业务能力来划分,并通过自动化部署机制来独立部署。

微服务就是一个独立的职责单一的服务应用程序

1.优点:松耦合,聚焦单一业务功能,无关开发语言,团队规模降低 , 扩展性好, 天然支持分库
2.缺点:随着服务数量增加,管理复杂,部署复杂,服务器需要增多,服务通信和调用压力增大

😄111.你们项目中微服务之间是如何通讯的?

1.同步通信:通过Feign发送http请求调用

2.异步:消息队列,如RabbitMq、KafKa等

😄112.服务注册和发现是什么意思?Spring Cloud 如何实现服务注册发现?

服务注册和发现是分布式系统架构中的关键组件之一,它是将服务信息注册到服务注册中心,而服务发现则是指服务消费方从服务注册中心获取可用的服务信息,以便进行服务调用。

spring cloud是利用 Eureka 来实现服务注册和发现的。

😄113.你们项目中使用的注册中心是什么 ? 有没有了解过原理 ?

我的项目中注册中心用的是Nacos , 基本上所有的注册中心的核心功能都包括服务注册 , 服务发现, 服务状态监控这三个功能

Nacos 是一个基于云原生理念构建的动态服务发现、配置管理和服务治理中心

服务提供方启动后会把服务信息注册到 Nacos 中心,服务消费方启动后会从 Nacos 中心获取服务信息,从而实现服务之间的通信。

Nacos 通过集成 Ribbon 和 Spring Cloud LoadBalancer 来实现负载均衡

😄114.你们项目负载均衡如何实现的 ?

服务调用过程中的负载均衡一般使用SpringCloud的Ribbon 组件实现 , Feign的底层已经自动集成了Ribbon , 使用起来非常简单

客户端调用的话一般会通过网关, 通过网关实现请求的路由和负载均衡

内容持续输出中…

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值