面试总结
微服务就是可以把一个项目中不同的功能进行拆分,使得各个模块进行独立,
注册中心的作用是使得服务与服务之间可以事实感知其他服务在上面位置,别的服务想要调用的时候可以从注册中心获取到他的地址列表,然后给对方发送请求就可以了,
配置中心的作用就是服务上线以后修改配置方便,不需要从新部署打包发布服务。
使用fein组件来实现服务之间的数据调用
想要调用远程服务首先得必须在注册中心中,然后必须开启远程调用功能,并且编写接口告诉spring cloud这个接口需要调用远程服务,声明接口的每一个方法都是调用哪个远程服务的那个请求
1 nacos
该项目使用了微服务注册中心nacos来进行注册发现,单体服务都会通过配置文件注册到注册中心里面,使得服务之间可以发现对方,使用@EnableDiscoveryClient注解开启服务注册与发现功能
并且使用了nacas的配置中心,使得需要改配置的时候直接在nacos改,不需要在去项目里面进行修改,重新打包部署
2 fein
使用fein组件来实现服务之间的数据调用
想要调用远程服务首先得必须在注册中心中,然后必须开启远程调用功能,并且编写接口告诉spring cloud这个接口需要调用远程服务,声明接口的每一个方法都是调用哪个远程服务的那个请求
导入fein的依赖,开启fein的远程调用功能@EnableFeignClients,然后编写远程接口指定调用哪个服务调用哪个请求
3 gateway
所有的请求都会先发给网关,网关代理给其他服务,可以在网关统一配置跨域问题
Gateway由三部分组成
1 Route :路由
2 Predicate:断言
3 Filter : 过滤器
当请求到达网关,网关先断言,来判断是否符合路由规则,如果符合,就先经过过滤器之后去指定位置
4 vue
<template>
<div></div>
</template>
<script>
//这里可以导入其他文件(比如:组件,工具 js,第三方插件 js,json 文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
export default {
//import 引入的组件需要注入到对象中才能使用
components: {},
props: {},
data() {
//这里存放数据
return {
};
},
//计算属性 类似于 data 概念
computed: {},
//监控 data 中的数据变化
watch: {},
//方法集合
methods: {
},
//生命周期 - 创建完成(可以访问当前 this 实例)
created() {
},
//生命周期 - 挂载完成(可以访问 DOM 元素)
mounted() {
},
beforeCreate() {}, //生命周期 - 创建之前
beforeMount() {}, //生命周期 - 挂载之前
beforeUpdate() {}, //生命周期 - 更新之前
updated() {}, //生命周期 - 更新之后
beforeDestroy() {}, //生命周期 - 销毁之前
destroyed() {}, //生命周期 - 销毁完成
activated() {}, //如果页面有 keep-alive 缓存功能,这个函数会触发
}
</script>
<style lang='scss' scoped>
//@import url(); 引入公共 css 类
</style>
5 redis缓存
Redis支持五种数据类型:
string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
请求过来——读取缓存数据——命中——返回结果——结束
——未命中——查询数据库——将数据放入缓存——返回查询结果
1解决外部缓存溢出
1 升级lettuce版本
2使用jedis操作redis的底层客户端
2 缓存穿透
查询一个一定不存在的数据,就是出现缓存穿透,因为没有将空结果写入缓存
3缓存雪崩
指的是我们设置相同的过期时间,缓存同一时刻失效,请求全部转发到db,导致雪崩,在原有失效时间的基础上增加一个随机值,比如1-5分钟,降低缓存同时失效的概率
4缓存击穿
对于一些热点数据,就是在某一时刻会超高并发的访问,如果大量请求的同时key过期了,就会缓存击穿
可以使用加锁,只让一个人来查数据库,查询完成之后添加缓存,释放锁,第二个人拿到锁之后先查缓存,缓存中有就不查数据库了
5 spring cache 操作缓存里面的增删改查
一个cachemanager管理多个cache缓存,通过cache来进行增删改查
###6 压力测试
使用Apache JMeter进行压力测试,jvisualvm进行性能监控
7 锁
1 本地锁 synchronized(this){
}
2 分布式锁 redisson
8 数据持久化
1、Redis实现数据持久化的两种实现方式:
RDB:指定的时间间隔内保存数据快照
AOF:先把命令追加到操作日志的尾部,保存所有的历史操作
9 redis删除机制
1 定期删除:redis每隔一段时间就会去查看redis,设置了过期时间的key,会在100ms的间隔内默认查看3个key
2 惰性删除:如果去查询一个已经过期的key,redis会先查看当前key的生存时间,如果过了生存时间redis会立即删除
当然无论redis删除没删除外界都查不到,只是没删除的话还占着内存
1.2. 隔离级别
事务并发引起一些读的问题:
-
脏读 一个事务可以读取另一个事务未提交的数据
-
不可重复读 一个事务可以读取另一个事务已提交的数据 单条记录前后不匹配
-
虚读(幻读) 一个事务可以读取另一个事务已提交的数据 读取的数据前后多了点或者少了点
并发写:使用mysql默认的锁机制(独占锁)
解决读问题:设置事务隔离级别
-
read uncommitted(0)
-
read committed(2)
-
repeatable read(4)
-
Serializable(8)
隔离级别越高,性能越低。
一般情况下:脏读是不可允许的,不可重复读和幻读是可以被适当允许的。
2.1. 分布式事务基础
Seata有3个基本组件:
- Transaction Coordinator(TC):事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚。
- Transaction Manager™:事务管理器,控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议。
- Resource Manager(RM):资源管理器,控制分支事务,负责分支注册、状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚。
Seata管理分布式事务的典型生命周期:
-
TM 向 TC 申请开启一个全局事务,全局事务创建成功并生成一个全局唯一的 XID。
-
XID 在微服务调用链路的上下文中传播。
-
RM 向 TC 注册分支事务,将其纳入 XID 对应全局事务的管辖。
-
TM 向 TC 发起针对 XID 的全局提交或回滚决议。
-
TC 调度 XID 下管辖的全部分支事务完成提交或回滚请求。
6、java 基础面试题
1、java基础
1、 java 基本类型和引用类型的区别
2、java关键字什么时候使用
1 static
2、final
3 this
4 super
3 抽象类与接口的区别
4 ==与 equals的区别
1. java 中操作字符串都有哪些类?它们之间有什么区别?
操作字符串的类有:String、StringBuffer、StringBuilder。
String 和 StringBuffer、StringBuilder 的区别在于 String 声明的是不可变的对象,每次操作都会生成新的 String 对象,然后将指针指向新的 String 对象,而 StringBuffer、StringBuilder 可以在原有对象的基础上进行操作,所以在经常改变字符串内容的情况下最好不要使用 String。
StringBuffer 和 StringBuilder 最大的区别在于,StringBuffer 是线程安全的,而 StringBuilder 是非线程安全的,但 StringBuilder 的性能却高于 StringBuffer,所以在单线程环境下推荐使用 StringBuilder,多线程环境下推荐使用 StringBuffer。
2. String 类的常用方法都有那些?
- indexOf():返回指定字符的索引。
- charAt():返回指定索引处的字符。
- replace():字符串替换。
- trim():去除字符串两端空白。
- split():分割字符串,返回一个分割后的字符串数组。
- getBytes():返回字符串的 byte 类型数组。
- length():返回字符串长度。
- toLowerCase():将字符串转成小写字母。
- toUpperCase():将字符串转成大写字符。
- substring():截取字符串。
- equals():字符串比较。
7 事务
1.1. 基本概念
事务的概念:事务是逻辑上一组操作,组成这组操作各个逻辑单元,要么一起成功,要么一起失败。
事务的四个特性(ACID):
-
原子性(atomicity):“原子”的本意是“不可再分”,事务的原子性表现为一个事务中涉及到的多个操作在逻辑上缺一不可。事务的原子性要求事务中的所有操作要么都执行,要么都不执行。
-
一致性(consistency):“一致”指的是数据的一致,具体是指:所有数据都处于满足业务规则的一致性状态。一致性原则要求:一个事务中不管涉及到多少个操作,都必须保证事务执行之前数据是正确的,事务执行之后数据仍然是正确的。如果一个事务在执行的过程中,其中某一个或某几个操作失败了,则必须将其他所有操作撤销,将数据恢复到事务执行之前的状态,这就是回滚。
-
隔离性(isolation):在应用程序实际运行过程中,事务往往是并发执行的,所以很有可能有许多事务同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。隔离性原则要求多个事务在并发执行过程中不会互相干扰。
-
持久性(durability):持久性原则要求事务执行完成后,对数据的修改永久的保存下来,不会因各种系统错误或其他意外情况而受到影响。通常情况下,事务对数据的修改应该被写入到持久化存储器中。
2 容器集合
常用容器的图录:
1Collection 是单列集合
1 List 元素是有序的、可重复
有序的 collection,可以对列表中每个元素的插入位置进行精确地控制。
可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
可存放重复元素,元素存取是有序的。
List接口中常用类
Vector: 线程安全,但速度慢,已被ArrayList替代。
底层数据结构是数组结构
ArrayList:线程不安全,查询速度快。
底层数据结构是数组结构
linkedList:线程不安全。增删速度快。
底层数据结构是列表结构
2Set(集) 元素无序的、不可重复。
取出元素的方法只有迭代器。不可以存放重复元素,元素存取是无序的。
Set接口中常用的类
HashSet:线程不安全,存取速度快。
底层数据结构是哈希表(哈希表:数据+链表/红黑树)。
哈希表依赖两个方法:hashCode()和equals()
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终:
自动生成hashCode()和equals()即可
LinkedHashSet
底层数据结构由链表和哈希表组成。 由链表保证元素有序。 由哈希表保证元素唯一。
TreeSet:线程不安全,可以对Set集合中的元素进行排序。
底层数据结构是红黑树。(是一种自平衡的二叉树)
如何保证元素唯一性呢?
根据比较的返回值是否是0来决定
如何保证元素的排序呢?
两种方式
自然排序(元素具备比较性)
让元素所属的类实现Comparable接口
比较器排序(集合具备比较性)
让集合接收一个Comparator的实现类对象
3 Map 是一个双列集合
A:Map集合的数据结构仅仅针对键有效,与值无关。
B:存储的是键值对形式的元素,键唯一,值可重复
Hashtable:线程安全,速度慢
底层数据结构是哈希表。线程安全,效率低
哈希表依赖两个方法:hashCode()和equals()
执行顺序:
首先判断hashCode()值是否相同
是:继续执行equals(),看其返回值
是true:说明元素重复,不添加
是false:就直接添加到集合
否:就直接添加到集合
最终:
自动生成hashCode()和equals()即可
不允许null作为键,null作为值。
|–Properties:用于配置文件的定义和操作,使用频率非常高,同时键和值都是字符串。
是集合中可以和IO技术相结合的对象。(到了IO在学习它的特有和io相关的功能。)
HashMap:线程不安全,速度快
HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。
当我们往Hashmap中put元素时,首先根据key的hashcode重新计算hash值,根绝hash值得到这个元素在数组中的位置(下标),如果该数组在该位置上已经存放了其他元素,那么在这个位置上的元素将以链表的形式存放,新加入的放在链头,最先加入的放入链尾.如果数组中该位置没有元素,就直接将该元素放到数组的该位置上。
需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn)
LinkedHashMap: 可以保证HashMap集合有序。存入的顺序和取出的顺序一致。
底层数据结构由链表和哈希表组成。 由链表保证元素有序。 由哈希表保证元素唯一
TreeMap:可以用来对Map集合中的键进行排序.
底层数据结构是红黑树。(是一种自平衡的二叉树)
如何保证元素唯一性呢?
根据比较的返回值是否是0来决定
如何保证元素的排序呢?
两种方式
自然排序(元素具备比较性)
让元素所属的类实现Comparable接口
比较器排序(集合具备比较性)
让集合接收一个Comparator的实现类对象
3List、Set、Map 之间的区别是什么?
4HashMap 和 Hashtable 有什么区别?
-
hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
-
hashTable同步的,而HashMap是非同步的,效率上比hashTable要高。
-
hashMap允许空键值,而hashTable不允许
12在 Queue 中 poll()和 remove()有什么区别?
poll() 和 remove() 都是从队列中取出一个元素,但是 poll() 在获取元素失败的时候会返回空,但是 remove() 失败的时候会抛出异常。
13哪些集合类是线程安全的?
- vector:就比arraylist多了个同步化机制(线程安全),因为效率较低,现在已经不太建议使用。在web应用中,特别是前台页面,往往效率(页面响应速度)是优先考虑的。
- statck:堆栈类,先进后出。
- hashtable:就比hashmap多了个线程安全。
- enumeration:枚举,相当于迭代器。
14迭代器 Iterator 是什么?
迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构。迭代器通常被称为“轻量级”对象,因为创建它的代价小。
15Iterator 怎么使用?有什么特点?
Java中的Iterator功能比较简单,并且只能单向移动:
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
10 创建线程池有哪几种方式?**
①. newFixedThreadPool(int nThreads)
创建一个固定长度的线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程规模将不再变化,当线程发生未预期的错误而结束时,线程池会补充一个新的线程。
②. newCachedThreadPool()
创建一个可缓存的线程池,如果线程池的规模超过了处理需求,将自动回收空闲线程,而当需求增加时,则可以自动添加新线程,线程池的规模不存在任何限制。
③. newSingleThreadExecutor()
这是一个单线程的Executor,它创建单个工作线程来执行任务,如果这个线程异常结束,会创建一个新的来替代它;它的特点是能确保依照任务在队列中的顺序来串行执行。
④. newScheduledThreadPool(int corePoolSize)
创建了一个固定长度的线程池,而且以延迟或定时的方式来执行任务,类似于Timer。
https://blog.csdn.net/l_kanglin/article/details/57411851)
13在 java 程序中怎么保证多线程的运行安全?**
线程安全在三个方面体现:
- 原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作,(atomic,synchronized);
- 可见性:一个线程对主内存的修改可以及时地被其他线程看到,(synchronized,volatile);
- 有序性:一个线程观察其他线程中的指令执行顺序,由于指令重排序,该观察结果一般杂乱无序,(happens-before原则)。
14多线程锁的升级原理是什么?**
在Java中,锁共有4种状态,级别从低到高依次为:无状态锁,偏向锁,轻量级锁和重量级锁状态,这几个状态会随着竞争情况逐渐升级。锁可以升级但不能降级。
锁升级的图示过程:
锁共有4种状态详解: 【Java多线程策略 一】锁的三种状态切换
15什么是死锁?**
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。是操作系统层面的一个错误,是进程死锁的简称,最早在 1965 年由 Dijkstra 在研究银行家算法时提出的,它是计算机操作系统乃至整个并发程序设计领域最难处理的问题之一。
16怎么防止死锁?**
死锁的四个必要条件:
- 互斥条件:进程对所分配到的资源不允许其他进程进行访问,若其他进程访问该资源,只能等待,直至占有该资源的进程使用完成后释放该资源
- 请求和保持条件:进程获得一定的资源之后,又对其他资源发出请求,但是该资源可能被其他进程占有,此事请求阻塞,但又对自己获得的资源保持不放
- 不可剥夺条件:是指进程已获得的资源,在未完成使用之前,不可被剥夺,只能在使用完后自己释放
- 环路等待条件:是指进程发生死锁后,若干进程之间形成一种头尾相接的循环等待资源关系
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之 一不满足,就不会发生死锁。
理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和 解除死锁。
所以,在系统设计、进程调度等方面注意如何不让这四个必要条件成立,如何确 定资源的合理分配算法,避免进程永久占据系统资源。
此外,也要防止进程在处于等待状态的情况下占用资源。因此,对资源的分配要给予合理的规划。
17说一下 synchronized 底层实现原理?**
synchronized可以保证方法或者代码块在运行时,同一时刻只有一个方法可以进入到临界区,同时它还可以保证共享变量的内存可见性。
Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:
- 普通同步方法,锁是当前实例对象
- 静态同步方法,锁是当前类的class对象
- 同步方法块,锁是括号里面的对象
18synchronized 和 volatile 的区别是什么?**
- volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取; synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
- volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。
- volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。
- volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
- volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。
19synchronized 和 Lock 有什么区别?**
-
首先synchronized是java内置关键字,在jvm层面,Lock是个java类;
-
synchronized无法判断是否获取锁的状态,Lock可以判断是否获取到锁;
-
synchronized会自动释放锁(a 线程执行完同步代码会释放锁 ;b 线程执行过程中发生异常会释放锁),Lock需在finally中手工释放锁(unlock()方法释放锁),否则容易造成线程死锁;
-
用synchronized关键字的两个线程1和线程2,如果当前线程1获得锁,线程2线程等待。如果线程1阻塞,线程2则会一直等待下去,而Lock锁就不一定会等待下去,如果尝试获取不到锁,线程可以不用一直等待就结束了;
-
synchronized的锁可重入、不可中断、非公平,而Lock锁可重入、可判断、可公平(两者皆可);
-
Lock锁适合大量同步的代码的同步问题,synchronized锁适合代码少量的同步问题。
4Springmvc运行流程描述:
- 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;
- DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
- DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter;(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(…)方法)
- 提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
1、HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
2、数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
3、数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
4、数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
- Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
- 根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;
- ViewResolver 结合Model和View,来渲染视图;
- 将渲染结果返回给客户端。
5spring mvc 有哪些组件?
Spring MVC的核心组件:
- DispatcherServlet:中央控制器,把请求给转发到具体的控制类
- Controller:具体处理请求的控制器
- HandlerMapping:映射处理器,负责映射中央处理器转发给controller时的映射策略
- ModelAndView:服务层返回的数据和视图层的封装类
- ViewResolver:视图解析器,解析具体的视图
- Interceptors :拦截器,负责拦截我们定义的请求然后做处理工作
7 mybatis
1说一下 mybatis 的一级缓存和二级缓存?
一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;
对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。
8 mysql
注明 普通索引:仅加速查询
唯一索引:加速查询 + 列值唯一(可以有null)
主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
全文索引:对文本的内容进行分词,进行搜索
1数据库的三范式是什么?
第一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项。
第二范式:要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。
第三范式:任何非主属性不依赖于其它非主属性。
2说一下 ACID 是什么?
Atomicity(原子性):一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。
Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
3mysql 的内连接、左连接、右连接有什么区别?
内连接关键字:inner join;左连接:left join;右连接:right join。
内连接是把匹配的关联数据显示出来;左连接是左边的表全部显示出来,右边的表显示出符合条件的数据;右连接正好相反。
4mysql 索引是怎么实现的?
索引是满足某种特定查找算法的数据结构,而这些数据结构会以某种方式指向数据,从而实现高效查找数据。
具体来说 MySQL 中的索引,不同的数据引擎实现有所不同,但目前主流的数据库引擎的索引都是 B+ 树实现的,B+ 树的搜索效率,可以到达二分法的性能,找到数据区域之后就找到了完整的数据结构了,所有索引的性能也是更好的。
5. MySQL/InnoDB中的事务隔离级别
SQL标准中的事务四种隔离级别
隔离级别 | 脏读(Dirty Read) | 不可重复读(NonRepeatable Read) | 幻读(Phantom Read) |
---|---|---|---|
未提交读(Read uncommitted) | 可能 | 可能 | 可能 |
已提交读(Read committed) | 不可能 | 可能 | 可能 |
可重复读(Repeatable read) | 不可能 | 不可能 | 可能 |
可串行化(Serializable ) | 不可能 | 不可能 | 不可能 |
- 未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
- 提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
- 可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
- 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
未提交读(Read uncommitted)
数据库一般都不会用,而且任何操作都不会加锁
5 说一下 mysql 的行锁和表锁?
MyISAM 只支持表锁,InnoDB 支持表锁和行锁,默认为行锁。
表级锁:开销小,加锁快,不会出现死锁。锁定粒度大,发生锁冲突的概率最高,并发量最低。
行级锁:开销大,加锁慢,会出现死锁。锁力度小,发生锁冲突的概率小,并发度最高。
6说一下乐观锁和悲观锁?
乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。
悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。
数据库的乐观锁需要自己实现,在表里面添加一个 version 字段,每次修改成功值加 1,这样每次修改的时候先对比一下,自己拥有的 version 和数据库现在的 version 是否一致,如果不一致就不修改,这样就实现了乐观锁。
7 mysql 问题排查都有哪些手段?
使用 show processlist 命令查看当前所有连接信息。
使用 explain 命令查询 SQL 语句执行计划。
开启慢查询日志,查看慢查询的 SQL。
8如何做 mysql 的性能优化?
为搜索字段创建索引。
避免使用 select *,列出需要查询的字段。
垂直分割分表。
选择正确的存储引擎。
7 liunx常用命令
1 操作文件命令[重点]
# 0.cd 用来切换目录
# 1.pwd 显示当前工作目录(print working directory)
# 2.touch 创建空文件
# 3.mkdir 创建目录(make directoriy)
-p 父目录不存在情况下先生成父目录 (parents)
# 4.cp 复制文件或目录(copy)
cp 文件名 目录 复制文件到指定目录中
cp -r 目录名 目录 复制指定目录到指定目录中
-r 递归处理,将指定目录下的文件与子目录一并拷贝(recursive)
# 5.mv 移动文件或目录、文件或目录改名(move)
mv 文件名 新文件名 文件改名
mv 文件名 目录名 文件移动
mv 目录名 不存在目录名 目录改名
mv 目录名 已存在目录名 目录移动
# 6.rm 删除文件(remove)
-r 同时删除该目录下的所有文件(recursive)
-f 强制删除文件或目录(force)
# 7.rmdir 删除空目录(remove directoriy)
# 8.cat 显示文本文件内容 (catenate) 用来展示少量内容
# 9.more、less 分页显示文本文件内容 退出用q退出
# 10.head、tail查看文本中开头或结尾部分的内容
head -n 5 a.log 查看a.log文件的前5行
# 11.tail -f b.log 循环读取(fellow)
# 12.echo 输出命令
echo I love baby 说明:用来向屏幕输出一句话
echo I Love baby >> aa.txt 说明:将这段内容输入到 文件中
10 docker
1 镜像(image)
Docker 镜像(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。
容器(container)
Docker 利用容器(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。
它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。
可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
3仓库(repository)
仓库(Repository)是集中存放镜像文件的场所。
仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
仓库分为公开仓库(Public)和私有仓库(Private)两种形式。
最大的公开仓库是 Docker Hub(https://hub.docker.com/),
存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云 等
4小结
需要正确的理解仓储/镜像/容器这几个概念:
Docker 本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就似乎 image镜像文件。只有通过这个镜像文件才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。
- image 文件生成的容器实例,本身也是一个文件,称为镜像文件。
- 一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,也就是我们的容器
- 至于仓储,就是放了一堆镜像的地方,我们可以把镜像发布到仓储中,需要的时候从仓储中拉下来就可以了。
5架构图
6daocker 命令
### 1 列出本地主机上的镜像 docker images
### 2 查找镜像 docker search 某个X镜像名字 docker search [OPTIONS] 镜像名字
### 3 下载镜像
docker pull 某个X镜像名字
docker pull 镜像名字[:TAG]
### 4 删除镜像
1. docker rmi -f 镜像ID
2. docker rmi -f 镜像名1:TAG 镜像名2:TAG
3. docker rmi -f $(docker images -qa)
### 5 提交镜像
docker commit提交容器副本使之成为一个新的镜像
docker commit -m=“提交的描述信息” -a=“作者” 容器ID 要创建的目标镜像名:[标签名]
### 1 新建并启动容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
### 2 列出当前所有正在运行的容器
docker ps [OPTIONS]
7 数据持久化
容器的持久化
容器间继承+共享数据
1 直接命令添加
-
命令 : docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
docker run -it -v /宿主机目录:/容器内目录 centos /bin/bash
11 ES
要的时候从仓储中拉下来就可以了。
5架构图
[外链图片转存中…(img-hNu2pDE7-1704263973857)]
6daocker 命令
### 1 列出本地主机上的镜像 docker images
### 2 查找镜像 docker search 某个X镜像名字 docker search [OPTIONS] 镜像名字
### 3 下载镜像
docker pull 某个X镜像名字
docker pull 镜像名字[:TAG]
### 4 删除镜像
1. docker rmi -f 镜像ID
2. docker rmi -f 镜像名1:TAG 镜像名2:TAG
3. docker rmi -f $(docker images -qa)
### 5 提交镜像
docker commit提交容器副本使之成为一个新的镜像
docker commit -m=“提交的描述信息” -a=“作者” 容器ID 要创建的目标镜像名:[标签名]
### 1 新建并启动容器
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
### 2 列出当前所有正在运行的容器
docker ps [OPTIONS]
7 数据持久化
容器的持久化
容器间继承+共享数据
1 直接命令添加
-
命令 : docker run -it -v /宿主机绝对路径目录:/容器内目录 镜像名
docker run -it -v /宿主机目录:/容器内目录 centos /bin/bash