Java八股整合(MySQL+Redis+Maven)

MySQL

数据库设计三范式

不可再分,部分依赖,传递依赖

主键和外键区别

主键非空约束,唯一性约束,唯一标识一个字段

外键用于和其他表建立连接,是另一张表的主键,可重复可为空可以有多个

为什么不推荐使用外键

因为外键增加了复杂度(增删时要考虑外键约束),增加了额外工作(额外维护外键),不利于分库分表

drop,delete和truncate区别

drop丢弃数据,在删除整个表时使用

delete删除数据,按行删除数据

truncate清空数据,在清空表中数据时使用

drop和truncate是DDL数据定义语言,不能回滚;delete是DML数据库操作语言,提交才生效

数据库设计步骤

需求分析,概念结构设计,逻辑结构设计,物理结构设计,数据库实施,数据库运行和维护

关系型数据库

建立在关系模型上的数据库,包含一对一,一对多,多对多的关系

SQL

结构化查询语言,目的是从数据库中读写数据

整数类型的UNSIGNED属性有什么用

表示不允许负值的无符号整数,提升正整数上限

CHAR和VARCHAR区别

定长和不定长字符串

VARCHAR(100)和VARCHAR(10)区别

最大容量不同,超过时需要修改表结构,100会消耗更多内存(排序时按照100进行),但占用磁盘空间一样

DECIMAL和FLOAT,DOUBLE区别

DE是定点数,存储精确值

为什么不用TEXT和BLOB

无默认值;使用临时表时无法使用内存临时表,只能在磁盘上创建;检索效率低;不能直接创建索引需要指定前缀长度;消耗大量网络和IO带宽;导致DML变慢

DATE和TIMESTAMP区别

D没有时区信息,消耗存储空间更大

NULL和空字符串区别

NULL表示不确定值,无法判断相等(要用IS NULL判断);会占用空间;影响聚合函数结果

空字符串长度为0

Boolean类型如何表示

TINYINT(1),可以存储1或0表示

MySQL基础架构

连接器,查询缓存,分析器,优化器,执行器,插件式存储引擎

MySQL存储引擎

默认InnoDB,唯一事务性存储引擎

是插件式架构,基于表而不是数据库

InnoDB和MyISAM区别

I是行级别锁,M是表级别锁

M无事务支持,不支持外键,不支持MVCC,不支持数据库异常后的安全恢复,性能不如I强

InnoDB数据本身就是索引文件,MyISAM索引文件和数据文件是分离的

事务

逻辑上的一组操作,要么都执行,要么都不执行

ACID原子性,隔离性,一致性,持久性,一致性是目标

并发事务带来的问题

脏读,丢失修改(修改被复写),不可重复度,幻读

并发事务控制方式

锁(共享锁(读锁,S锁),排它锁(写锁,X锁))(行级锁,表级锁(不容易死锁))

意向共享锁(IS锁),意向排它锁(IX锁),意向锁之间互相兼容

MVCC多版本并发控制方法,一份数据存储多个版本,通过隐藏字段,read view,undo log实现

四个事务隔离级别

通过锁和MVCC机制共同实现

默认可重复读

InnoDB行锁

记录锁,单个行记录的锁

间隙锁,锁定一个范围,不包括记录本身

临键锁,锁定一个范围,包括记录本身

默认临键锁,操作的索引是唯一索引或主键则降级为记录锁,只锁住索引本身

当前读和快照读区别

快照读(一致性非锁定读),就是Select语句,读到的是记录的历史版本

当前读(一致性锁定读),给记录加X或S锁

MySQL如何存储IP地址

INET_ATON(),ip转换为无符号整型

INET_NTOA(),无符号整型转换为ip

分析SQL性能

EXPLAIN

索引

底层数据结构

Hash表,通过哈希算法找到key对应的index。冲突时用链表或者红黑树

二叉查找树,性能依赖于平衡度

