Java复习大纲
- 前言
- Java基础知识
- JAVA EE
- 数据结构与算法
- Java常见框架
- Spring
- Spring-Boot
- SpringData JPA
- Hibernate
- Mybatis/MybatisPlus
- SpringCloud
- 消息中间件
- Rabbitmq
- Kafka
- 缓存中间件
- Redis
- 数据库
- oracle
- MySql
- Pgsql
- 设计模式
- JVM
- UML类图
- 分布式及微服务
- 分布式锁
- 分布式事务(Seata框架)
- 微服务框架
- SpringCloud
- Dubbo
- Linux
- Docker
- K8S
- LeetCode刷题
前言
每次复习的时候都要找对应的java知识、视频来看,本文打算将所有的java相关知识列成大纲,学习完后进行总结,不断完善。之后通过总结的内容进行复习会更快速。
Java基础知识
JAVA EE
多线程
并发相关开发(包)JUC
CAS
AutomicInteger
threadlocal底层实现原理、如何实现线程池
IO
NIO
锁机制sync和lock的区别
数据结构与算法
常见排序算法
线性表
栈
队列
树
堆
Java常见框架
Spring
IOC和AOP原理
IOC创建过程
spring容器applicationcontext
bean工厂 beanfactory
bean的创建过程
总体上可分为实例化、初始化、完成阶段。
先是读取配置文件中的bean信息
读取的配置信息会封装成beandefinination放在对应的map中,是concurrentmap。之后spring提供了扩展点,可以自动扫描注解加载bean。
然后会根据bean定义信息对bean进行实例化然后进行属性注入,也就是依赖注入,然后会执行bean的初始化方法。在属性注入之后,初始化的前后spring也提供了两个扩展点。最后会将完整的bean对象放到单例池中singletonobjects。
spring容器如果显示销毁会执行容器的销毁方法,调用applicationcontext.close()
spring后处理spring提供了两个扩展点一个是beanfactorypostprocessor,一个是beanpostprocessor。
第一个beanfactorypostprocessor是在bean定义对象创建后bean对象初始化之前。基于此可以实现component注解,进行扫描注解自动把bean定义信息加载至map
第二个beanpostprocessor是在bean对象属性注入后,放在单例池之前的扩展点,可以基于此实现aop原理。
如何解决bean对象互相引用注入的问题,是通过三级缓存。
比如A中依赖B,B中需要注入A。
当实例化A进行属性注入时,会发现B对象不存在,此时A是一个半成品的BEAN,且没有引用,会放到一个三级缓存中,然后去创建B对象,创建B对象后会去注入A,会从一级缓存依次往下找,在三级缓存找到了A,此时A被引用,会进入到二级缓存,而B此时完成了依赖注入,会直接进入单例池,也就是一级缓存。然后A会再次注入B,此时B已存在一级缓存,A实例化完毕也进入单例池。
一级缓存就是单例池,二级缓存就是有引用的半成品bean,三级缓存是没有引用的半成品bean。
AOP原理就是基于动态代理技术包括基于JDK的动态代理和CGLIB的动态代理。
JDK的动态代理是基于接口的动态代理,被代理对象必须有实现接口。
CGLIB的动态代理是基于父类的动态代理,被代理对象不能被final修饰
JDK动态代理就是proxy.newproxyinstance去对方法动态加强。
Spring-Boot
SpringData JPA
Hibernate
Mybatis/MybatisPlus
SpringCloud
消息中间件
Rabbitmq
Kafka
与其它消息中间件的对比
底层实现原理
缓存中间件
Redis
缓存雪崩
大量key过期
解决办法:设置随机的过期时间
缓存击穿
热点key过期
可以动态延长热点key时长,重新获取数据时加锁。
缓存穿透
大量请求不存在的key。
缓存一个空值,布隆过滤器。
数据库
oracle
事务隔离级别
B+树 B树
MVCC
多版本并发控制
MySql
ACID 原子性 一致性 隔离性 持久性
事务隔离级别,默认可重复读
读未提交,读已提交,可重复读,串行化
索引
底层实现B+树
为什么选择B+树,而不是二叉树,红黑树,B树?
一是二叉树不是平衡的,可能导致性能很差,红黑树是自平衡,但是每个节点只有两个节点。
B树一个节点可以存多个数据,同时可以有n+1个子节点。
B+树除了叶子结点,其余节点只存索引,叶子节点才存数据,并且各个叶子节点会有双向指针,形成一个双向链表。
数据库引擎
innodb myisam memory
innodb的特点事务,外键,行级锁
myisam不支持事务和外键,表级锁
索引的类别 聚集索引和二级索引 也叫辅助索引
主键索引,唯一索引,普通索引,全文索引
聚集索引默认是主键索引,如果不存在主键索引默认取第一个唯一索引,如果不存在唯一索引,会为每行默认生成rowid,基于rowid生成聚集索引。
全文索引是基于文本建立的索引,基于倒排索引的机制。
索引最左前缀匹配原则
对于联合主键如果中间字段不匹配,中间以后的用不到索引。
sql优化机制
主要是对索引优化
insert优化 多条insert合成一条进行insert,但是不能过长一般不超过1000
多条insert 手动管理事务,减少提交次数。
尽量按主键进行顺序插入。顺序插入性能比乱序高,取决于mysql数据的组织结构 索引组织表。且所有数据形成了一个双向链表,顺序插入比乱序高。
主键设计原则
主键不能设置太长,索引中存放的都是主键,会增加磁盘的空间和IO性能
主键尽量设置成自增,插入时选择顺序插入
避免对主键修改,因为会重新建立索引
主键不要采用UUID或者其它自然主键,比如身份证号,一个是由于太长,另一个是连续的会造成页分裂的现象。
页分裂在对数据进行插入时,由于页空间有限,如果就两个页中间没有空间可以插入,前一个页会分出一半的数据,分裂成一个新
页,并对链表的关系重新建立关联。
页合并,是每次在删除元素时,会看跟前一个页或后一个页能否进行合并。
mysql数据库逻辑存储结构表空间、段,区,页,行
一个区一般是1M,一页是16KB。
每个表默认都会有个表空间,一个表空间中可分为索引段,数据段,回滚段(undo log)
查询时建立联合索引
对oder by和group by后面的字段建立索引
尽量建立覆盖索引,避免回表查询
对于多字段排序,如果排序的方式不一致,可以根据实际情况建立对应索引,比如按第一个字段升序,第二个字段降序。
update 更新字段要加索引,否则行锁会变成表锁,影响并发性能。
limit分页查询对于后面的数据分页查询效率低下,尽量采用加覆盖索引和子查询的方式
count*性能约等于count1大于count主键大于count字段
前两个不用取值后两个要先把字段值取出来,没有加非空约束的还要进行约束判断。
锁
包括全局锁,表级锁和行锁。
全局锁只允许读,主要是在做数据库备份或迁移时使用。
表级锁可分为表锁和意向锁。
表锁分为共享和互斥两种。
意向锁是为了防止DML和DDL的冲突,防止加表锁时要一行一行判断是否有加行锁,因此在加行锁时,会加一个意向锁。加表锁时根据是否存在意向锁进行判断。
行锁也是分为共享锁和排他锁。
间隙锁和临键锁。
间隙锁是把两个叶子节点数据之间的空隙锁住,不允许往空隙中插入数据,比如查询某个不存在数据。
临键锁是锁住当前叶子节点和它前面的空隙,即行锁与间隙锁的结合。
行锁锁住的是索引
MVCC
是mysql实现读已提交和可重复读的原理。
MVCC多版本并发控制涉及三个因素,一个是两个隐藏字段,一个是undo log版本链,一个是readview。
undolog版本链实际就是根据undolog可以知道每次修改的历史记录。
mysql的表有两个隐藏字段,分别时当前最近修改的事务id,以及上一次修改的地址。readview是读视图,是快照读获取数据的依据,它记录了活跃事务的id,以及当前事务的id。
对于读已提交而言,在事务开始后,每次其它数据更新的版本记录都会生成一次readview,而可重复读只有事务开始的时候会去生成readview,之后直接复用。
redo log和undo log
redo log叫重做日志,实现了事务的持久性,记录了事务提交时对数据页的物理修改,用于在把脏页(缓冲池与磁盘不一致的数据页)刷新到磁盘时,出现错误用来做数据恢复。
redo log涉及重做日志缓冲,和重做日志文件,当缓冲池中的数据被修改后,就会生成对于的重做日志,放在重做日志缓冲然后再刷新到磁盘。相比直接把缓冲池的修改直接刷新到磁盘相比,重做日志是采用追加的方式,顺序磁盘IO性能高于随机磁盘IO。
undo log保证了事务的原子性,叫做回滚日志,记录了事务修改前的数据,比如一条update语句记录的是反向的update语句。
undo log同时会用于MVCC
事务中分为当前读和快照读,当前读表示每次都能读到最新的数据,快照读对于读已提交来说,每次查询都会生成一个快照读,可重复读是只有第一个读才会生成快照读。
Pgsql
各数据库之间的区别
设计模式
23中设计模式及实际应用
单例模式
工厂模式
观察者模式
责任链模式
命令模式
JVM
原理及调优
JVM分区
垃圾回收算法
G1、CMS
UML类图
分布式及微服务
分布式系统/微服务系统的设计理念
CAP:一致性(C)、可用性(A)、分区容错性(P)
分区容错性的意思是在集群环境下不同节点的网络可能断开,从而形成分区。容错性指在这样的分区条件下也得提供服务。
在这种情况下,要么保证可用性,丢失一致性。因为不同节点数据不一致。
要不保证一致性,但是会丢失可用性,这样就是阻塞用户请求,等待分区恢复。
只能保证其中两个,如果在集群条件下,只能是CP或AP。
BASE理论
其中BA指的是基本可用
S指的是软状态
E指的是最终一致性
分布式锁
分布式事务(Seata框架)
Seata是分布式事事务的解决方案。
分布式事务的实现需要有事务协调者TC,事务管理者TM,资源管理者RM
TM限定全局事务的范围
RM对分支事务进行管理
首先TM会向TC注册全局事务。
TC根据分支事务的执行情况决定是提交还是回滚。
分布式事务模型
XA、AT、TCC、SAGA
XA是二阶段的分布式事务模型,同时也是一种规范,常见的关系型数据库都实现了XA规范,因此实现起来很简单。
XA在第一阶段分支事务执行完后都先不提交,等到TC判断所有分支事务都执行完了再一起提交,如果有分支事务失败,则回滚。
XA实现了强一致性,拥有事务的ACID特性。
AT也是二阶段的分布式事务模型。
但是AT第一阶段会直接提交事务,第二阶段会根据执行的成功和失败执行不同操作。如果执行失败则根据记录的快照进行恢复,如果执行成功,则删除快照。
整体流程是,分支事务在向事务协调者TC注册后,会保存一份当前的快照,如果事务执行失败,根据快照进行恢复。
AT由于是第一阶段进行提交,锁定资源时间不长,性能好。
XA回滚是基于数据库事务回滚的,而AT是基于快照回滚的。
XA是强一致性,AT是最终一致性。
AT为了解决脏写的问题,引入了一个全局锁,由TC记录当前事务锁定了哪些资源,如果都是由seata框架管理的事务则会阻塞,实现了一定隔离性。但是如果并发的不是seata管理的事务,则仍有可能出现脏写,AT框架会记录操作前后的快照,会比较当前数据与最新的快照数据是否一致,不一致则会记录异常数据提醒用户。
TCC包括try confirm cancel
try主要是做资源预留并做提交,confirm是如果没有问题则将冻结的数据删除,cancel是在如果失败,则手动写逻辑进行回滚。
空回滚和业务悬挂的问题:
空回滚是指try还没执行就阻塞了,超时后C会通知回滚,由于try还没执行,对于被阻塞的业务,我们需要空回滚,不能执行具体业务。而业务悬挂是指在空回滚的基础上,如果try在执行空回滚后突然又可以执行,则会执行一遍try的逻辑,但是整个事务已经结束,因此在执行try逻辑时需要判断当前事物的状态。
saga也是第一阶段提交,第二阶段写补偿逻辑,但是没有实现隔离性,有可能出现脏写。
微服务框架
SpringCloud
旧的微服务框架采用的是zookeeper+Dubbo(阿里开发)
注册中心采用的是zookeeper和redis实现
服务远程调用:dubbo协议
配置中心:无
服务网关: 无
服务监控和保护:dubbo-admin但是功能弱
SpringCloud早期版本:
注册中心:Eureka
服务远程调用:Feign(基于Http协议)
配置中心:springcloudConfig
服务网关:springcloudgateway、zuul
服务监控与保护:Hystrix
SpringCloudAlibaba是阿里在springcloud基础上做的扩展,开发了自己的注册中心、配置中心、服务监控与保护采用sentinel。
注册中心:支持Eureka、同时开发了自己的nacos注册中心
服务远程调用:Feign、同时也支持Dubbo协议
负载均衡:Ribbon
配置中心:Nacos
服务网关:GateWay、zuul
服务监控与保护:sentinel
nacos服务分级存储模型:
命名空间(namespace)-group-服务-集群(可以区分地域)-实例
不同命令空间下的服务是不可见的,group就是分组。
nacos可以实现配置的热更新。
通过@Value注解注入,需要加上@RefreshScope注解才能实现热更新
通过@ConfigurationProperties注入,可直接热更新
读取配置优先级:服务名-环境名.yml > 服务名.yml (多环境配置共享)> 本地配置
Ribbon懒加载:第一次访问时才会创建loadBalanceClient,才会去拉去服务,而后会被缓存在内存中
饥饿加载(eager-load):开启后项目启动时就会去加载,减少第一次访问的时间。
Ribbon负载均衡策略:所有策略实现一个IRule接口。
RandomRule:随机
RoundRibonRule: 轮询
ZoneAvoidanceRule: 基于区域的轮询,优先选择与当前处于同一区域的服务器进行轮询。
WeightResponseTimeRule:基于权重的选择,服务器响应时间越长,权重应该更小。
NacosRule:springcloudalibaba实现了springcloud的接口,优先访问同集群的服务。
Feign底层实现:
URLConnection:JDK中的默认实现,也是Feign的默认选项,不支持连接池(3次招手),性能比较差
Apache HttpClient:支持连接池
OKHttp: 支持连接池
Feign性能优化:一个是日志级别设置为basic或none,一个是修改底层实现,修改为连接池。
网关GateWay的作用:
1、可以做用户身份认证和权限认证。(可以在全局过滤器中自定义实现)
2、将请求路由到微服务,实现负载均衡。(配置的路由规则叫路由断言,路由断言工厂就是来解析路由断言,看到底将请求路由到什么地方)
3、对用户请求进行限流。
网关本身也是一个服务,需要在nacos上注册。
路由过滤器可以对请求的请求头和响应体进行加工,包括针对部分路由的过滤器、defaultFilters、全局过滤器(自定义逻辑)
过滤器的执行顺序:order值越小,优先级越高。order值一样时,defaultFilters>局部路由过滤器>全局过滤器
跨域问题需要在网关配置
Eureka和nacos作为注册中心的区别:
Eureka和nacos都支持服务的注册和服务拉取。都支持服务提供者主动心跳进行健康检测。
nacos实例分为非临时实例以及临时实例。nacos除了被动接受服务提供者的心跳检测,对于非临时实例提供主动检测。并且临时实例挂了之后会直接从nacos中剔除,但是非临时实例会一直保留,等待服务恢复。
除此之外,nacos除了服务者主动拉取服务信息之外,还支持主动推送变化的服务信息。
nacos集群默认是AP模式,如果存在非临时实例会切换为CP模式;Eureka默认是AP模式。
服务网关:GateWay和zuul的区别
服务监控与保护:Hystrix和sentinel的区别
服务远程调用:dubbo和feign的区别
Feign和Http的区别:
ES:elasticSearch 开源的搜索引擎,用于存储、计算、搜索数据。
ELK:ES结合kibana(数据可视化)、logstash、Beats(数据抓取)也就是elastic stack
ES底层实现时基于lucene的技术(java语言的一个类库(jar包),具有可扩展、高性能的特点)
高性能是基于倒排索引。
正向索引和倒排索引的区别:
正向索引就是传统数据库的索引比如Mysql
倒排索引:有两个概念一个是文档,一个是词条。文档就是指一行数据,词条是根据语义将内容拆分成多个词条,每个词条关联一个或多个文档,然后对词条通过建立索引的方式进行查找,提高查询效率。
es中文档是以json格式进行存储,它与mysql的侧重点不同。mysql主要是负责事务类型的操作,es主要是负责海量数据的计算、搜索。ES中索引是同类型文档的集合。
DSL是基于Json的查询语句,类比于mysql中的sql
sentinel 阿里开源的服务保护的组件
微服务的雪崩问题:微服务中调用链复杂,一个服务出现故障,导致其他服务的请求无法释放,造成整个微服务集群的异常。
解决办法包括:
1、设置超时时间
2、限流
3、隔离,限制某个业务的线程数
4、熔断降级,异常的请求达到一定比例,直接熔断,直接返回。
限流、隔离、降级
sentinel隔离是基于信号量隔离,就是记录了一个使用线程的数量,达到一定数量则不允许使用。hystrix现在已经停止维护了,默认是通过线程池隔离。
sentinel避免了多创建线程池和线程的开销,所以更好一些。
sentinel流控模式分为三种,直接,关联,链路。
直接是统计当前资源的请求数,可以直接对当前请求路径进行限流。
关联是统计其它资源的请求,对当前限流。用于存在竞争资源的两个请求,对低优先级进行限流。如数据库读写,对读进行限流。
链路是对某个请求链路进行限流,如A和B都可以访问C,对A到C的请求进行限流
还有热点参数限流,对指定参数的请求进行限流。
流控效果分为快速失败,预热模式,排队等待
预热模式也是快速失败,但阈值会动态变化,开始只有三分之一。
排队等待可以起到流量整形的作用,达到阈值会进入队列 但是会设置超时时间,超过时间也会失败。
限流支持按QPS的限流,支持调用关系的限流。
sentinel支持慢启动和匀速排队的模式。
熔断降级除了支持异常请求的熔断,还支持慢请求的熔断,Hystirx不支持慢请求熔断。
sentinel还提供了对应的控制台界面,提供了更多监控,配置的功能,比hystrix更完善和强大。
Dubbo
Linux
常见命令
java排查问题的命令或者工具(JDK)