建设明星网站的目的,高校信息化建设网站系统微信,怎么用织梦做购物网站,自己怎么做网站首页Java基础
1、JDK和JRE的区别是什么** JDK是Java开发工具包#xff0c;JRE是Java运行时环境#xff0c;二者的区别在于
JRE是Java程序运行所必须的#xff0c;它包含jvm和一些Java的基础类库
JDK是Java程序开发所必须的#xff0c;它包含JRE和一些开发工具
总结一下就是…Java基础
1、JDK和JRE的区别是什么** JDK是Java开发工具包JRE是Java运行时环境二者的区别在于
JRE是Java程序运行所必须的它包含jvm和一些Java的基础类库
JDK是Java程序开发所必须的它包含JRE和一些开发工具
总结一下就是JDK包含JRE如果仅仅是运行Java程序只要有JRE即可如果是要开发Java程序则必须要有JDK
2、和的区别是什么 和都是逻辑运算符都可以实现取并的效果即符号两边的表达式都为true结果才是true
不一样的是有短路的功能即当符号前面的表达式为false时后面的表达式将不再执行而没有这个功能
另外还可以用作位运算符当操作符两边的表达式不是boolean类型时表示按位与操作
3、final finally finalize区别是什么 这是Java提供的三个关键字虽然长的差不多但是其实没什么联系使用场景也完全不同
final可以修饰类、变量、方法修饰类表示该类不能被继承、修饰方法表示该方法不能被重写、 修饰变量表示该变量是一个常量不能被重新赋值。
finally一般作用在try-catch代码块中在处理异常的时候无论程序是否出现异常写在finally中的代码都会被执行一般用来释放一些资源
finalize是Object类的一个方法它会在一个对象被垃圾回收的时候自动被垃圾回收器来调用
4、String、StringBuffer、 StringBuilder 的区别
这几个都是关于字符串的类他们的区别点有下面几个
可变性String是不可变对象其它的都是可变对象 线程安全String和StringBuffer是线程安全的StringBuilder是线程不安全的 效率StringBuilder最高StringBuffer居中String效率最低 使用场景少量字符串的操作使用String大量字符串的频繁操作在多线程下使用StringBuffer单线程下可以使用StringBuilder
5、有哪些创建对象的方式 1、new 2、反射 3、克隆 4、json反序列化
6、重写和重载的区别是什么 重载和重写都是用于描述方法间的关系的但是他们的含义和场景确大不相同
重写是存在于子父类之间的一般用在父类的方法无法满足子类需求时子类重写方法来自定义方法功能
它要求子类定义的方法与父类中的方法具有相同的方法名字相同的参数表和相同的返回类型
重载是存在于同一个类中的一般用在功能相似的方法需要接收不同的参数时
它要求多个方法具有相同的名字但方法具有不同的参数列表
7、this和super的应用场景是什么 this代表的是当前对象一般用于在一个方法中调用本对象的成员变量或其它方法
super代表是父类对象一般在本对象和父对象出现成员名称冲突时强行调用父对象的成员也经常用于调用父类的构造方法
8、throw和throws的区别是什么 throws用在方法的声明上声明当前方法可能抛出的异常
throw写在方法里真正的抛出一个异常抛出自定义异常。创建对象自定义抛出异常
9、应该使用什么数据类型来计算价格 1、如果不是特别关心内存和性能的话使用 BigDecimal
2、否则使用预定义精度的 double 类型
3、用int也可以在表中存储的单位是分元角分的分比如一个删除两块五在表中存250
10、 与 equals 的区别 是一个运算符equals 是 Object 类的方法 用于基本类型的变量比较时比较的是值是否相等equals不能直接用于基本数据类型的比较需要转换为其对应的包装类型。 用于引用类型的比较时。和 equals 都是比较栈内存中的地址是否相等。但是通常会重写 equals 方法去实现对象内容的比较。
11、接口和抽象类的区别 它们的共同点是都不能实例化对象
它们的不同点是 抽象类一般用于抽取子类中的共同方法和属性接口一般用于指定实现类的规范 抽象类可以有构造方法作用是用给抽象父类中中的属性赋值接口中不能有构造方法 接口中不能含有静态代码块而抽象类可以有静态代码块 一个类只能继承一个抽象类而一个类却可以实现多个接口。
12、说出几个常见的异常 Java中的异常分为运行时异常和编译时异常两大类
运行时异常都是 RuntimeException 类及其子类异常这类异常的特点是不强行要求程序员进行处理常见的有
NullPointerException 空指针异常调用了未经初始化的对象或者是不存在的对象
IndexOutOfBoundsException 数组角标越界异常常见于操作数组对象时发生
ClassCastException 数据类型转换异常
NoSuchMethodException 方法不存在异常
非运行时异常也叫编译异常是 Exception 的子类但不是 RuntimeException的子类类型上都属于及其子类
它要求程序员在编写代码的过程中提供异常处理方案否则编译不通过常见的有IOException和SQLException等
13、Java 反射有了解吗 反射是指在运行状态中对于任意一个类都能够知道这个类所有的属性和方法并且可以调用它的任意一个方法
它主要应用于大量的框架底层比如 Spring/Spring Boot、MyBatis 等等
14、浅拷贝和深拷贝区别
浅拷贝只复制基础类型的数据对象属性值复制地址不复制值
深拷贝要复制的对象所引用的对象都复制了一遍也就是说把teacher中的属性和值也会一一复制 集合系列
1.说一说集合类的体系结构 我们常见的集合主要有两大类分别是单列集合和双列集合
2、聊聊集合类的底层数据结构 集合主要分为单列集合和双列集合
双列集合都是Map的实现类主要有HashMap、LinkedHashMap和TreeMap
HashMap JDK1.8之前是由数组链表组成的JDK1.8之后为了提升效率在当链表的长度8并且数组长度64的时候链表就会转换为红黑树 LinkedHashMap继承自HashMap在HashMap的基础上增加了一条双向链表来保持键值对的插入顺序。 TreeMap底层是红黑树
单列集合主要是List和Set
List有ArrayList和LinkedListArrayList底层是数组查询快增删慢LinkedList底层是双向链表查询慢增删快
Set有HashSet、LinkedHashSet和TreeSet它的实现原理和对应的Map是一样的底层都是用的对应Map的key实现
3、ArrayList和LinkedList的区别 ArrayList和LinkedList都是Java中的单列结合都是有序的可重复的
不同点有下面几个
底层数据结构不同ArrayList 底层是动态数组查询快增删慢而LinkedList底层是双向链表LinkedList查询慢增删快 占用内存空间不同LinkedList比ArrayList更占内存这是因为它的每个节点除了存储数据还存储了前后节点的引用两个引用
4、HashMap和HashTable区别 HashMap和HashTable都是Map的子类都可以存储键值对的数据区别点在于HashTable是线程安全HashMap则不是
HashTable的线程安全是通过底层在每个方法上添加synchronized 实现的因此它的效率要比HashMap低
如果碰到需要线程安全的场景我们则会使用ConcurrentHashMap而不用HashTable所以我对它的了解也就这些
ConcurrentHashMap相比较HashTable来说他用到了乐观锁结合悲观锁一起使用的
5、HashMap的底层原理 HashMap底层数据结构是在JDK1.8之前是数组链表实现在JDK1.8之后是数组链表红黑树
下面我以map中存储对象的流程给您说一下它的实现原理把
当我们创建一个HashMap的时候JDK就会在内存中创建一个长度为16的数组
当我们调用put方法像HashMap中保存一个元素的时候它会先调用key的hashCode方法计算出key的hash值
然后使用得到hash值对数组长度取余找出当前对象的元素在数组中的位置
接下来它会判断算出的位置上是否有元素如果没有就会将此元素直接存储到当前位置上
如果算出的位置上有元素或者是有链表它会再调用key的equals方法跟存在元素的key做比较
如果有一个比较得到的结果为true则会进行值的覆盖如果都为false则会将元素追加在链表的末尾
当然为了降低Hash冲突和链表长度HashMap还做了一些优化
当元素的数量超过数组大小与加载因子的乘积的时候就会执行扩容扩容为原来的2倍并将原来数组中的键重新进行hash运算然后分配到新数组中
当链表的长度8并且数组长度64的时候链表就会转换为红黑树当红黑树结点数小于6时将再次转回为链表。
6、HashMap是怎么解决哈希冲突的
当我们调用put方法像HashMap中保存一个元素的时候它会先调用key的hashCode方法计算出key的hash值然后使用得到hash值对数组长度取余找出当前对象的元素在数组中的位置不同的元素计算完毕之后就可能会被分配到数组中的同一个位置上这就是所谓的哈希冲突。
我知道的一种解决方式是开放定址法也称为线性探测法就是从发生冲突的那个位置开始按照一定的次序从 hash 表中找到一个空闲的位置然后把发生冲突的元素存入到这个空闲位置中
7、HashMap的扩容机制是怎样的 HashMap的扩容机制是指当HashMap中的元素个数超过数组长度乘以负载因子时就会重新分配一个更大的数组并将原来的元素重新计算哈希值并插入到新的数组中。
在JDK1.8中底层是调用resize方法实现扩容的它的默认做法是当元素个数超过数组长度的0.75倍时触发扩容每次扩容的时候都是扩容为原来的2倍 扩展后Node对象的位置要么在原位置要么移动到原偏移量两倍的位置。
8、为何HashMap的数组长度一定是2的次幂 1、效率高 2、可以尽量避免hash冲突
9、说一下HashSet的实现原理 HashSet是基于HashMap实现的HashSet的值存放于HashMap的key上HashMap的value统一为present因此 HashSet的实现比较简单相关 HashSet 的操作基本上都是直接调用底层 HashMap 的相关方法来完成由于HashMap的键是不能重复的所有HashSet 不允许重复的值。
10、HashSet如何检查重复 存储数据的时候有一个equals方法去跟存在的每个值进行比较表较结果有一个相等则直接丢弃不相等就会被挂在老元素的后面。 线程池
1、创建线程有几种方式 我知道的创建线程的方式大体上可以分为四种
1继承Thread类并重写run方法创建线程 2实现Runnable接口并重写run方法 3实现Callable 接口并重写call方法 4使用线程池创建 2、runnable和callable的区别
Runnable接口run方法无返回值Callable接口call方法有返回值也 3、start和run的区别 run(): 封装了要被线程执行的代码本质上就是一个普通方法可以被调用多次
start(): 用来启动线程底层会自动去执行run方法中的代码start方法只能被调用一次
也就是启动线程的时候只能调用start方法如果调用的run方法不会启动新线程而是当普通方法调用执行
4、notify和 notifyAll的区别 这两个方法都是用户唤醒被wait方法休眠的线程的区别点在于
notifyAll唤醒所有wait的线程 notify随机唤醒一个 wait 线程 5、sleep 和 wait 的区别 方法归属不同sleep是Thread 的静态方法而wait是Object的成员方法 醒来时机不同 sleep会在指定的时间后自动苏醒而wait需要其他线程的唤醒 锁特性不同sleep不会释放锁而wait会释放锁 使用限制不同wait必须用在synchronized代码块中而sleep无此限制 6、说一下线程的状态及转换 在我的理解中线程共分为7种状态分别是新建、就绪、运行、终止以及阻塞、等待、死亡
它们之间的转换关系是这样的
当线程new出来之后没有start之前就会处于新建状态 当线程执行start方法之后就进入就绪状态 当就绪的线程一旦获取到了cpu的执行权就可以进入运行状态 当线程执行完了run方法之后就进入了死亡状态 这是一条正常的流程但是代码在运行状态下可以因为一些原因进入到其它状态比如说当进行抢锁操作时抢锁失败就会进入到阻塞状态 当代码调用了wait或者sleep方法时就会进入等待状态
这是我对线程状态及其转换的理解
7、现在有T1,T2,T3三个线程如何保证它们按顺序执行 用join方法实现
具体来说就是可以在t2之前调用t1.join()在t3之前调用t2.join()
8、synchronized的实现原理是怎样的 在Java中每个对象都隐式包含一个 monitor监视器对象加锁的过程其实就是竞争 monitor 的过程
当线程进入字节码monitorEnter指令之后线程将持有monitor对象执行monitorExit时释放 monitor 对象
如果在这个过程中其它线程就会阻塞等待获取该monitor对象
1、线程池的执行流程
当我们提交一个任务到线程池中线程池的处理流程如下
首先判断线程池里的核心线程是否都在执行任务如果不是则创建一个新的工作线程来执行任务。 如果核心线程都在执行任务则判断工作队列是否已满如果没满则将新提交的任务存储在这个工作队列里。 如果工作队列满了则判断线程数是否小于最大线程数如果是则创建临时线程直接执行任务 如果线程数已经到达了最大线程数则会执行对应的拒绝策略逻辑 2、线程池的核心参数 线程池在创建的时候最大支持传入7个参数分别是
核心线程数、最大线程数、临时线程的空闲时间、临时线程的空闲时间单位、工作队列长度、创建线程的工厂、线程池的拒绝策略
3、线程池的拒绝策略有哪些 拒绝策略是指将任务添加到线程池中时线程池拒绝该任务所采取的相应策略官方提供的有4种不用背英文直接说中文
AbortPolicy直接抛出异常默认策略
CallerRunsPolicy用调用者所在的线程来执行任务
DiscardOldestPolicy丢弃阻塞队列中靠最前的任务并执行当前任务
DiscardPolicy直接丢弃任务
4、了解Executors创建线程池吗
了解过Excutors是JDK提供的一个可以创建线程池的工具类它可以创建4 种线程池
但是用它创建的线程池有的没有限制最大线程数有的没有限制阻塞队列的长度这样的话极大可能导致OOM
因此我们公司不允许我们使用它而是使用自己传递参数的方式创建线程池
5、如何确定线程池的核心线程数 线程池的核心线程数跟任务的性质有很大关系对于CPU密集型时任务可以少配置线程数推荐配置为CPU核数1这样可以使得每个线程都在执行任务 IO密集型时即该任务需要大量的IO大部分线程都阻塞则需要多配置线程数推荐配置为CPU核数的2倍
什么是代码重排序 重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段
join、yield方法有什么区别 join在一个线程中调用另一个线程的Join方法是为了顺序执行线程如在线程A 中调用了B.join那么线程A将等待线程B运行完后在执行A。
yield让出运行机会给别的线程但是当前线程也可能继续得到机会
用户线程和守护线程有什么区别 用户线程: 是虚拟机启动的线程中的普通线程当所有用户线程结束运行后虚拟机才会停止运行即使还有一些守护线程在运行。 守护线程: 是在程序中创建的线程它的作用是为其他线程提供服务。当所有的用户线程结束运行后守护线程也会随之结束而不管它是否执行完毕。守护线程通常用于执行一些辅助性任务如垃圾回收、缓存清理等它们不需要等待所有的任务完成后再退出。
同步方法和同步块哪个是更好的选择 在 Java 中同步方法和同步块都是用于保护 共享资源9、避免线程之间互相干扰的机制。它们都可以用来实现线程安全的操作但在不同的情况下选择哪一种更好取决于具体的需求和场景。 1.同步方法:在 java 中可以使用 synchronized 关键字来创建同步方法。当一个线程进入同步方法时它就会获得对象的锁其他线程将无法进入该方法直到锁被释放。同步方法适合于简单的同步需求能够提供较为简洁的代码并且可以确保整个方法的执行都是线程安全9的。 2.同步块:同步块是在方法内部使用 synchronized 关键字来创建的一段同步代码块。同步块允许更加灵活地控制锁的粒度只对需要同步的部分代码进行同步减少了锁的粒度提高了并发性能。同步块适合于需要对代码片段进行精确控制的情况。 在选择同步方法和同步块时需要考虑具体的情况 如果整个方法都需要同步则可以选择同步方法简洁明了 如果只需要对方法中的部分代码进行同步或者需要对多个对象进行同步可以选择同步块。
volatile关键字作用 内存可见性保证变量的可见性当一个被volatile关键字修饰的变量被一个线程修改的时候其他线程可以立刻得到修改之后的结果。当一个线程向被volatile关键字修饰的变量写入数据的时候虚拟机会强制它被值刷新到主内存中。当一个线程用到被volatile关键字修饰的值的时候虚拟机会强制要求它从主内存中读取。 屏蔽JVM指令重排序防止JVM编译源码生成class时使用重排序指令重排序是编译器和处理器为了高效对程序进行优化的手段它只能保证程序执行的结果是正确的但是无法保证程序的操作顺序与代码顺序一致。这在单线程中不会构成问题但是在多线程中就会出现问题。非常经典的例子是在单例方法中同时对字段加入voliate就是为了防止指令重排序。
Lock和synchronized的区别 synchronized 是Java中的关键字Lock是一个interface接口 synchronized关键字可以直接修饰方法也可以修饰代码块而lock只能修饰代码块 synchronized在发生异常时会自动释放线程占有的锁因此不会导致死锁现象发生 Lock在发生异常时如果没有主动通过unLock()去释放锁则很可能造成死锁现象因此使用Lock时需要在finally块中释放锁 Lock可以让等待锁的线程响应中断interrupt而synchronized却不行使用synchronized时等待的线程会一直等待下去不能够响应中断 在性能上来说如果竞争资源不激烈两者的性能是差不多的而当竞争资源非常激烈时即有大量线程同时竞争此时Lock的性能要远远优于synchronized。
MySQL系列 0、MySQL的版本
5.5 5.7 8.x(我们用的是)
1、内连接和外连接的区别
内连接指的是使用左表中的每一条数据分别去连接右表中的每一条数据仅仅显示出匹配成功的那部分
外连接有分为左外连接和右外连接
左外连接: 首先要显示出左表的全部然后使用连接条件匹配右表能匹配中的就显示匹配不中的显示为null 右外连接: 首先要显示出右表的全部然后使用连接条件匹配左表能匹配中的就显示匹配不中的显示为null
2、drop、delete与truncate区别 这个关键字都是MySQL中用于删除的关键字区别在于
delete语句执行删除的过程是每次从表中删除一行并且同时将该行的删除操作作为事务记录在日志中保存以便进行进行回滚操作 drop 主要用于删除数据表、表中的列、索引等结构 truncate 是直接把表删除然后再重建表结构 这三种方式在效率方面drop 最高、truncate 其次、delete最低但是drop和truncate 都不记录日志无法回滚
3、union与union all的区别 union和union all都是MySQL中用于合并多条select语句结果的关键字它会将前后两条select语句的结果组合到一个结果集合中区别在于UNION ALL会返回所有结果UNION会去掉重复的记录
4、char和varchar的区别 char和varchar是MySQL中的字符串类型区别在于下面几方面
最大长度char最大长度是255字符varchar最大长度是65535个字符 占用长度char是定长的不足的部分用隐藏空格填充varchar是不定长的 空间使用char会浪费空间varchar会更加节省空间 查找效率char查找效率会很高varchar查找效率会更低 因此我们如果存储固定长度的列例如身份证号、手机号建议使用char
其它不定长度的建议使用varchar使用varchar的时候也要尽量让声明长度贴近实际长度
注意varchar(50)中50的涵义是最多存放50个字符varchar(50)和varchar(200)存储hello所占空间一样
5、事务的四大特性
事务是有一组操作要不全部成功要不全部失败事务的四大特性指的是原子性、一致性、隔离性、持久性
原子性事务是最小的执行单位不允许分割同一个事务中的所有命令要么全部执行要么全部不执行 一致性事务执行前后数据的状态要保持一致例如转账业务中无论事务是否成功转账者和收款人的总额应该是不变的 隔离性并发访问数据库时一个事务不被其他事务所干扰各并发事务是独立执行的 持久性一个事务一旦提交对数据库的改变应该是永久的即使系统发生故障也不能丢失
6、并发事务多个事务同事执行带来的问题 并发事务下可能会产生如下的问题
脏读一个事务读取到了另外一个事务没有提交的数据 不可重复读一个事务读取到了另外一个事务修改的数据 幻读虚读一个事务读取到了另外一个事务新增的数据
7、事务隔离级别 事务隔离级别是用来解决并发事务问题的方案不同的隔离级别可以解决的事务问题不一样
读未提交 允许读取尚未提交的数据可能会导致脏读、幻读或不可重复读 读已提交 允许读取并发事务已提交的数据可以阻止脏读但是幻读或不可重复读仍有可能发生 可重复读 对同一字段的多次读取结果都是一致的除非数据是被本身事务自己所修改可以阻止脏读和不可重复读但幻读仍有可能发生 可串行化 所有的事务依次逐个执行这样事务之间就完全不可能产生干扰该级别可以防止脏读、不可重复读以及幻读。 上面的这些事务隔离级别效率依次降低安全性依次升高如果不单独设置MySQL默认的隔离级别是可重复读
原理我知道是MVCC多版本并发控制有日志文件和3个隐藏的列处理的
8、数据库建表三大范式 三大范式是指导设计表的原则
第一范式表中的每一列不能再进行拆分也就是每一列都应该是原子的列不可再拆分 第二范式一张表只做一件事不要将多个层次的数据列保存到一张表中 一张表只做一件事 第三范式数据不能存在传递关系说的通俗点就是一张表拆成两个表使用外键建立关系使用外键
在现有的程序设计中认为第三范式是可以不遵守的也就是通过添加冗余字段来减少多表联查或计算我们称为反三范式
9、索引的分类
1、从物理存储角度上分为聚集聚簇索引和非聚集非聚簇索引
聚集索引指的是数据和索引存储在同一个文件中
非聚集索引指的是数据和索引存储在不同的文件中
2、从逻辑角度上分为普通、唯一、主键和联合索引它们都可以用来提高查询效率区别点在于
唯一索引可以限制某列数据不出现重复主键索引能够限制字段唯一、非空
联合索引指的是对多个字段建立一个索引一般是当经常使用某几个字段查询时才会使用它比对这几个列单独建立索引效率要高
10、索引的创建原则 我们在建立索引的时候应该遵循下面这些原则
主键字段、外键字段应该添加索引 经常作为查询条件、排序条件或分组条件的字段需要建立索引 经常使用聚合函数进行统计的列可以建立索引 经常使用多个条件查询时建议使用组合索引代替多个单列索引 除此之外下面这些情况不应该建立索引
数据量小的表不建议添加索引 数据类型的字段是TEXT、BLOB、BIT等数据类型的字段不建议建索引 不要在区分度低的字段建立索引比如性别字段、年龄字段等
11、索引失效的情况 索引失效指的是虽然在查询的列上添加了索引但是某些情况下查询的时候依旧没有用到索引常见的情况有
使用like关键字时模糊匹配使用开头将导致索引失效 使用连接条件时如果条件中存在没有索引的列会导致索引失效 在索引列上进行计算、函数运算、类型转换将导致索引失效 使用 !、not in、is null、is not null时会导致索引失效 使用联合索引时没有遵循最左匹配原则会导致索引失效
12、如何知道索引是否失效
MySQL中自带了一个关键字叫explain它可以加在一个sql的前面来查看这条sql的执行计划
在执行计划中我们主要观察两列的结果一列是type一列是extra
第一个type是重要的列显示本次查询使用了何种类型常见的值从坏到好依次为all、index、range、ref、eq_ref 、const、system
all表示全表扫描数据文件返回符合要求的记录其他值标识用到索引了
除了type之外我们需要关注一下extra列如果出现using index最好了它表示列数据仅仅使用了索引中的信息而没有回表查询
13、MyISAM和InnoDB的区别 MyISAM和InnoDB是目前MySQL中最为流行的两种存储引擎它们的区别有这几方面
MyISAM不支持事务每次操作都是原子的InnoDB支持事务支持事务的四种隔离级别 MyISAM不支持外键InnoDB支持外键 MyISAM仅仅支持表级锁即每次操作是对整个表加锁InnoDB支持行级锁因此可以支持写并发 MyISAM属于非聚集性索引它的数据和索引不在同一个文件中InnoDB属于聚集性索引它的数据和索引在同一个文件中 MyISAM中主键和非主键索引的数据部分都是存储的文件的指针InnoDB主键索引的数据部分存储的是表记录非主键索引的数据部分存储的是主键值
14、索引的数据结构是什么 在MySQL中索引使用的数据结构是BTreeB树是基于B树的变种它具有B树的平衡性而且树的高度更低
B树非叶子节点不存在数据只存索引因此其内部节点相对B树更小树的高度更小查询产生的I/O更少 B树查询效率更高B树使用双向链表串连所有叶子节点区间查询效率更高 B树查询效率更稳定B树每次都必须查询到叶子节点才能找到数据而B树查询的数据可能不在叶子节点也可能在这样就会造成查询的效率的不稳定
15、什么是覆盖索引什么是回表
覆盖索引是指查询使用了索引并且需要返回的列在该索引中已经全部能够找到 。
如果没有全部找到会回表查询
通过非聚簇索引找到对应的主键值到聚簇索引中查找整行数据这个过程就是回表
主键索引就是聚簇索引
16数据库中的锁有哪些
MySQL中的锁从不同维度可以分为不同的种类
1、从锁的粒度上可以分为表锁和行锁
表锁指的是会锁定修改数据所在的整个表开销小加锁快锁定粒度大发生锁冲突概率高
行锁指的是会锁定修改数据所在的行记录开销大加锁慢锁定粒度小发生锁冲突概率低
2还有两种概念上的锁是悲观锁和乐观锁
悲观锁是指一个事务在修改数据的时候总是认为别人也会修改此数据所以强制要使用锁来保证数据安全
乐观锁是指一个事务在修改数据的时候总是认为别人不会修改此数据因为不加任何锁
这种情况下万一在当前事务修改的时候数据被其它事务也修改了机会出现问题此时常用的方案是
给数据表中添加一个version列每次更新后都将这个列的值加1读取数据时将版本号读取出来
在执行更新的时候会先比较版本号如果相同则执行更新如果不相同说明此条数据已经发生了变化就放弃更新或重试
17、MySQL日志类型 MySQL的很多功能都是依靠日志来实现的比如事务回滚数据备份主从复制等等常见的日志有下面几个
binlog归档日志
负责记录对数据库的写操作一般用在主从复制过程中记录日志从库拷贝此日志做重放实现数据同步
redolog重做日志
用于确保事务的持久性。防止在发生故障的时间点尚有脏页未写入磁盘
在重启 mysql 服务的时候根据 redo log 进行重做从而达到事务的持久性这一特性
undo log 回滚日志
保存了事务发生之前的数据的一个版本可以用于回滚
18、MySQL主从复制的流程 主从复制用于MySQL主从集群的主节点向从节点同步数据主要是依靠MySQL的binLog实现的大体流程分为三步
Master 主库在事务提交时会把数据变更记录在二进制日志文件 BinLog中 从库读取主库的二进制日志文件 Binlog 写入到从库的中继日志 RelayLog slave重做中继日志中的事件将改变反映它自己的数据
19、谈谈你对sql的优化的经验 我在企业中优化Sql大体分为三步
第一查找问题sql主要手段是开启mysql的慢查询日志它会将执行时间较长的sql记录记录下来 找到sql之后我会分析出现问题的原因原因很多主要字段类型选择错误、sql语句效率低、索引失效等等 根据问题不同我会再去定具体的解决方案 简单给您说几个常见的把
确定选择的引擎是否合适
myisam适合于查询为主增删较少无事务要求的数据表
Innodb适用于有事务处理或者包括很多的更新和删除的数据表
第二表设计是否合理
单表不要有太多字段建议在20以内
合理的加入冗余字段可以提高查询速度
确定字段的数据类型是否合适
数值型字段的比较比字符串的比较效率高得多字段类型尽量使用最小、最简单的数据类型
设置合适的字符串类型char和varcharchar定长效率高varchar可变长度效率稍低varchar的长度只分配真正需要的空间
尽量使用TIMESTAMP而非DATETIME尽量设计所有字段都得有默认值尽量避免null
第三确定sql的书写是否有的题
SELECT语句务必指明字段名称避免直接使用select *
SQL语句中IN包含的值不应过多
可以用内连接就尽量不要使用外连接
使用连接连接查询来代替子查询
适用联合(UNION)来代替手动创建的临时表
表数据比较多的时候是否添加了合适的索引
表的主键、外键必须有索引
经常出现在where子句中的字段特别是大表的字段应该建立索引
经常用于排序、分组的字段应当建立索引
加上索引之后还应该使用Explain来确认索引是否生效
如果上面的几项都没有问题那可能就是因为服务器性能或者数据量过大导致的查询慢此时可以考虑读写分离
也就是我们搭建一个MySQL的主从集群让1个主节点负责写入数据多个从节点负责查询数据已分摊查询压力
Maven 和mybatis
0、Maven的作用好处
1统一项目结构
2可以做项目构建编译 compile、测试test、打包package
3依赖管理
1、Maven常见命令
clean:清除编译后的文件就是删除target文件夹
compile编译项目
test: 执行junit测试代码
package把项目打成jar包
install把打好的包放到本地仓库
deploy把打好的包放到私服上
2、说下Maven生命周期
Maven的命令是有先后顺序的执行后面的命令会自动执行前面的命令
举例 我执行了package命令就自动会执行 compile test
3、jar包冲突怎么办等讲到Maven高级再说
版本锁定
4、Mybatis中#{}和${}的区别 ${}表示的是字符串拼接#{}是预编译处理是占位符。
${}存在SQL注入问题#{}可以有效的防止SQL注入。
4、${}有SQL注入问题是不是就不会用到了
当然这也不是说${}就没有使用场景
比如如果sql中需要动态传递表名或者字段名那就只能使用${}了这种情况的值是程序员自己传过去的不是页面直接传的
5、当实体类中的属性名和表中的字段名不一样 怎么办 1、开启驼峰映射这种方式可以处理掉字段和属性满足驼峰转换规则的那部分
2、字段起别名可以在查询的SQL语句中定义字段名的别名让字段名的别名和实体类的属性名一致
3、手动映射mybatis提供了Results注解 和在xml中提供了resultMap标签它可以通过来自定义映射关系来保证字段和属性的映射
6、MyBatis动态SQL了解吗 动态SQL是为了解决SQL语句灵活性不足的问题而提出的一种技术它可以根据条件拼接SQL语句以不同的查询需求
MyBatis常用的动态SQL标签有
if 用来判断 符合条件的会拼接到sql中
where 如果没有条件时可以去除where关键字 还可以去除第一个And或or关键字
set 去除最后一个逗号
foreach 用来批量处理的 比如批量删除拼接 in后面的值
sql 定义一个sql片段 就是提取公共的sql include 引入sql片段
7、Mybatis的一级缓存和二级缓存
一级缓存是sqlSession级别的在同一个sqlSession中执行同样的sql语句时如果有缓存直接读取缓存中的数据
二级缓存是namespaceMapper级别的
一级缓存是默认开启的 二级缓存需要手动开启一般二级缓存不用
前端
1、有哪些常用的事件可以直接说过中文名
离焦事件 onblur
聚焦事件 onFocus
鼠标移上去 onmouseover
鼠标移出去 onmouseout
点击事件 onclick
表单提交 onsubmit
2、设置样式的时候有哪些常用的选择器
标签选择器
标签名{}
class类选择器
.class名字{}
id选择器
#id值{}
3、你们用的VUE哪个版本
VUE3
4、v-if和v-show的区别
都是可以控制显隐、
v-if控制的话在浏览器查看源码是看不到隐藏的内容
v-show控制的话在浏览器查看源码是可以看到隐藏的内容 display样式控制
5、VUE的生命周期
VUE对象从创建到销毁 会自动触发8个函数叫做钩子函数
我们经常用mounted 打开页面时执行查询数据的方法
6、TypeScript是什么
主要是控制JavaScript中的类型
7、做过前端吗 我们用的是ElementPlus和VUE3管理类型的页面是没有问题的 spring系列
1、谈谈你对SpringIOC的理解 IOC也叫控制反转 对象以前是我们程序员自己new的但是现在对象都是由Spring创建并放入到了IOC容器中如果需要使用某个对象的时候直接从容器中获取
两个细节1、Spring通过哪种方式创建的反射 2、创建的对象放入到哪里了ConcurrentHashMap作为IOC容器
2、Spring中有哪些依赖注入方式
依赖注入指的是Spring给对象中属性进行赋值的过程主要包括两种方式
1、Autowired 根据类型注入
2、构造器依赖注入构造器注入是指容器调用一个类的构造器创建对象时直接传入给属性赋值
Setter方法注入Setter方法注入是指容器在创建对象完成后通过调用属性的Setter 方法可以属性赋值这种是早期有xml配置时经常用。
3、你用过哪些Spring注解 我们常用的Spring注解主要分类下面几大类
1、创建对象Component、Controller、Service、Repository
它们都可以标注在自己开发的类上Spring会使用注解标注的类创建出对象然后放入容器
2、依赖注入Autowired
标注在属性或者属性对应的set方法上Spring会根据被标注属性的类型自动对属性进行赋值
3、依赖注入Qualifier
和Autowired一块使用在同一类型的bean有多个的情况下Spring会根据name进行选择注入
4、配置类Configuration、Bean
主要标注在配置类中用于声明配置类和向Spring容器中放入一些配置有关的对象
5、当然还有一些平时用的不是特别多的
比如声明注解扫描的ComponentScan声明Bean的作用域的Scope用于切面编程的AroundPointcut等等
4、SpringBean的作用域有几种 在Spring中作用域是用来对象的存活范围的它支持5种作用域
第一种是单例配置为单例的对象会跟随Spring容器创建而创建跟随Spring容器销毁而销毁在Spring容器中无论获取多少次单例对象得到的都是同一个这也是Spring中的对象的默认作用域
第二种是多例配置为多例的对象在每次获取的时候才会创建而且每次获取到的都不一样
还有三种分别是request、session和application目前已经基本不再使用
其实在我们平时的开发过程中对象基本上都是配为单例的这样可以有效的节省资源只有单例对象存在线程安全问题时才考虑调整为多例。
5、Spring中的bean线程安全吗 Spring中的Bean主要分为单例和多例默认是单例的如果单例bean有成员变量多线程操作时要同时修改这个成员变量的值就有可能出现线程不安全情况解决方式有两种
1将Bean的作用域由单例改为多例这样虽然解决了但是不推荐因为每个线程就产生一个对象并发量大的时候可以造成内存溢出 2将需要的可变成员变量保存在ThreadLocal中 ThreadLocal本身就具备线程隔离的特性这就相当于为每个线程提供了一个独立的变量副本每个线程只需要操作自己的线程副本变量从而解决线程安全问题。
6、谈谈你对SpringAOP的理解 AOP又叫面向切面编程就是在不改变原代码的基础上对原方法做增强比如做事务管理、日志、性能监视、安全检查等等
Spring AOP是基于动态代理的它底层同时支持JDK和CGLIB的代理方式并且会根据被代理类是否有接口自动选择最合适的代理方式
7、AOP的代理有几种方式 JDK动态代理和CGLIB动态代理
JDK动态代理只能对有接口的类进行代理而且效率较高 CGLIB可以对任意的类进行动态代理但是效率上不如JDK 因此在进行代理时如果被代理类有接口就用JDK如果没有接口就用CGLIB
8、Spring的通知类型有哪些
四大通知环绕通知 总共有5种
四大通知指的是
前置通知在某切点之前执行的通知 返回后通知在某切点正常完成后执行的通知 抛出异常后通知在某切点抛出异常退出时执行的通知 后置通知在某切点退出的时候执行的通知不论是正常返回还是异常退出
环绕通知可以替代四大通知
9、Spring事务传播行为有几种 事务传播行为是为了解决业务层方法之间互相调用的事务问题。
当事务方法被另一事务方法调用时必须指定事务应该如何传播。
例如方法可能继续在现有事务中运行也可能开启一个新事务并在自己的事务中运行。
Spring支持7个种事务传播行为的
必须事务如果当前存在事务则加入该事务如果当前没有事务则创建一个新的事务
必须新事务创建一个新的事务如果当前存在事务则把当前事务挂起
强制事务如果当前存在事务则加入该事务如果当前没有事务则抛出异常
支持事务如果当前存在事务则加入该事务如果当前没有事务则以非事务的方式继续运行
不支持事务以非事务方式运行如果当前存在事务则把当前事务挂起
强制无事务以非事务方式运行如果当前存在事务则抛出异常
嵌套事务如果当前存在事务则创建一个当前事务的嵌套事务来运行如果当前没有事务则创建一个事务
嵌套事务是已存在事务的一个子事务嵌套事务开始执行时将取得一个保存点
如果这个嵌套事务失败将回滚到此保存点
嵌套事务是外部事务的一部分只有外部事务结束后它才会被提交
10、Spring中的事务是如何实现的
在方法上添加Transactional注解就可以实现控制事务是基于Spring的AOP机制的
他的原理就是要保证在同一个方法中使用的是同一个Connection对象并且把这个Connection对象的事务提交方式改成手动提交这样可以统一管理事务的提交和回滚
怎么保证多个方法之间使用的是同一个Connection的把Connection放到了ThreadLocal中
11、什么情况下会导致事务失效 方法上明明有Transactional但是事务没有生效 1)、 事务的传播行为会导致事务失效举例 A方法调用B方法时 B方法的事务传播行为是REQUIRES_NEW A方法事务回滚不会把B方法的事务回滚 2)、 rollbackFor指定的异常没有包含抛出的异常 3)、 以无事务方法调用本类中的事务方法 4)、 使用了异步--多线程
12、Spring中的设计模式有哪些 工厂模式Spring使用工厂模式通过 BeanFactory和 ApplicationContext创建 bean 对象 单例模式 Spring 中的 bean 默认都是单例的 代理模式Spring 的 AOP 功能用到了 JDK 的动态代理和 CGLIB 字节码生成技术 模板方法用来解决代码重复的问题。比如 RestTemplate、jdbcTemplate、 JpaTemplate 等以 Template 结尾的对数据库操作的类它们就使用到了模板模式 观察者模式 Spring 事件驱动模型就是观察者模式很经典的一个应用。定义对象键一种一对多的依赖关系当一个对象的状态发生改变时所有依赖于它的对象都会得到通知被制动更新如 Spring 中 listener 的实现 ApplicationListener。
13、Spring是怎么解决循环依赖的
循环依赖是指A依赖BB又依赖A
这就是涉及到SpringIOC容器的三级缓存了
singletonObjects一级缓存存放完全初始化好的 Bean 的集合从这个集合中取出来的 Bean 可以立马返回
earlySingletonObjects二级缓存存放创建好但没有初始化属性的 Bean 的集合它用来解决循环依赖
singletonFactories三级缓存存放单实例 Bean 工厂的集合 singletonsCurrentlyInCreation存放正在被创建的 Bean 的集合
14、SpringBean的生命周期
具体的内容记不清了但是基本概括下来就是5点内容
构造 Bean 对象 设置 Bean 属性 执行初始化方法如果有就执行 Bean 调用 销毁 Bean
中间如果实现了一些Aware相关接口的话可以自动执行接口带的实现方法
15、SpringMVC的常用注解有哪些 我们常用的Springmvc注解主要分类下面几大类
1、用于声明Bean到Springmvc容器Controller、RestController
区别在于后者还可以将返回的集合或对象转换为JSON直接返回
2、设置请求路径RequestMapping、GetMapping、PostMapping 、PutMapping、DeleteMapping
第一个是通用的可以接收各种类型的请求后面四个只能直接对应类型的请求
3、接收请求参数
RequestBody 接收请求体中的json数据
PathViriable接收请求路径中的参数
RequestHeader接收请求头中的参数
RequestParam一般用于给参数设置默认值或者完成请求参数和controller方法参数的映射
16、SpringMVC如何处理统一异常 SpringMVC的异常处理底层是通过AOP实现的它的核心思想是将异常处理的代码和业务逻辑代码分离开来
使用它之后我们在自己的业务代码中不需要在处理异常有异常直接就上抛到框架中
框架就会将异常交给自定义的全局异常处理器中统一处理
自定义全局异常处理器会用到两个注解
RestControllerAdvice 标注在类上声明被标注的类是一个用于专门处理异常的类 ExceptionHandler 标注在异常处理类中的方法上声明被标注的方法可以处理哪些异常
springboot系列
1、项目中为什么选择SpringBoot SpringBoot简化了Spring可以快速搭建企业级项目而且开发起来效率也会更高它的主要优点如下
版本锁定SpringBoot在父工程中进行了大量常见依赖的版本锁定省去了我们查找依赖版本和解决版本冲突的麻烦 简化依赖SpringBoot以功能化的方式将需要的依赖进行组装并且允许程序员以starter的方式进行引入 简化配置SpringBoot实现了大量依赖框架的默认配置项程序员无须再进行自己配置 简化启动方式SpringBoot内置了一个tomcat使用它开发的程序无需再进行tomcat部署可直接运行 2、SpringBoot的自动装配原理 自动装配就是自动地把其他组件中的Bean装载到IOC容器中不需要开发人员再去配置文件中添加大量的配置我们只需要在SpringBoot的启动类上添加一个SpringBootApplication的注解就可以开启自动装配SpringBootApplication底层最重要的一部分是EnableAutoConfiguration这个注解来实现的它作用是
读取所有jar包中两个指定配置文件中的所有配置类(xxxxAutoConfiguration)配置类中需要使用Conditional注解来声明配置成立的必要条件
3、SpringBoot的核心注解是哪个 SpringBoot的核心注解在启动类上叫SpringBootApplication主要组合包含了以下3个注解
SpringBootConfiguration组合了Configuration注解实现配置文件的功能 EnableAutoConfiguration打开自动配置的功能也可以关闭某个自动配置的选项 ComponentScanSpring组件扫描默认会扫描启动类所在的包
4、SpringBoot中的starter是干什么的 当项目足够复杂时因为涉及的组件太多了就需要引入很多的依赖此时管理依赖就变的很麻烦
此时SpringBoot的starter就派上用场了每个starter都可以为我们提供某个服务场景所需要的一系列依赖
在导入starter之后SpringBoot主要帮我们完成了两件事情
相关组件的自动导入 相关组件的自动配置
5、SpringBoot读取配置的方式有几种 SpringBoot常见的读取配置信息的方式有两种
使用Value配合EL表达式Value(“${name}”)注解直接注入对应的值 使用ConfigurationProperties注解把对应的值绑定到一个配置对象然后将配置对象注入到需要的地方 推荐使用使用第二种方式在配置比较多的情况下操作简单可读性好
6、如何理解拦截器 拦截器是Spring提供的一种拦截机制目的是实现对指定请求路径进行拦截然后做成指定的处理
自定义一个拦截器需要实现HandlerInterceptor并重写接口中定义的3个方法
preHandle 这个方法在Controller处理请求之前被调用通过方法的返回值可以确定是否放行请求 postHandle这个方法在Controller处理请求之后被调用 afterCompletion这个方法将在整个请求结束之后被调用此方法主要用于进行资源清理
7、拦截器和过滤器的区别是什么 拦截器和过滤器都可以实现请求的拦截处理不同点有下面几个
技术栈所属不同过滤器属于JavaWeb技术依赖Servlet容器而拦截器是属于Spring的技术 拦截范围不同过滤器可以拦截所有请求而拦截器主要是针对发往controller请求 拦截位置不同过滤器在前端控制器前拦截行而拦截器在前端控制器后拦截
8、SpringBoot项目如何实现方法的异步调用 异步调用指的是a方法在调用b方法的时候无需等待b方法执行完毕就可以继续向下执行
一般用在a方法无需使用b方法返回结果的场景下可以在一定程度上提高运行效率
在SpringBoot中使用异步调用是很简单的只需要做两个操作就可以了
在启动类上添加EnableAsync注解开启异步调用支持 在被调用的方法上添加Async注解
9、SpringBoot中如何实现定时任务 在SpringBoot中使用定时任务主要有两种方式一个就是使用SpringTask另一个则是使用第三方框架Quartz
SpringTask主要是通过Scheduled注解来实现定时任务触发的格式如下
主要属性如下
fixedRate按一定的频率执行任务参数类型为long单位 ms fixedDelay上一次任务执行完后多久再执行参数类型为long单位 ms initialDelay延迟多久再第一次执行任务参数类型为 long单位 ms cron使用cron表达式指定任务在特定时间执行
10、SpringBoot中如何解决跨域问题 跨域是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的是浏览器对JavaScript实施的安全限制
当浏览器从一个域名的网页去请求另一个域名的资源时出现域名、端口、协议任一不同都属于跨域 SpringBoot解决跨域很简单执行添加一个配置类实现WebMvcConfigurer接口然后重写addCorsMappings方法即可Configuration
Redis系列
1、项目中为什么用Redis
操作速度快Redis的数据都保存在内存中相比于其它硬盘类的存储速度要快很多 数据类型丰富Redis支持 stringlistsetZsethash 等数据类型基本满足我们开发中的各种使用场景
2、Redis的数据类型有哪些 Redis最常见的数据类型有5种分别是String、List、Hash、Set、ZSet下面给您详细介绍一下
String简单的 key-value 类型最大能存储512MB数据。场景计数、缓存文章标题、微博内容等
List底层是链表特点是增删容易随机访问困难。场景发布与订阅或者说消息队列
Hash类似于Java中的HashMap适合存储对象。场景系统中对象数据的存储
Set是一种无序集合可以方便的求交、并、差集。 场景共同关注、共同粉丝、共同喜好等功能
ZSet相比于set来讲多了1个权重参数 score元素会按照score进行排序。场景各种排行榜弹幕消息
3、Redis为什么这么快 Redis之所以运行速度比较快主要是由于这样一些原因:
纯内存操作Redis的绝大部分请求是纯粹的内存操作非常快速
单线程Redis的核心部分是单线程运行的避免了不必要的上下文切换也不存在线程切换导致的 CPU消耗
使用 I/O 多路复用模型和非阻塞 IO
什么是 I/O 多路复用
I/O多路复用是指利用单个线程来同时监听多个Socket 并在某个Socket可读、可写时得到通知从而避免无效的等待充分利用CPU资源 目前的I/O多路复用都是采用的epoll模式实现它会在通知用户进程Socket就绪的同时把已就绪的Socket写入用户空间不需要挨个遍历Socket来判断是否就绪提升了性能 其中Redis的网络模型就是使用I/O多路复用结合事件的处理器来应对多个Socket请求比如提供了连接应答处理器、命令回复处理器命令请求处理器 在Redis6.0之后为了提升更好的性能在命令回复处理器使用了多线程来处理回复事件在命令请求处理器中将命令的转换使用了多线程增加命令转换速度在命令执行的时候依然是单线程
4、Redis的持久化方案 两种数据持久化的方式分别是RDB和AOF
RDB全称Redis Database Backup fileRedis数据备份文件也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后从磁盘读取快照文件恢复数据。快照文件称为RDB文件默认是保存在当前运行目录。
AOF全称为Append Only File追加文件。Redis处理的每一个写命令都会记录在AOF文件可以看做是命令日志文件
5、如何保证Redis数据与MySQL一致 我们用的是同步双写或双删 即在程序更新完新增MySQL之后后立即同步更新redis
或者mysql数据发生改变后直接删除Redis中的数据什么时候用时再加入缓存中
6、什么是缓存穿透 怎么解决
而缓存穿透指的是请求一直在查询一个数据库中不存在的数据这样缓存中没有请求就会到达数据库而数据库也没有也就没法缓存
所以每一次请求都会直接到数据库中查询这就极有可能导致数据库被压垮
常用的解决方案有两个
1查询返回的数据为空仍把这个空结果进行缓存但过期时间尽量设置稍短一些
2使用布隆过滤器将所有可能存在的数据哈希到一个足够大的 bitmap 中一个一定存在的数据会被这个 bitmap 拦截掉从而避免了对DB的查询 7、Redis的过期删除策略有哪些 Redis的过期删除策略指的是当Redis中的key过期之后在什么时候进行删除的处理方案常用的删除策略就两个
惰性删除只会在取出 key 的时候才对数据进行过期检查过期了就删除 定期删除每隔一段时间抽取一批 key执行删除过期 key 操作 两者相比定期删除对内存更加友好惰性删除对 CPU 更加友好。两者各有千秋所以 Redis 采用的是定期删除惰性/懒汉式删除。
8、Redis的内存淘汰策略有哪些 Redis的内存淘汰策略指的是当Redis的内存已经存满又有新的数据需要保存时的处理方案官方提供了8种淘汰策略no-eviction禁止驱逐数据也就是说当内存不足以容纳新写入数据时新写入操作会报错。 volatile-lru从已设置过期时间的数据集中挑选最近最少使用的数据淘汰 volatile-ttl从已设置过期时间的数据集中挑选将要过期的数据淘汰 volatile-random从已设置过期时间的数据集中任意选择数据淘汰 volatile-lfu从已设置过期时间的数据集中挑选最不经常使用的数据淘汰 allkeys-lru在所有的数据集中选择最近最少使用的数据淘汰 allkeys-random在所有的数据集中任意选择数据淘汰 allkeys-lfu在所有的数据集中选择最不经常使用的数据淘汰
其实主要记住可以删除最近最少使用的或者提前删除即将过期的
9、Redis集群有哪些方案 在Redis中提供的集群主要有三种分别是主从、哨兵和分片集群
主从集群主要用来解决Redis的并发问题一般是一个主节点负责数据写入多个从节点负责数据读取主节点的数据会实时同步给从节点
哨兵集群主要用来解决Redis的高可用问题哨兵会监控集群中节点的状态并在主节点出现问题时进行重新选主
分片集群主要用来解决Redis的海量数据存储问题它要求有多个主节点然后数据写入的数据会经过计算落到其中一个上
在这个计算的过程中Redis引入了哈希槽的概念Redis集群有16384个哈希槽每个 key通过CRC16校验后对16384取模来决定放置哪个槽
而分片集群的每个节点负责一部分 hash 槽这样就可以计算出一个key会出现在哪个节点上了查询的时候也是同时的方式来定位即可
10、什么是缓存预热 缓存预热是指系统上线后提前将相关的缓存数据加载到缓存系统。
避免在用户请求的时候先查询数据库然后再将数据缓存的问题用户直接查询事先被预热的缓存数据。
如果不进行预热那么 Redis 初始状态数据为空系统上线初期对于高并发的流量都会访问到数据库中对数据库造成流量的压力。
缓存预热解决方案主要有下面几个
数据量不大的时候工程启动的时候进行加载缓存动作 数据量大的时候设置一个定时任务脚本进行缓存的刷新 数据量太大的时候优先保证热点数据进行提前加载到缓存
11、什么是缓存击穿怎么解决
缓存击穿指的是对于一个设置了过期时间的key在其缓存失效的瞬间有大量的请求访问这个它这些请求在缓存找不到就会直接到数据库导致数据库被压垮
常用的解决方案有两个
使用互斥锁当缓存失效时不立即去数据库查询而是先去获取一把全局锁那个线程获取到了就去数据库查询获取不到的就等待重试查询缓存
修改设置key有效期的逻辑大体如下
在设置key的时候不给它设置过期时间而是单独设置一个过期时间字段一块存入缓存中
当查询的时候从redis取出数据后判断时间是否过期如果过期则开通另外一个线程进行数据同步当前线程正常返回数据
12、什么是缓存雪崩怎么解决
缓存雪崩指的是大量的key在某一时刻同时失效这样大量的请求全部转发到DBDB 瞬时压力过重雪崩
解决方案也很简单就是在设置key的过期时间的时候尽量加一些随机值这样缓存过期时间的重复率就会降低
13、用过Redis的事务吗 Redis中本身是没有事务的概念的但是他有几个命令组合起来能实现类似于事务的效果。也就是说Redis事务的本质是一组命令的集合。
这里用到的命令主要有5个分别是
MULTI用来组装一个事务 EXEC执行一个事物 DISCARD取消一个事务 WATCH用来监视一些key一旦这些key在事务执行之前被改变则取消事务的执行 UNWATCH取消 WATCH 命令对所有key的监视 总结说Redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令。Reids中单条命令式原子性执行的但事务不保证原子性且没有回滚。
Linux和docker命令
简单的有 目录结构 根目录/ /usr/local /root 查看目录 ls -la ls -l ---ll pwd 切换目录 cd ./ ../ / /root cd /usr cd ../usr 创建目录 mkdir /a/b/c -pv 删除目录(文件) rm -rf / 复制目录(文件) cp 源文件 放的位置 剪切目录(文件) mv 源文件 放的位置
高级一点的有 编辑文件 touch 文件 vi vim i------esc : w q cat 文件 查看文件 tail -f 文件压缩 (tar.gz) tar zcvf 压缩包 文件解压 tar zxvf 压缩包 文件授权 chmod 777 -R test.java 查看端口(比如8080) netstat -no|grep 8080 查看进程(比如tomcat) ps -ef|grep tomcat 强杀进程 kill -9 进程id
Docker
docker search 镜像名称 ----------------- 从网上搜索镜像 docker pull 镜像名称:tag -----------------从网上下载镜像 docker images -----------------查看宿主机上已经有的镜像 docker run -d --name容器名称 -p 宿主机端口号容器的端口号 -v 宿主机目录容器的目录 镜像名称 ----------------- 以哪个镜像启动容器 docker ps ----------------- 查看正在运行的容器 docker ps -a ----------------- 查看所有的容器 docker rm 容器名称 or 容器ID ----------------- 删除容器 docker rm -f 容器名称 or 容器ID ----------------- 强制删除容器 docker stop|start|restart 容器名称 ----------------- 停止|启动|重启容器 docker load -i 镜像.tar ----------------- 解压镜像的压缩包 docker exec -it 容器名称 bash | sh -----------------以交互式方式进入容器中 docker inspect 容器名称 -----------------查看容器的详细信息 docker logs 容器名称 -----------------查看容器的运行日志
Dockerfile ----------------- 制作镜像 Docker-compose.yml ----------------- 批量管理容器 docker compose up -d 启动容器 docker compose down 关闭并移除容器 docker compose stop 仅仅关闭容器
springcloud系列
1、怎么保证消息的可靠性怎么保证消息不丢失
消息发送方开启消息确认机制如果消息发送失败记录日志log文件table表
MQ本身交换机、队列、发送的消息都要持久化 使用SpringBoot开发 默认都是持久化的
消息消费方开启确认机制 auto模式 以及设置重试次数到达重试次数后把消息放到一个error队列中
2、消息重复消费怎么解决怎么保证消息幂等性
发送消息时给消息设置id在消息转换器那里设置消费成功后把消息id放到Redis中再次消费时先从Redis根据消息id获取如果获取到了证明这个消息已经消费过了如果没有获取到证明没有消费过继续消费就可以了
3、消息出现堆积怎么办
1、消费方开启多线程 2、消费方集群部署 3、Lazy Queue惰性队列
4、是否了解死信队列有什么用
1、超时未处理的消息会变成死信死信需要发送到死信交换机再路由到死信队列实现延迟任务
最终借助了MQ的插件实现了延迟任务
5、在项目中你们使用的是MQ的哪种模式
Direct 消息发送到交换机、通过key路由到队列 Topickey支持通配符 #
6、你们为什么不用RocketMQ | Kafka
不知道啊领导定的啊~11
1、常用SpringCloud的组件
1、Nacos 注册中心和配置中心 2、OpenFeign 远程调用 3、LoadBalancer 负载均衡的 Ribbon2021之前的版本 4、Gateway 网关 5、Sentinel 服务保护 限流 现成隔离 熔断 降级方法需要写代码 6、Seata 分布式事务涉及到多个数据源 XA 执行SQL后事务不提交统一提交或回滚 AT 执行SQL后事务提交并记录数据改变之前和之后的数据放到undo_log表中
2、OpenFeign工作原理 Feign是SpringCloud技术栈中用于远程调用的一个HTTP客户端主要作用是将远程服务调用格式本地方法调用格式统一成一致的
Feign的工作步骤如下
1)、首先需要在SpringBoot的启动类上添加EnableFeignClients 注解开启对Feign的支持
2、创建一个Feign的Interface接口接口上需要添加一个FeignClient的注解注解中value值是需要调用的微服务的名字
3、在接口中创建方法创建的方法要和即将调用的方法 请求路径、请求方式, 请求参数、返回类型保持一致 3、什么是Sentinel他能做什么
他是SpringCloudAlibaba下的一个用来做服务保护的组件
限流、线程隔离、熔断、还可以支持降级方法
4、LoadBalancer的负载均衡策略有哪些 官方提供了好几种负载均衡策略
轮询策略按照一定的顺序依次调用服务实例 权重策略根据每个服务提供者的响应时间分配一个权重响应时间越长权重越小被选中的可能性也就越低。它的实现原理是刚开始使用轮询策略并开启一个计时器每一段时间收集一次所有服务提供者的平均响应时间然后再给每个服务提供者附上一个权重权重越高被选中的概率也越大。 随机策略从服务提供者的列表中随机选择一个服务实例
5、Nacos作为注册中心工作原理 Nacos是SpringCloudAlibaba技术栈的一项技术在项目中主要用作服务注册中心和服务配置中心
Nacos做服务注册中心主要具备下面这些能力
服务注册服务提供者会将自己的地址信息注册到Nacos中在nacos中形成一张服务清单
服务发现服务消费者会从Nacos中查询服务提供者的信息并且缓存到本地并且每隔30s更新一次
当服务提供者的地址发生变化之后Nacos也会主动推送最新的地址信息给消费者
服务续约服务提供者会间隔一定时间就给Nacos发送心跳表明自己在线服务剔除当nacos一段时间内接收不到服务微服务的续约请求时或者收到微服务的下线请求时就会将服务地址从服务清单中删除
jvm基本认知 JVM的主要组成部分有哪些? 作用是什么? 类加载器ClassLoader: 负责将字节码文件加载到内存中 运行时数据区Runtime Data Area: 用于保存java程序运行过程中需要用到的数据和相关信息 执行引擎Execution Engine: 字节码文件并不能直接交给底层操作系统去执行因此需要特定的命令解析器执行引擎将字节码翻译成底层系统指令 本地库接口Native Interface: 会被执行引擎调用参与字节码的翻译 JVM运行时数据区包含几部分? 每部分的作用是什么? java中都有哪些类加载器? 3 启动类加载器 扩展类加载器 应用程序类加载器 什么是双亲委派模型? 双亲委派模型针对的是 Java 虚拟机中三个类加载器的这三个类加载器分别是
启动类加载器Bootstrap ClassLoader
扩展类加载器Extension ClassLoader
应用程序类加载器Application ClassLoader 类装载的执行过程是怎样的? 类从被加载到虚拟机内存中开始直到卸载出内存为止整个生命周期包括了7个阶段加载、验证、准备、解析、初始化、使用、卸载 加载: 这个阶段会在内存中生成一个代表这个类的java.lang.Class对象 验证: 这个阶段的主要目的是为了确保Class文件包含的信息符合当前虚拟机的要求并且不会危害虚拟机自身的安全 准备: 这个阶段正式为类变量分配内存并设置类变量的初始值注意这里的初始值指的是默认值而不是代码后的实际值 解析: 这个阶段将符号引用替换为直接引用比如方法中调用了其他方法方法名可以理解为符号引用而直接引用就是使用指针直接引用方法 初始化: 这个阶段是执行类构造器方法的过程是类加载的最后一步到了这一步Java虚拟机才开始真正执行类中定义的Java程序代码(字节码) 使用: 这个节点程序在运行 卸载: 这个阶段类Class对象被GC 怎么判断对象是否可以被回收? 可达性分析算法 Roots 通过一系列为GC Roots的对象作为起始点从这些节点开始向下搜索搜索所走过的路径称为引用链 当一个对象到GC Roots没有任何引用链相连时则证明该对象是不可用的。 JVM有哪些垃圾回收算法? 标记-清除 标记-整理-清除 复制 分代