自平衡二叉查找树,需要多次旋转,每个节点只能存储一个数据,需要多次磁盘IO

红黑树,应用广泛

B树,多路平衡查找树,节点同时存放key和data;叶子结点相互独立;可能未到叶子结点就检索完毕;需要先找到查询下限再中序遍历找上限

B+树,非叶子结点只存key,叶子结点之间有条引用链,检索稳定,只需要链表遍历即可,IO次数更少

索引类型

(索引和数据是否一起存储)

聚簇索引,InnoDB中主键索引。查询快,对排序查找和范围查找速度快。但是依赖有序数据,更新代价大

非聚簇索引,辅助索引和MYSQL的MyISAM引擎的所有索引。更新代价小。但是也依赖有序数据,可能会需要二次查表找到对应数据(key=value时无需回表)

(应用维度划分)

主键索引,普通索引,唯一索引,覆盖索引,联合索引,全文索引

最左前缀原则

使用联合索引时,根据索引字段顺序,从左到右依次匹配查询条件中的字段,查询条件与最左侧字段匹配则会走索引过滤数据

一直向右匹配,直到遇到范围查询(大于小于)为止,对于大于等于,小于等于,between以及前缀匹配like的范围查询不会停止匹配

索引下推

在索引遍历过程中执行部分where语句的判断条件,直接过滤掉不满足的记录,减少回表次数,提高查询效率

将Server层负责的事推给下层存储引擎层处理,减少了数据传输量

推荐给什么样的字段设置索引

非空,经常被查询,被作为条件查询,频繁需要排序,常被用于连接的字段

日志

重做日志redolog

把修改记录在redolog中,持久性

刷盘(放入磁盘)时间:事务提交,log空间不足,事务日志缓存区满,检查点,后台刷新线程,正常关闭服务器

硬盘上的redolog有多个,是日志文件组,每个大小一样

随时写入

归档日志binlog

逻辑日志,用于数据备份,主备,主主,主从,保证同步

statement记录SQL语句原文

row记录原文和操作数据

mixed二者混合

事务提交时写入

两阶段提交

redolog和binlog逻辑不一致

将redolog拆成prepare和commit

恢复数据时处于prepare阶段,无binlog则会回滚

commit阶段无法回滚

回滚日志undolog

用于回滚,保证事务原子性

MYSQL基础架构

连接器:身份验证和权限相关

查询缓存:查询语句查询

分析器:未命中缓存时查看SQL语法(词法分析,语法分析)

优化器:按照最优执行

执行器:执行语句

Server层:跨存储引擎功能实现

存储引擎:数据存储和读取,插件式架构

Redis

基于c语言的非关系数据库,数据保存在内存中,读写快

Redis为什么快

基于内存,有一套高效的事件处理模型,主要是单线程事件循环和IO多路复用,内置了多种优化后的数据类型和结构实现,通信协议实现简单且解析高效

为什么用Redis

访问速度快,高并发,功能全面(能用于分布式锁,限流,消息队列,延时队列等)

Redis Module

可以动态灵活的扩展实现方式,自定义开发

Redis可以做消息队列吗

Redis可以做搜索引擎吗

Redis实现延时服务

1.Redis过期事件监听(存在很多问题)

Redis2.0引入了发布订阅功能,引入了channel概念,发布者投递消息给channel,订阅者订阅关心的channel,有一个默认的channel,监听过期的key事件,当key过期后,发布到该channel。

只要监听这个channel,就可以拿到过期的key信息,实现延时任务。

该功能叫keyspace notifications

但是时效性差(过期消息发布是在删除key时发布,到了指定时间可能key还没被删除),可能丢消息(没有订阅者会直接丢弃消息),多实例下重复消费(广播模式发布订阅消息)

2.Redisson内置的延时队列

基于Redis的SortedSet实现,每个元素有一个分数,将过期时间作为分数输入

