java面试题(持续更新)
java 基础
java面向对象有哪些特征
面向对象的三大特征:封装、继承、多态
封装:隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据,封装性也提高了代码的可复用性
继承:从已有的类中派生出新的类,新的类吸收已有类的数据属性和行为,并扩展新的能力,java中通过extend关键字实现继承,父类中被private修饰的变量和方法不会被继承,不能在子类中直接操作父类中被private修饰的变量和方法,同时子类不能继承父类的构造方法
多态:多态指的是类和类的关系,两个类有继承关系,存在方法重写,在调用时有父类引用指向子类,所以多态的三个要素是:继承、重写、父类引用指向子类对象
ArrayList和LinkList的区别
ArraList和LinkList都实现了List接口
ArraList是基于索引的数据结构,他的底层是数组,
他可以以O(1)时间复杂度对元素进行随机访问,
而LinkList是以元素链表的形式存储他的数据,
这种情况下,查找某个元素的时间复杂度是O(n)
相对于ArrayList来说,他的插入、添加、删除操作速度更快,
因为当元素被添加到集合的任意位置的时候,不需要重写计算大小或者是更新索引
java接口和抽象类有哪些区别
他们都不能被实例化出来,可以将接口和抽象类作为引用类型,一个抽象类被继承或者接口被实现,需要实现其中的抽象方法。接口不能有构造方法,但抽象类可以,抽象类可以有抽象方法或者具体方法,接口只能有抽象方法,接口中不能有静态方法,一个类可以实现多个接口,但一个类只能继承一个抽象类,接口中定义的成员变量实际上都是常量
String、StringBuffer、StringBuilder的区别和应用场景
String是只读字符串,是不可变的,StringBuffer/StringBuilder是可变的,
StringBuffer和StringBuilder中方法完全相同,
区别在于StringBuffer是线程安全的,他的所有方法都被synchronized所修饰
ABA问题
如何避免ABA问题
可以通过版本号或者加时间戳解决
class的初始化过程?
类加载的过程大致分为,加载、验证、准备、解析、初始化几个阶段,
类加载机制是什么?
java虚拟机一般使用java类的流程为:
首先将开发者编写的java源代码编译成java字节码(.class文件),
然后类加载器会读取这个.class的文件,并转化成java.lang.class的实例,
有了该实例后,java虚拟机可以利用newInstance之类的方法创建真正的对象了
concurrentHashMap的底层原理
根据版本不同数据结构也不太相同
1.7:内部主要是一个segment数组,而数组的每一项又是一个HashEntry数组,
元素都存在HashEntry数组里,因为每次锁定的是Segment对象,
所以又叫做分段锁
1.8:与hashmap一样,采用:数组+链表+红黑树
底层原理则是采用锁链表或者红黑树结点,相比于HashTable的方发锁,力度更细,是对数组中的桶的头结点进行锁定,这样锁定,只会影响数组当前下标的数据,不会影响其他下标结点的操作,可以提高读写效率
put的过程:
HashMap在put方法中,它使用hashCode()和equals()方法。
当我们通过传递key-value对调用put方法的时候,HashMap使用Key hashCode()和哈希算法来找出存储key-value对的索引。
如果索引处为空,则直接插入到对应的数组中,
否则,判断是否是红黑树,若是,则红黑树插入,否则遍历链表,
若长度不小于8,则将链表转为红黑树,转成功之后 再插入
GC如何判断对象可以被回收?
1.引用计数法(已被淘汰)
2.可达性分析算法(根引用)
不同引用类型的回收机制也是不一样的
1.强引用:通过关键字new的对象都是强引用对象,强引用指向的对象任何时候都不会被回收,宁愿OOM(内存泄漏)也不会被回收
2.软引用,如果一个对象持有软引用,呢么当JVM堆空间不足时,会被回收,一个类的软引用可以通过java.lang.ref.SoftReference持有
3.弱引用,如果一个对象持有弱引用,呢么在GC时,只要发现弱引用就会被回收,一个类的软引用可以通过java.lang.ref.WeakReference持有
4.虚引用,几乎和没有一样,随时可以被回收,通过OhantomReference持有
java的类加载器
1.Bootstrap类加载器
2.Extention类加载器
3.Application类加载器
4.Custom自定义类加载器
JVM内存模型如何分配
根据虚拟机规范,JVM的内存分为堆,方法区,虚拟机栈,本地方法栈,程序计数器,
synchronized和lock区别
ThreadLocal的原理是什么,使用场景
Thread类中有两个变量threadLocal和inheritableThreadLocals
二者都是ThredLocal内部类ThredLocalMap类型的变量
,我们通过查看内部类ThreadMap可以发现实际上它类似于一个HashMap。
默认情况下,每个线程中的这两个变量都为null,
只有当每个线程第一次调用ThreadLocal的set或者get的时候才会创建他们,
除此之外,每个线程的本地变量不是存放在ThreadLocal实例中的,
而是放在调用线程的ThreadLocals变量里面。
通过set方式将value添加代调用线程的threadLocals中,当调用线程调用get方法的时候能够从他的threadLocals中取出变量,
如果调用线程一直不终止,呢么这个本地变量就会一直存在,所以在不使用本地变量的时候需要调用remove方法将threadLocals中删除不用的本地变量,防止内存泄漏
DCL单例模式实现
public class Singleton{
//volatile是防止指令重排
private static volatile Singleton singleton;
private Sinleton(){};
public static Singleton getInstance(){
//第一层判断单例对象是不是null
//如果不是null直接放回
if(singleton == null){
//现在加锁
synchronized(Singleton.class){
//第二层判断
//如果A,B两个线程都在同步代码块等待
//A创建完对象之后B再进入,如果不再检测一遍,B又会创建一个对象
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton
}
}
创建线程的方式有哪些
java可以用四种方式来创建线程,如下所示
1.继承Thread类创建线程
2.实现Runnable接口,创建线程
3.使用Callable和Future创建线程
4.使用线程池例如用Executor框架继承Thread类创建线程
介绍一下线程的生命周期和状态
如何预防死锁
死锁发生的四个必要条件
1.互斥条件,同一时间只能有一个线程获取资源
2.不可剥夺条件一个线程已经占有的资源,在释放之前不会被其他线程抢占
3.请求和保持条件,线程等待过程不会释放已占有的资源
4.循环等待条件,多个线程互相等待对方释放资源
双亲委派机制是什么
双亲委派模式是java1.2后引入的,其工作原理是,
如果一个类加载器收到加载请求,他并不会自己先去加载,
而是把这个请求委托给父类的加载器去执行,
如果父类加载器还存在父类加载器,则进一步向上委托,依次递归,
请求最终将到达顶层的启动类加载器,
如果父类可以完成加载任务,就成功返回,若父类不行,子类就会尝试自己加载
线程sleep,wait,join,yield如何使用
1.sleep
其作用是让目前正在执行的线程休眠,
让CPU去执行其他任务,从线程的状态来说,
就是从执行状态转为阻塞状态
2.wait
其必须获得对应的锁才能调用,让线程进入等待状态
释放当前线程持有的锁资源线程只有notify或者notifyAll
方法调用后才会被唤醒然后才会去争夺锁
3.join
线程之间协调方式使用场景:
线程A必须等待线程B运行完毕之后才能运行可以在线程A中的代码加入ThreadB.join()
4.yield
让当前正在运行的线程回到运行状态,
以允许具有相同优先级的其他线程获得运行的机会,
因此使用yield的目的是让具有相同优先级的线程之间能够适当的轮换执行,但
是,实际中无法保障yield达到让步的目的,因为让步的线程可能被线程调度再次选中
了解那些垃圾回收算法
1.标记-清除算法
2.复制算法
3.标记-整理算法
4.分代收集算法
对象在内存中的创建过程
new
执行构造方法
建立关联
Springcloud
分布式ID的生产方案有哪些
1.UUID
2.数据库主键自增
3.redis自增
4.雪花算法
雪花算法生产的id由那些部分组成
1.符号位-1位
2.时间戳-4位
3.机器ID-10位
4.序列号-12位
分布式锁在项目中有哪些应用场景
一般使用分布式锁的场景需要满足以下场景
1.系统是一个分布式系统,集群,java的锁已经锁不住了
2.操作共享资源,比如库里唯一的用户数据
3.同步访问,即多个进程同时操作共享资源
分布式锁的有哪些实现方案
1.redis的分布式锁,大多基于redis做扩展开发,setnx,Redissson
2.基于Zookeeper顺序临时节点
3.基于数据库,比如Mysql主键或者唯一索引的唯一性
Redis做分布式锁用什么命令
SETNX(set if not exit)
格式:setnx key value将key的值设置为value,当且仅当key不存在
若给定的key已经存在,则setnx不会有任何动作
需要加上过期时间,为了防止死锁
redis如何做分布式锁
Mysql如何做分布式锁
Springboot
springboot的自动配置原理是什么?
Spring Boot启动的时候会通过
@EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中的所有自动配置类,
并对其进行加载,而这些自动配置类都是以AutoConfiguration结尾来命名的,
它实际上就是一个JavaConfig形式的Spring容器配置类,
它能通过以Properties结尾命名的类中取得在全局配置文件中配置的属性如:server.port,
而XxxxProperties类是通过@ConfigurationProperties注解与全局配置文件中对应的属性进行绑定的。
https://blog.csdn.net/u014745069/article/details/83820511
MyBatis、MyBatis Plus
#{}和${}的区别是什么?
${}是字符串替换,#{}是预处理;
使用#{}可以有效的防止SQL注入,
提高系统安全性。
Mybatis在处理${}时,就是把${}直接替换成变量的值。
而Mybatis在处理#{}时,会对sql语句进行预处理,
将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
通常一个mapper.xml文件,都会对应一个Dao接口,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
Mapper接口里的方法,是不能重载的,因为是使用 全限名+方法名 的保存和寻找策略。
Mybatis是如何进行分页的?分页插件的原理是什么?
Mybatis使用RowBounds对象进行分页,它是针对
ResultSet结果集执行的内存分页,而非物理分页。
可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,
实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,
根据dialect方言,添加对应的物理分页语句和物理分页参数。
如何获取自动生成的(主)键值?
insert 方法总是返回一个int值 ,这个值代表的是插入的行数。 如果采用自增长策略,
自动生成的键值在 insert 方法执行完后可以被设置到传入的参数对象中。
insert id=”insertname” usegeneratedkeys=”true” keyproperty=”id”>
insert into names (name) values (#{name})
insert>
当实体类中的属性名和表中的字段名不一样 ,怎么办 ?
第一种使用字段名和对象名称一致
第二种通过来映射字段名和实体类属性名的一一对应的关系。
select id="getOrder" parameterType="int" resultMap="orderresultmap">
select * from orders where order_id=#{id}
select>
resultMap type=”me.gacl.domain.order” id=”orderresultmap”>
!–用id属性来映射主键字段–>
id property=”id” column=”order_id”>
!–用result属性来映射非主键字段,property为实体类属性名,column为数据表中的属性–>
result property = “orderno” column =”order_no”/>
result property=”price” column=”order_price” />
reslutMap>
在mapper中如何传递多个参数?
(1)第一种:
//DAO层的函数
Public UserselectUser(String name,String area);
//对应的xml,#{0}代表接收的是dao层中的第一个参数,#{1}代表dao层中第二参数,更多参数一致往后加即可。
select id="selectUser"resultMap="BaseResultMap">
select * fromuser_user_t whereuser_name = #{0} anduser_area=#{1}
select>
(2)第二种: 使用 @param 注解:
public interface usermapper {
user selectuser(@param(“username”) string username,@param(“hashedpassword”) string hashedpassword);
}
然后,就可以在xml像下面这样使用(推荐封装为一个map,作为单个参数传递给mapper):
select id=”selectuser” resulttype=”user”>
select id, username, hashedpassword
from some_table
where username = #{username}
and hashedpassword = #{hashedpassword}
select>
(3)第三种:多个参数封装成map
try{
//映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
//由于我们的参数超过了两个,而方法中只有一个Object参数收集,因此我们使用Map集合来装载我们的参数
MapString, Object> map = new HashMap();
map.put("start", start);
map.put("end", end);
return sqlSession.selectList("StudentID.pagination", map);
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e; }
finally{
MybatisUtil.closeSqlSession();
}
** 一对一、一对多的关联查询 ? **
mapper namespace="com.lcb.mapping.userMapper">
!--association 一对一关联查询 -->
select id="getClass" parameterType="int" resultMap="ClassesResultMap">
select * from class c,teacher t where c.teacher_id=t.t_id and c.c_id=#{id}
/select>
resultMap type="com.lcb.user.Classes" id="ClassesResultMap">
!-- 实体类的字段名和数据表的字段名映射 -->
id property="id" column="c_id"/>
result property="name" column="c_name"/>
association property="teacher" javaType="com.lcb.user.Teacher">
id property="id" column="t_id"/>
result property="name" column="t_name"/>
/association>
/resultMap>
!--collection 一对多关联查询 -->
select id="getClass2" parameterType="int" resultMap="ClassesResultMap2">
select * from class c,teacher t,student s where c.teacher_id=t.t_id and c.c_id=s.class_id and c.c_id=#{id}
/select>
resultMap type="com.lcb.user.Classes" id="ClassesResultMap2">
id property="id" column="c_id"/>
result property="name" column="c_name"/>
association property="teacher" javaType="com.lcb.user.Teacher">
id property="id" column="t_id"/>
result property="name" column="t_name"/>
/association>
collection property="student" ofType="com.lcb.user.Student">
id property="id" column="s_id"/>
result property="name" column="s_name"/>
/collection>
/resultMap>
/mapper>
Springmvc
springmvc工作流程是什么?
Spring
spring的核心
spring是一个开源框架
spring是为了简化企业开发而生的,使得开发变得更加优雅和简洁
spring是一个IOC和AOP的容器框架
IOC:控制反转
AOP:面向切面编程
spring事务
spring事务大致可以分为三类
1.支持当前事务的
* REQUIRED(必须有)
如果方法没有事务,新建一个事务,如果存在一个事务中,则加入这个事务中
* SUOOIRTS(可有可无)
支持当前事务,如果当前没有事务,就以非事务方式执行
* MANDATORY(强制)
使用当前的事务,如果当前没有事务,就抛出异常
2.不支持当前事务的
* REQUIRES_NEW
新建事务,如果当前存在事务,就把当前事务挂起
* NOT_SUPPORTED
以非事务方式执行,如果当前存在事务,就把当前事务挂起
* NEVER
以非事务方式执行,如果存在事务就抛出异常
3.NESTED
如果当前存在事务,则嵌套事务内执行,如果当前没有事务
则执行与PROPAGATION_REQUIRED类似的操作
spring的事务的隔离级别
读未提交
读已提交
可重复读
串行化
在进行配置的时候,如果数据库和spring代码中的隔离级别不同
那么以sprig的配置为主
spring的事务实现方式的原理
在使用spring框架的时候,可以有;两种事务的实现方式,
一种是编程式事务,用户通过代码来控制事务的处理逻辑,
还有一种是声明式事务,通过Transactional注解来实现
spring事务是什么时候失效
1.bean对象没有被spring管理
2.方法的访问修饰符不是public
3.自身调用问题
4.数据源没有配置事务管理器
5.数据库本身不支持事务
6.异常被捕获
spring框架中的单例Bean是线程安全的吗
spring框架中使用那些设计模式以及应用场景
spring支持的bean作用域有哪些
简述spring bean的生命周期
1.实例化bean,利用反射生成对象
2.填充bean的属性,这里可能会有循环依赖问题,所以设置了三级缓存
3.调用aware接口:
4.调用BeanPostProcessor中的前置处理方法:来设置application环境,资源加载器等
5.调用初始化方法,判断是否有实现初始化bean的接口,如果有调用afterPropertiesSet方法
6.调用BeanPostProcessor中的后置处理方法,spring的aop就是在这里实现的
7.获取到完整的对象,可以通过getBean的方式来进行对象的获取
8.销毁流程,1.判断是否实现了DispoableBean接口,2.调用destroyMethod方法
BeanFactory和FactoryBean的区别?
applicationContext和BeanFactory的区别
谈谈你对循环依赖的理解
elasticsearch
简单介绍下ES?
ES是一种存储和管理基于文档和半结构化数据的数据库(搜索引擎)。
它提供实时搜索(ES最近几个版本才提供实时搜索,
以前都是准实时)和分析结构化、半结构化文档、数据和地理空间信息数据。
ES中的倒排索引是什么?
传统的检索方式是通过文章,逐个遍历找到对应关键词的位置。
倒排索引,是通过分词策略,形成了词和文章的映射关系表,
也称倒排表,这种词典 + 映射表即为倒排索引。
ES是如何实现master选举的?
前置条件:
1)只有是候选主节点(master:true)的节点才能成为主节点。
2)最小主节点数(min_master_nodes)的目的是防止脑裂。
Elasticsearch 的选主是 ZenDiscovery 模块负责的,主要包含 Ping(节点之间通过这个RPC来发现彼此)和 Unicast(单播模块包含一个主机列表以控制哪些节点需要 ping 通)这两部分;
获取主节点的核心入口为 findMaster,选择主节点成功返回对应 Master,否则返回 null。
选举流程大致描述如下:
第一步:确认候选主节点数达标,elasticsearch.yml 设置的值 discovery.zen.minimum_master_nodes;
第二步:对所有候选主节点根据nodeId字典排序,每次选举每个节点都把自己所知道节点排一次序,然后选出第一个(第0位)节点,暂且认为它是master节点。
第三步:如果对某个节点的投票数达到一定的值(候选主节点数n/2+1)并且该节点自己也选举自己,那这个节点就是master。否则重新选举一直到满足上述条件。
如何解决ES集群的脑裂问题
所谓集群脑裂,是指 Elasticsearch 集群中的节点(比如共 20 个),
其中的 10 个选了一个 master,另外 10 个选了另一个 master 的情况。
当集群 master 候选数量不小于 3 个时,可以通过设置最少投票通过数量
(discovery.zen.minimum_master_nodes)超过所有候选节点一半以上来解决脑裂问题;
当候选数量为两个时,只能修改为唯一的一个 master 候选,其他作为 data 节点,避免脑裂问题。
ElasticSearch中的分析器是什么?
在ElasticSearch中索引数据时,数据由为索引定义的Analyzer在内部进行转换。
分析器由一个Tokenizer和零个或多个TokenFilter组成。
编译器可以在一个或多个CharFilter之前。分析模块允许您在逻辑名称下注册分析器,
然后可以在映射定义或某些API中引用它们。
Elasticsearch附带了许多可以随时使用的预建分析器。
或者,您可以组合内置的字符过滤器,编译器和过滤器器来创建自定义分析器。
MQ
RabbitMQ
RabbitMQ的三大核心
1.流量削峰
2.代码解耦
3.异步处理
.RabbitMQ的五消息模型
1.简单消息模型
功能:一个生产者P发送消息到队列Q,一个消费者C接收。实现了基本的消息的生产和消费。一对一。
2.工作队列
功能:一个生产者,多个消费者。写法与基本消息模型类似,
只不过原来是一个消费者,现在是多个消费者。多个消费者处理队列中的数据。
3.发布订阅模型
功能:一个生产者发送的消息会被多个消费者获取。
一个生产者、一个交换机、多个队列、多个消费者
4.路由模式
功能:生产者发送消息到交换机并且要指定路由key,消费者将队列绑定到交换机时需要指定路由key。
只有当两个key相匹配时,消息才会发送到对应的消费者队列。即在广播的基础上有了路由的功能
5.主题订阅模式
功能:生产者P发送消息到交换机X,type=topic,
交换机根据绑定队列的routing key的值进行通配符匹配;
符号井号:匹配一个或者多个词 lazy.井号可以匹配 lazy.irs或者lazy.irs.cor; 符号*:只能匹配一个词 lazy.* 可以
RabbitMQ如何防止消息丢失
RabbitMQ消息丢失的情况 :
第一种:生产者弄丢了数据。生产者将数据发送到 RabbitMQ 的时候,可能数据就在半路给搞丢了,因为网络问题啥的,都有可能。
第二种:RabbitMQ 弄丢了数据。MQ还没有持久化自己挂了
第三种:消费端弄丢了数据。刚消费到,还没处理,结果进程挂了,比如重启了。
解决方案
针对生产者:
1.使用confirm机制。
2.开启RabbitMQ事务 。
针对RabbitMQ :
1.消息持久化
2.设置集群镜像模式
3.消息补偿机制
针对消费者 :ACK确认机制。
RabbitMQ如何保证消息不会重复消费
保证消息幂等性
让每个消息携带一个全局的唯一ID,即可保证消息的幂等性,
具体消费过程为:消费者获取到消息后先根据id去查询redis/db是否存在该消息
如果不存在,则正常消费,消费完毕后写入redis/db
如果存在,则证明消息被消费过,直接丢弃
RabbitMQ死信队列和延迟队列分别是什么?
1.死信队列就是一个普通的交换机,有些队列的消息成为死信后,
(比如过期了或者队列满了)这些死信一般情况下是会被 RabbitMQ 清理的。
2.延迟队列,即消息进入队列后不会立即被消费,只有到达指定时间后,才会被消费。
Nacos
Nacos服务是如何判定服务实例的状态?
通过发送心跳包,5秒发送一次,如果15秒没有回应,
则说明服务出现了问题,如果30秒后没有回应,则说明服务已经停止。
服务消费方是如何调用服务提供方的服务的?
通过创建RestTemplate对象来实现。
也可以通过Feign
Nacos中的负载均衡底层是如何实现的?
通过Ribbon实现,Ribbon中定义了一些负载均衡算法,然后基于这些算法从服务
实例中获取一个实例为消费方提供服务。
Ribbon 内置的负载策略都有哪些?
8种,可以通过查看IRule接口的实现类进行查看
Feign
为什么使用feign?
基于Feign可以更加友好的实现服务调用,简化服务消费方对服务提供方方法的调用
** FeignClient注解的作用是什么?**
告诉Feign Starte,在项目启动时,为此注解描述的接口创建实现类-代理类
Feign方式的调用,底层负载均衡是如何实现的?
Ribbon
EnableFeignClients注解的作用是什么?
描述配置类,例如启动类
Redis
redis的过期键有哪些删除策略
redis集群方案有哪些
常见集群分类:
1.主从复制集群
2.分片集群
集群的实现方式
* 主从复制集群,手动切换
* 带有哨兵的HA的主从复制集群
* 客户端实现路由索引的分片集群
* 使用中间件代理层的分片集群
* redis自身实现的cluster分片集群
redis的事务是怎么实现的?
MUTIL、EXEC、DISCARD、和WATCH是redis事务相关的命令,事务可以一次执行多个命令
EXEC命令负责触发并执行事务中的所有命令
如果客户端在使用MULTI开启了一个事务之后,
却因为断线而没有成功执行EXEC,那么事务中的所有命令都不会被执行
另一方面如果,客户端成功在开启事务之后执行了EXEC,那么事务中的所有方法都会被执行
redis击穿、穿透、雪崩、预热的解决方案
穿透:缓存不存在,数据库不存在,高并发,少量key
击穿:缓存不存在,数据库存在,高并发,少量key
雪崩:缓存不存在,数据库存在,高并发,大量key
都可以使用限流的互斥锁,保障数据库稳定
说说Redis的基本数据结构类型
1.String(字符串)
2.Hash(哈希)
3.List(列表)
4.Set(集合)
5.zset(有序集合)
它还有三种特殊的数据结构类型
Geospatial
Hyperloglog
Bitmap
Redis为什么这么快
1.基于内存存储实现
我们都知道内存读写是比在磁盘快很多的,
Redis基于内存存储实现的数据库,
相对于数据存在磁盘的MySQL数据库,省去磁盘I/O的消耗。
2.高效的数据结构
我们知道,Mysql索引为了提高效率,选择了B+树的数据结构。
其实合理的数据结构,就是可以让你的应用/程序更快。
3.合理的数据编码
4.合理的线程模型-I/O 多路复用-单线程模型
** 什么是热Key问题,如何解决热key问题**
什么是热Key呢?在Redis中,我们把访问频率高的key,称为热点key。
如果某一热点key的请求到服务器主机时,由于请求量特别大,
可能会导致主机资源不足,甚至宕机,从而影响正常的服务。
如何解决热key问题?
Redis集群扩容:增加分片副本,均衡读流量;
将热key分散到不同的服务器中;
使用二级缓存,即JVM本地缓存,减少Redis的读请求。
说说Redis的常用应用场景
缓存
排行榜
计数器应用
共享Session
分布式锁
社交网络
消息队列
位操作
MySQL与Redis 如何保证双写一致性
缓存延时双删
删除缓存重试机制
读取biglog异步删除缓存
为什么Redis 6.0 之后改多线程呢?
1.Redis6.0之前,Redis在处理客户端的请求时,
包括读socket、解析、执行、写socket等都由一个顺序串行的主线程处理,这就是所谓的“单线程”。
2.Redis6.0之前为什么一直不使用多线程?
使用Redis时,几乎不存在CPU成为瓶颈的情况, Redis主要受限于内存和网络。
例如在一个普通的Linux系统上,Redis通过使用pipelining每秒可以处理100万个请求,所以如果应用程序主要使用O(N)或O(log(N))的命令,
它几乎不会占用太多CPU。
redis使用多线程并非是完全摒弃单线程,redis还是使用单线程模型来处理客户端的请求,
只是使用多线程来处理数据的读写和协议解析,执行命令还是使用单线程。
这样做的目的是因为redis的性能瓶颈在于网络IO而非CPU,
使用多线程能提升IO读写的效率,从而整体提高redis的性能。
** Redis的Hash 冲突怎么办**
哈希冲突:通过不同的key,计算出一样的哈希值,导致落在同一个哈希桶中。
Redis为了解决哈希冲突,采用了链式哈希。链式哈希是指同一个哈希桶中,多个元素用一个链表来保存,它们之间依次用指针连接。
Mysql
MySql的隔离级别有哪些?
mysql定义了四种隔离级别
1.READ UNCOMMITTED读取未提交内容
安全最低,使得用户能看到未提交的事务内务,可能造成脏读的问题,一般不用
2.READ COMMITTED读取已提交的内容
大多数数据库采用这种隔离级别,
但mysql不是,该隔离级别可能导致不可重复读的问题,
就是用户在执行同一个语句可能会有两种不同的结果,
一个是别人没commit的时候的结果,一个是别人commit之后的结果
3.REPEATABLE READ可重复读
Mysql的默认隔离级别,该级别解决了READ UNCOMMITTED隔离级别的问题,
他保证同一个事务的多个实例在并发读取时,
会看到同样的数据行,不过会导致另外一个问题“幻读”。
InnoDB存储引擎通过多版本并发控制机制(MVCC机制)解决了幻读问题
4.SERIALIZABLE串行化
最安全,但效率最低,他通过强制事务排序,
使其不可能有冲突,从而解决幻读问题,
这个级别可能会导致大量的超时和锁竞争现象
什么是脏读
脏读是指一个事务读取了未提交事务执行过程中的数据
当一个事务操作正在多次修改数据,而在事务没提交的时候,
另一个并发事务来读取了数据,就会导致读取到的数据并非是最终持久化之后的数据
不可重复读
不可重复读是指对于数据库的某个数据,
一个事务执行过程中多次查询返回不同查询结果,这就是事务执行过程中,数据被其他事务提交修改了
不可重复读和脏读的区别在于,脏读是一个事务读取了另一个事务未完成的事务执行过程中的数据
而不可重复读是一个事务执行过程中,另一个事务提交并修改了当前事务正在读取的数据
Mysql主从复制的原理是什么
1.master服务器中将数据的改变记录二进制binlog日志中
当master上的数据发生改变的时候,则将其改变写入binlog文件中
2.从服务器会在一定时间间隔内对master的二进制文件进行探查
如果发生了改变吗,则开始一个IO线程请求master的二进制时间
3.同时主节点为每个IO线程启动一个dump线程用户向其发送二进制事件
并保存到从服务器上的中继日志中,此时从节点启动SQL线程从中继日志中做重放,使得其数据和主库保持一致
MySql聚簇索引和非聚簇索引的区别?
是否是聚簇索引取决于数据和索引是否放在一起
其中innodb只能有一个聚簇索引,
向innodb插入数据时,必须包含一个索引的key值
这个索引的key值,可以是主键,如果没有主键那么就是唯一键,如果没有唯一键
那么就会生成一个6字节的rowid
索引的数据结构
mysql的主要用到两种结构,B-Tree和Hash索引
Innodb存储引擎默认是B+Tree
Memory存储引擎默认Hash索引
对比:
hash类型的索引,查询单条快,查询范围慢
b+tree类型的索引,b+树,层数越多,数据量指数级增长
B+树在实现索引上的优势及过程( mysql索引结构有哪些,各自优势(其实主要考察b+树的数据结构))
索引的数据结构和具体存储引擎的实现有关,Mysql中使用比较多的索引有hash索引,B+Treee索引,innodb的索引
实现为B+树,Memory存储引擎为hash索引
1.B+树是一个平衡的多叉树,从根节点到每个叶子节点的高度差不超过1
而且同层级的节点之间有指针连接,在B+树上的常规检索,从根节点到叶子节点的搜索效率基本相当,不会出现大量的波动
而且基于索引的顺序扫描时,也可以利用双向指针左右移动,效率非常高
2.Hash索引采用一定的hash算法,把键值换算成新的哈希值
检索时不需要和b+树索引那样从根节点逐级查找,只需要一次hash计算即可定位到对应的位置
3.如果是等值查询那么hash索引有绝对的优势,但如果是范围查询,就不行了,hash索引不支持多列联合索引查询
B+树索引的关键字检索效率比较平均,不像B树那样波动大
MySql执行计划怎么看?
MySql索引的类型有哪些,以及对数据库的性能的影响
普通索引:允许被索引的数据列包含重复的值
唯一索引:可以保证数据记录的唯一性
主键索引:是一种特殊的唯一索引,
联合索引:索引覆盖多个数据列
全文索引:通过建立倒排索引(ES)
Mysql的锁有那些类型
共享锁、排它锁、行级锁、表级锁、页级锁、记录锁、间隙锁、临键锁
怎么处理Mysql的慢查询
1.开启慢查询日志,定位那个sql语句出现问题
2.分析sql语句,查看是否加载了额外的数据,可能是查询多余的行
3.分析语句的执行计划,然后获得其使用索引的情况,
之后修改语句或者修改索引,使得语句尽可能命中索引
4.如果最后发现实在无法优化,可以考虑是否表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表
索引的设计原则有那些
在进行索引设计的时候,应该保证索引字段占用空间越小越好
1.适合索引的列是出现在where字句中的列,或者连接字句中指定的列
2.基数较小的表,索引效果差,没必要建立索引
3.在选择索引列的时候,越短越好,可以指定某些列的一部分
4.定义外键的数据列一定要创建索引
5.更新频繁的字段不要有索引
6.大文本,大对象不要创建索引
什么是回表
什么是索引覆盖
什么是最左匹配原则
什么是索引下推
Mysql的结构
Vue
vue父组件向子组件传递数据?
通过props
子组件像父组件传递事件?
$emit方法
v-show和v-if指令的共同点和不同点?
共同点:都能控制元素的显示和隐藏;
不同点:实现本质方法不同,v-show本质就是通过控制css中的display设置为none,控制隐藏,只会编译一次;v-if是动态的向DOM树内添加或者删除DOM元素,若初始值为false,就不会编译了。而且v-if不停的销毁和创建比较消耗性能。
总结:如果要频繁切换某节点,使用v-show(切换开销比较小,初始开销较大)。如果不需要频繁切换某节点使用v-if(初始渲染开销较小,切换开销比较大)。
如何让CSS只在当前组件中起作用?
在组件中的style前面加上scoped
如何获取dom?
ref=“domName” 用法:this.$refs.domName
说出几种vue当中的指令和它的用法?
v-model双向数据绑定;
v-for循环;
v-if v-show 显示与隐藏;
v-on事件;v-once: 只绑定一次。
请说出vue.cli项目中src目录每个文件夹和文件的用法?
assets文件夹是放静态资源;components是放组件;
router是定义路由相关的配置; app.vue是一个应用主组件;main.js是入口文件。
分别简述computed和watch的使用场景
computed:
当一个属性受多个属性影响的时候就需要用到computed
最典型的栗子: 购物车商品结算的时候
watch:
当一条数据影响多条数据的时候就需要用watch
栗子:搜索数据
什么是 vue 生命周期?有什么作用?
每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、
将实例挂载到 DOM 并在数据变化时更新 DOM 等。
同时在这个过程中也会运行一些叫做 生命周期钩子 的函数,这给了用户在不同阶段添加自己的代码的机会。
(ps:生命周期钩子就是生命周期函数)例如,如果要通过某些插件操作DOM节点,
如想在页面渲染完后弹出广告窗, 那我们最早可在mounted 中进行。
详细链接:https://blog.csdn.net/weixin_54787921/article/details/118541476
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net