通过Redisson扫描SortedSet中的过期元素,移除并加入就绪消息列表中,有消息进入就会被监听,避免对整个SortedSet轮询,提升执行效率

减少了丢消息的可能(消息持久化),不存在重复消费问题(通过一个队列获取任务)

Redis常用数据类型

String,用于常规数据缓存,计数,分布式锁等。存储序列化后的对象数据,更省内存,Hash散列是对对象每个字段单独存储(一般用String存对象,需要对某个属性频繁修改则用Hash)(数组+链表)

String底层用C语言,但不是用C语言的字符串实现的,而是自己编写了SDS

List是自己实现了链表的数据结构(双向链表),可以用来做消息队列,但是功能过于简单且有很多缺陷

Set用于存放不能重复数据的场景,或者查找多个数据源的交集和并集差集,或者随机访问元素

Zest有序集合,用于对某个元素按照权重排序的场景,或者存储的数据有优先级的场景

HyperLogLog基数统计,采用稀疏矩阵(计数量小),稠密矩阵(计数量大)计数,通过概率统计预估,存在误差,用于大量计数的情景

Bitmap位图(存放0和1),每个元素下标叫offset偏移量,用于保存状态信息

Geospatial地理位置,用于管理地理空间数据

有序集合底层为什么用跳表而不是各种树

有序集合元素小于64字节并且个数小于128时使用ziplist,超过后使用skiplist

跳表使用多级索引减少增删改查时间为O(logn)

平衡树查询插入和删除时间复杂度都是O(logn),但是需要对树调平衡

红黑树实现复杂,需要旋转和染色,并且按照区间查询操作效率不如跳表

B+树为了减少IO次数,但是Redis存储数据较少,不需要,并且B+树实现复杂

Redis单线程模型

Reactor模式对应的是Redis中的文件事件处理器,文件事件处理器是单线程方式运行的,所以一般说Redis是单线程模型

文件处理器以单线程方式运行,但是通过IO多路复用监听多个套接字,为不同套接字关联不同的事件处理器,减少了额外创建线程监听客户端的大量连接

文件处理器包含多个socket(客户端连接),IO多路复用程序(支持多客户端连接),文件时间分派器(用于关联socket和事件处理器),事件处理器(连接应答,命令请求,命令回复)

Redis数据过期时间

缓解内存消耗

通过过期字典保存数据过期的时间

删除策略

惰性删除(访问时删除),定期删除,延迟队列(维护麻烦),定时删除(CPU压力大)

Redis采用定期删除+惰性删除

定期删除受到执行时间和过期key比例影响, 超时则中断,比例过大则重复删除流程

大量key集中过期怎么办

避免集中过期,设置随机过期时间,或对过期的key开启lazyfree机制

内存淘汰策略

设置了过期时间的最近最少使用淘汰,将要过期的数据淘汰,设置了过期时间的任意数据淘汰,最近最少使用淘汰,任意数据淘汰,不淘汰,最不常用的淘汰,设置了过期时间的最不常用的淘汰

Redis事务

命令打包顺序执行不被打断

通过MUL TI开始事务,EXEC执行事务,DISCARD取消事务,WATCH监听key,实现

不支持回滚,不满足原子性

支持三种持久化方式:快照,只追加文件,RDB和AOF混合持久化

Redis性能优化

使用批量操作减少网络传输(命令发送,排队,执行,返回结果)

解决大量key集中过期问题

处理BigKey

占用大量内存的key,,可能是程序设计不当,业务数据规模考虑不周到,未及时清理垃圾

会造成客户端超时阻塞,网络阻塞,工作线程阻塞

处理bigkey:分割bigkey,手动清理,采用合适的数据结构,开启lazyfree

处理hotkey

访问次数多的key,可能是重大热搜或者参与秒杀的商品

会占用CPU和带宽

处理hotkey:读写分离,使用Redis Cluster分散存储,二级缓存(放JVM本地内存)

慢查询日志

需要消耗长时间的命令,遍历或排序

慢查询日志每个条目包括:日志标识符,Unix时间戳,执行所需的时间,组成命令参数的数组,客户端IP地址和端口号,客户端名称

Redis持久化机制

RDB快照(默认),获取内存数据在某个时间点的副本 ,save命令会阻塞主线程,bgsave会fork子线程,不会阻塞主线程(默认)

RDB文件小,可以直接还原数据,不需要重新执行命令,但是生成RDB文件慢,多个版本RDB格式不兼容,不易理解

AOF只追加文件,将修改Redis的命令写入AOF缓冲区,再写入文件中(根据持久化方式决定何时写入),实现步骤:命令追加,文件写入,文件同步,文件重写,重启加载

为什么执行完命令才写日志:写日志时不需要语法检查,并且写日志不会阻塞命令执行

AOF重写:会创建子线程重写,将重写时新写入的命令加入重写缓冲区,重写完成后将缓存区内容加入新文件末尾,最后用新的文件替换旧文件

AOF校验:通过校验和

AOF安全性强,生成文件过程快

RDB和AOF混合持久化,AOF重写时将RDB内容写入AOF开头,但这样导致文件格式为混合型,可读性差

丢失数据影响小则使用RDB,不建议单独使用AOF,可以间歇创建RDB快照,保存的数据安全性高可以同时使用两种持久化方式

Redis内存碎片

申请的内存大于实际用到的,或频繁修改缓存中的数据

常见阻塞原因

O(n)命令,生成RDB快照,AOF日志记录,AOF刷盘,AOF重写,大key相关操作,清空数据库,集群扩容,内存交换,CPU竞争,网络问题

缓存穿透

大量请求的key不在缓存中也不在数据库中,导致大量请求提交到数据库上,造成巨大压力

解决方案:缓存无效key,布隆过滤器,接口限流

布隆过滤器用一个很大的bit数组保存所有数据,每个位可以是1和0,判断用户请求值是否在过滤器中,不在则返回错误信息

缓存击穿

热点数据在数据库而不在缓存中,被瞬时大量数据请求打宕机了

解决方案:永不过期(不推荐),提前预热(提前存入缓存并设置合理过期时间),加锁(缓存失效后设置互斥锁保证只有一个请求访问数据库)

缓存雪崩

缓存同一时间大面积失效,大量请求直接访问数据库

由于Redis不可用:Redis集群,多级缓存(本地缓存+Redis缓存)

由于大量缓存同时失效:设置随机失效时间,提前预热(使用定时任务查询热点数据存入缓存,使用消息队列异步预热),持久缓存策略

如何保存缓存和数据库一致性

不一致时异步重试,将重试请求写入消息队列,由专门消费者重试直到成功

或者直接将操作缓存步骤放入消息队列中

推荐先更新数据库再更新缓存,配合消息队列或订阅变更日志

主从库延迟问题使用延迟双删,先删除缓存更新数据库,过一段时间再删除一次缓存

强一致需要牺牲性能

三种缓存策略

旁路缓存模式

适合多读场景

写时先更新数据库,然后直接删除缓存

读时先从缓存读取,缓存读取不到从数据库读取,再将数据放入缓存

缺点:首次请求数据一定不在缓存中(热点数据提前放入缓存),频繁写导致缓存经常被删除

读写穿透模式

将缓存作为主要数据存储,通过缓存写入数据库

写时先找缓存,缓存没有则直接更新数据库,缓存有则先更新缓存,再由缓存自己更新数据库

读时先找缓存,找不到就从数据库写入缓存,再由缓存响应

缺点:首次请求的数据一定不在缓存

异步缓存写入

也是由缓存负责缓存和数据库的读写

批量异步更新数据库,写性能高,但是数据一致性难以保证

Maven

用于项目构建,依赖管理,统一开发结构

Maven坐标

groupId定义了当前项目隶属的组织或公司

artifactID定义了当前项目名

version版本号

packaging定义了打包方式(可选)

classifier区分同一POM构建的不同内容的构件(可选)

Maven依赖

denpendencies管理总依赖的标签

dependency每个依赖的标签

groupId定义了当前项目隶属的组织或公司

artifactID定义了当前项目名

version版本号

依赖范围

compile(编译依赖范围),test(测试依赖范围),provided(编译和测试依赖范围,不包括运行),runtime(运行依赖范围,对编译主代码时无效),system(系统依赖范围)

依赖冲突

引入了同一个groupId的同一个artifactID的不同version

两个依赖同时引入了某个依赖,遵循路径最短优先和声明顺序优先

排除依赖

在dependency中加exclusions,exclusion

Maven仓库

Maven生命周期

Maven插件

Maven多模块管理

Spring

IoC

将程序中手动创建对象的控制权交给Spring管理,需要创建对象时直接取用即可

IoC容器实际上是个Map

最开始使用XML文件配置Bean,后来使用SpringBoot注解配置

Bean是什么

指IoC容器管理的对象

@Component标注任意类为Spring组件

@Repository标注持久层组件

@Service标注服务层组件

@Controller标注MVC控制层组件

@Bean通常标在方法上,自定义性更强

注入Bean的注解

@AutoWired是Spring提供的注解,优先按接口类型匹配,当一个接口有多个实现类时通过名称匹配,建议通过@Qualifier区分,可以在构造方法,方法,字段和参数中使用

@Resource是JDK提供的注解,默认通过名称匹配,可以按类型指定,可以在字段和方法上使用,不能用于构造函数或参数

@Inject

Bean作用域(@scope中配置)

singleton单例,prototype每次都会获取新实例,request请求域,session会话域,application应用域,websocket每次websocket产生一个新的bean

Bean线程安全吗?

singleton可能有线程安全问题,如果bean有状态则存在问题

尽量避免定义可变的成员变量,在类中定义ThreadLocal变量,将可变成员保存在其中

Bean生命周期

1首先找到配置文件中的bean定义,通过反射创建bean实例

2为bean设置相关属性和依赖,@AutoWired@Value,setter@Resource注入的各种

3bean初始化

4销毁bean,记录销毁方法,需要销毁时调用方法

AOP

将与业务无关,但是被业务模块共同调用的逻辑或责任封装起来,减少重复代码,降低耦合性

基于动态代理,代理的对象实现了接口就使用JDK Proxy创建代理对象;没实现接口就用Cglib生成被代理对象的子类

SpringAOP和AspectJAOP区别

s是运行时增强,a是编译时增强;s基于代理,a基于字节码操作

通知类型

前置通知,后置通知,返回通知,异常通知,环绕通知

控制切面执行顺序

使用@Order注解,或者实现Ordered接口重写getOrder方法

SpringMVC

模型Model,视图View,控制器Controller,将业务逻辑,数据,显示分离

相关推荐
52Hertz_leona10 分钟前
关于studywolf_control动态运动原语
开发语言·python
小天努力学java29 分钟前
【面试系列】深入浅出 Spring
java·spring·面试
Just_Paranoid33 分钟前
解析 Java 项目生成常量、变量和函数 Excel 文档
java·python·正则表达式·excel·javadoc
阿垂爱挖掘33 分钟前
34 - Java 8 Stream
java
dengjiayue44 分钟前
MySQL 查询大偏移量(LIMIT)问题分析
数据库·mysql
言之。1 小时前
【MySQL】在MySQL中如何定位慢查询?
数据库·mysql
叫我阿呆就好了1 小时前
C 实现植物大战僵尸(一)
c语言·开发语言
simple_ssn1 小时前
【蓝桥杯】压缩字符串
java·算法
monstercl1 小时前
【C#】元组
开发语言·c#
Suwg2091 小时前
【MySQL】踩坑笔记——保存带有换行符等特殊字符的数据,需要进行转义保存
数据库·笔记·mysql