Java知识体系总结
2020-04-10 10:19:23 0 举报
AI智能生成
知识点总结
作者其他创作
大纲/内容
java基础
JDK
概念
面向对象
用途
开发JAVA程序,运行JAVA程序
组成部分
java开发工具包,包含各种类库和工具
JRE
概念
面向对象
用途
运行JAVA程序
组成部分
核心内容是JVM及核心类库
==和equals的区别
== 比较的是内存地址,equals比较的是字符串的内容,如果不重写默认是==
两个对象的hashCode()相同,则equals()也一定为true,对吗?
两个对象的equals()为true,hashCode()一定相同;hashCode()相同equals()不一定为true;
final关键字的作用
作用
1.用于修饰类,修饰类属性,修饰类方法。
2.被final修饰的类不可以被继承;被final修饰的类属性和类方法都不能够被重写;被final修饰的类属性,子类不能给它重新赋值。
String属于基础的数据类型吗?
String不属于数据类型,是final修饰的类
操作字符串的类
String
String是不可变的对象,在每次对String类型进行改变时都会新生成一个对象
StringBuffer
对对象的改变不会产生新的对象,效率比StringBuild慢,但线程安全
StringBuild
不产生新对象,线程不安全,效率高
面向对象程序设计
特点
封装
将对象的属性和行为封装起来
继承
多态
概念
父类对象应用于子类
实现形式
继承和接口
存在的三个必要条件
继承
重写
子主题
Java语言的优势
一处编译到处运行
自从内管管理机制之下,不再需要为每一个new操作去写配对的内存分配和回收等代码,不容易出现内存泄露和内存溢出等问题
Spring Boot
提倡约定优先于配置
目的
简化spring初始化搭建以及开发过程
优点
1.开箱即用,提供各种默认配置来简化项目配置
2.内嵌WEB容器
3.没有冗余代码生成和xml配置的要求
Starter作用
主要目的是为了简化依赖
eg:spring-boot-starter-web里面包含各种依赖
spring-boot-starter-web作用
springweb核心组件
SpringApplication.run方法的原理
1.首先创建一个SpringApplication对象实例,然后再调用SpringApplication.run方法
首先开启SpringApplicationRunListeners监听器,然后通过createApplicationContext,preperContext,refreshContext方法创建,准备,刷新应用文上下文ConfigableApplicationContext,通过上下文加载应用所需的各种类和各种环境配置等,最后启动一个应用实例
NoSql数据库
Redis
概念
nosql缓存数据库
特征
1.通过key,value形式存放在内存中
2.分布式情况下数据可以共享,可以可以解决session共享问题
3.效率高(内存查询效率比查询硬盘效率高)
4.数据容易丢失
优点
1.能够减轻数据库压力
原因
查询内存比查询硬盘效率更高
2.
基本数据类型
string
深入理解
string类型是二进制安全的,redis的string可以包含任何数据,比如jpg图片或者序列化的对象,一个value最多可以是512M
set不允许重复,无需
String类型的无序的,不能重复的集合
zset不允许重复有序
每个元素都会关联一个double类型的分数.根据分数对集合进行从大到小排序,成员是唯一的,但分数是可以重复的
hash
k,v模式不变,但是v是一个键值对,特别适合存储对象
list
深入理解
1.底层实现是一个字符串链表,可以添加一个元素到链表的头部或者尾部。
2.如果健不存在,创建新的链表
3.如果键存在,新增内容
4.如果值全部移除,对应的键也消失了
5.对链表的头和尾操作效率都很高,对中间元素操作效率很低
redis如何存储对象
首先将对象转成json格式存放在redis中,通过反序列化成对象
分布式锁
分布式锁遇到的问题
1.服务挂掉锁没有释放
2.redis挂了
3.可能在设置超时时间时挂了,导致key永不过期
解决方式
手动删除Kkey
释放锁遇到的问题
1.业务代码执行时间超过锁的超时时间
A线程将B线程的锁删除
如何实现分布式锁
1.采用setnx,setex连用
缺点
高并发,不加锁的情况下,多个操作不能保证原子性
2.采用lua脚本操作分布式锁
脚本执行具有连续性,且redis是单线程的,具有排他性
redis高可用机制
1.主从复制
数据备份,读写分离,集群,高可用,宕机容错
如何实现
1.哨兵机制
作用
1.主要用与选举master
2.
实现形式
1.使用sentinel系统,进行心跳检测,如果服务器挂了,可以使用keepalived监听,自动重启
2.
应用场景
token生成,订单id,session共享,分布式锁,秒杀,抢红包
持久化机制
1.RDB
是什么?原理
1.redis首先会fork一个与当前线程一模一样的子进程来进行持久化,这个子线程的变量(环境变量,程序计数器等)都和原线程一模一样,首先将数据写入一个临时文件,待持久化结束了,再将这个临时文件替换之前持久化好的文件。
提问?为什么要fork一个子进程?
因为redis是单线程的,如果这个线程进行持久化了,客户端的请求得不到处理,必须等待持久化结束,客户端发送的命令会被堵塞,性能低下。
什么时候fork子进程,什么时候出发rdb持久化机制
1.shutdown时,如果没有开启aof,会出发rdb
2.配置文件默认快照配置
3.执行sava或者bgsave
bgsave会fork一个子进程
sava不会fork子进程直接使用主进程进行持久化,是阻塞的
2.AOF
是什么?原理
将redis的操作日志以追加的方式写入文件,读操作不做记录
主要分为三步:数据写入内存->数据写入aof_buf ->写入持久化文件
触发机制
no
表示等操作系统进行数据缓存同步到磁盘
快,持久化没保证
always
同步持久化,每次发生数据变更时,立即记录到磁盘
慢,安全
everysec
表示每秒同步一次
默认,很快,但是可能会丢失一秒内的数据
aof重写机制
为什么会出现重写机制?
aof是以日志追加的方式将命令字符串保存在aof文件中,随着我们操作redis的时间越久,aof文件越大,如果不做处理,总会撑破磁盘
原理
重写就是给aof文件做瘦身,直接根据现在内存的数据生成新的aof文件,然后去替换旧的aof文件。就可以把一下没用字符去掉,比如set k1 v1 ,然后我们del k1等等一些没用操作,这样我们的文件大小就会小很多
触发机制
1.当aof文件增长到一定大小的时候redis能够调用bgrewriteaof对日志文件进行重写
2.当aof文件大小的增长率大于配置项时自动开启重写 默认是100
3.当aof文件大于该配置项时自动开启重写
注意:注意:重写操作是通过fork子进程来完成的,所以正常的aof不会fork子进程,触发了重写才会
4.0之后混合持久化机制
4.0默认混合持久化是关闭的,通过aof-use-rdb-preamble,yes开启,no禁用,5.0之后默认开启。
混合持久化是通过bgrewriteaof完成的,不同的是开启混合持久化时,fork出得子进程会先将共享的内存副本全量以RDB方式写入到aof文件,然后再将重写缓冲区的增量命令以aof的方式写入到文件。写入完成后通知主进程更新统计信息,并将新的含有RDB格式和aof格式的文件替换旧的aof文件
优点
混合持久化机制结合了rbd持久化和aof持久化,由于绝大多数是rdb格式加载速度更快了,同时结合aof,增量的数据以aof方式保存,数据丢失更少
缺点
1.兼容性差,一旦开启混合持久化4.0之前都不识别该aof文件,同时由于绝大多数以rdb形式,阅读性较差
小总结
小总结
redis提供了rdb持久化方案,为什么还要aof?
优化数据丢失问题,rdb会丢失最后一次快照后的数据,aof丢书不会超过两秒
如果aof和rdb同时存在,听谁的
aof
rdb和aof优势和劣势
rdb适合大规模的数据恢复,同时对数据的完整性和一致性要求不高,在一定时间做一次数据备份,如果redis宕机的话,会丢失最后一次快照后的所有操作
aof根据配置项设置,一般不会丢失超过两秒的数据
Redis主从复制
单机有什么问题
单机故障
容量瓶颈
qps瓶颈
作用
1.读写分离
2.容灾备份
命令传播阶段出现断网
1.网络闪断闪连,忽略
2.段时间断网,增量
3.长时间断网,全量
全量复制核心三个条件
1.服务器运行id,用于服务器之间的通讯验证,当master首次连接slave时,会将自己的run_id发送个slave,slave保存
2.主服务器挤压的命令缓冲区,先进先出队列
3.主从服务器的偏移量,对比偏移量,然后判断执行全量还是增量
缺点
由于全部的写操作都在mater上,写操作无法实现负载均衡,然后同步更新到slave上,同步网络有一定延迟。
当主服务器宕机之后,将不能进行写操作,需要手动将从机升级到主机
Redis哨兵模式
作用,是什么
2.8开始引入,核心功能是主节点的故障转移
主要是为我们解决master选举的问题
功能
1.监控,哨兵会不断的检查主节点和从节点是否正常运作
2.自动故障转移
3.配置提供者,客户端在初始化时,通过连接哨兵来获得当前redis服务的主节点地址.
4.通知,哨兵可以将故障转移结果发送给客户端
架构
哨兵节点
哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的redis节点,不存储数据
数据节点
主节点和从节点
基本原理(重要)
主管下线
(针对所有服务器)在心跳检测定时任务中,如果其他节点超过一定的时间没有回复,哨兵节点会将其进行主观下线,(一个哨兵主观的判断下线)
客观下线
哨兵节点在对主节点进行主观下线后,会通过sentinel is-master-down-by-addr命令询问其他哨兵节点该主节点的状态,如果判断主节点下线的哨兵数量超过一定的值,则对主节点进行客观下线.
选举算法(Raft算法)
选举sentinel
故障转移
由选举出得领导者开始进行故障转移,在从节点中选择新的主节点
原则
1.首先过滤掉不健康的从节点
2.过滤掉响应慢的节点
3.过滤掉与mater断开时间最久的
4.优先选择,由replica-prioriry指定,如果无法区分则选择偏移量最大的,还是无法区分选择runid最小的从节点
redis Cluster
指派槽
通过crc16算法算出key的槽位
MongoDB
特征
存储json格式
memercache
特征
没有高可用,没有持久化
缓存的几大问题
缓存颗粒度
在使用缓存时,是将所有数据缓存还是部分数据缓存
缺点
空间浪费,网络带宽的浪费,代码通用性差
解决方式
综合数据通用性,空间占用比,代码维护性
缓存穿透
产生原因
多次请求不存在的key
解决方式
1.创建缓存空对象
2.使用布隆过滤器
Google布隆过滤器的缺点
1.基于jvm内存的一种过滤器,重启即失效
2.本地内存无法用在分布式场景,不支持大数据量存储
Redis布隆过滤器
可扩展性Bloom过滤器,达到容量重新创建一个新的过滤器
不担心重启即失效或者需要定时任务去维护的成本
缺点
需要网络IO,性能比Google差
缓存击穿
高并发情况下,查询大量的缓存中没有,数据库有的数据
解决方案
分布式锁
缓存雪崩
产生原因
大量的key设置了相同的过期时间,导致缓存在同一时刻全部失效,请求全部转发到DB,DB瞬时压力过重雪崩
解决方案
1.缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量.
2.做二级缓存,A1为原始缓存A2为拷贝缓存A1设置短期A2设置长期
3.不同的key设置不同的过期时间
关系型数据库
Mysql
数据库设计
三范式
1.原子约束,每列不可再分
2.保证唯一性,如主键
3.不要有冗余数据
分库分表
分库
条件
服务拆分,每个小项目有独立数据库,互不影响
分表
条件
按年存放日志
应用
1.使用一张大表专门存储所有数据
2.取模算法实现分表,均匀分配
缺点
1.分页查询
2.查询非常受限
解决方式:使用视图合成一张表
概念
关系型数据库管理系统
SQL优化
慢查询
概念
默认语句超过10s未响应的查询为慢查询
查询慢查询次数
show status like 'slow_queries'
查询慢查询时间
show variables like 'long_query_time'
SQL语句优化
1.首先通过执行计划定位慢查询
2.添加索引
SQL优化技巧
1.在group by 后面增加 order by null 就可以防止排序,提高效率
2。使用连接来替代子查询,不会在内存中创建临表
3.对查询进行优化,避免全表扫描,在where以及orderby涉及的列上建立索引
4.避免在where字句中对字段进行null值判断,容易导致引擎放弃使用索引,进行全表扫描
补充:尽可能使用not null填充数据库,char()型 null也占用空间
数据引擎
MyISAM
1.MyISAM不支持事务
2.MyISAM批量插入速度快
3.表级锁
4.支持全文索引
INNODB
1.INNDB支持事务
2.5.6之后支持全文索引
3.一般行级锁,update table set id=3 where name like 'a%';)全表锁
如何选择
不需要用到事务的时候,做很多count用myisam
可靠性要求高,或者要求支持事务
想要用到外检约束的时候
索引
概念
单独的,存储在磁盘上得数据库结构,指向表中所有记录的引用指针,是一种排好序的数据结构
底层结构
B+树,属于折半查找
缺点
增加,删除,索引文件也需要更新,占内存
优点
提高查询效率
使用条件
1.查询次数比较多,非常多不同值的字段
2.where条件需要查询的,值非常多不同
种类
主键索引
primary key
alter table 表明 add primary key(列名)
唯一索引
unique
alter table 表名 add unique 索引名(列名)
组合索引
子主题
全文索引
概念
将存储在数据库中得文章或者句子等任意内容信息查找出来的索引,单位是词
子主题
添加全文索引
alter table command add fulltext(instruction)
使用全文索引
select * from 表名 match 字段名 against ('检索内容')
普通索引
index
create index 索引名 on 表名(列名)
关系型数据库特征
1.持久化
2.主外键
3.sql语句
Web安全
表单重复提交(模拟http请求)CSRF
产生原因
网络延迟,刷新,回退
解决方式
前端
点击按钮之后置灰
后端
使用验证码+token令牌
XSS攻击(脚本注入)
产生原因
输入js脚本,提交
解决方式
1设置过滤器拦截所有请求
2重写获取值的方法,将特殊字符转成html
防盗链
概念
解决方式
判断请求来源
对称加密
概念
对称加密算法又称传统加密算法,加密和解密使用同一个秘钥
加密解密过程
明文->秘钥加密->密文,密文->秘钥解密->明文
优缺点
算法公开,计算量小,加密速度快,加密效率高.双方使用相同的秘钥,安全性得不到保证
注意事项
秘钥的保密工作非常重要,秘钥要求定期更换
非对称加密
概念
非对称加密算法又称现代加密算法
非对称加密是计算机通信安全的基石,保证了加密的数据不会被破解
非对称加密算法需要两个秘钥,公开密钥和私有密钥,并且是一对
优缺点
算法强度复杂,安全性依赖于算法和密钥,加密解密速度慢
两者之间的对比及应用场景
对称加密只有一种密钥,并且是非公开的,如果要解密就得让对方知道密钥。
非对称加密有两种密钥,其中一个是公开的。
非对称加密有两种密钥,其中一个是公开的。
由于RSA算法的加密解密速度要比对称算法速度慢很多,在实际应用中,通常采取
数据本身的加密和解密使用对称加密算法(AES)。
用RSA算法加密并传输对称算法所需的密钥。
数据本身的加密和解密使用对称加密算法(AES)。
用RSA算法加密并传输对称算法所需的密钥。
设计模式
主要作用
重复利用,代码易于扩展,提高代码阅读性,减少代码
设计模式六大原则
开闭原则
扩展性,易于修改
里式代换原则
接口隔离原则
接口隔离,降低类之前的耦合度
依赖倒转原则
面向接口编程
迪米特法则
保持类的相对独立性
合成复用原则
代码复用
常见的设计模式23种
单例
概念
保证一个jvm中只有一个实例
懒汉式
线程不安全,需要的时候才会实例化
恶汉式
线程天生安全,jvm class类加载的时候就初始化
工厂设计模式
代理设计模式
适配器设计模式
包装设计模式
集合
二叉查找树
概念
是一颗二叉树,它的左子节点的值比父节点小,它的右子节点的值比父节点大。高度决定了它的查找效率
时间复杂度
O(logn)最坏情况为O(N)
二叉查找树存在的问题
树倾斜
平衡二叉查找树
平衡树在插入和删除的时候,会通过旋转操作使树的高度保持在logN
AVL树
AVL树实现比较复杂,而且插入和删除性能差,在实际环境下得应用不如红黑树
红黑树
概念
1.每个结点或是红的,或是黑得
2.根结点是黑得
3.每个叶结点是黑的
4.如果一个结点是红的,则它的两个儿子都是黑的
5.对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点.
插入数据
1.将新结点的color赋为红色
原因
如果是黑色,就会导致根到叶子的路径上一条路径上,有一个额外的黑结点,这个是很难调整的.但是设为红色结点后,可能会导致出现两个连续的红色结点的冲突,那么可以通过颜色调换和旋转来调整,就简单多了.
以BST的插入方法到红黑树中.
HashMap
数据结构
1.7数组+链表
1.8数组+链表+红黑树
1.8的HashMap为什么要使用红黑树?
当元素个数小于一个阀值时,链表整体的插入查询效率要高于红黑树,当大于这个阀值的时候链表的整体的插入查询效率要低于红黑树.阀值为8
HashMap什么时候将链表转为红黑树?
当链表中得元素个数大于8,并且数组的长度大于等于64时
原因
如果数组长度还比较小,首先利用扩容来缩小链表的长度
1.8中HashMap得put方法的实现过程
1.首先根据key生成对应的hashCode
2.判断当前HashMap对象中得数组是否为空,如果为空则进行数组的初始化
3.根据逻辑与运算,算出hashCode基于当前数组对应的数组下标i
4.判断数组的第i个位置的元素是否为空
a.如果为空,则将key,value封装为Node对象赋值给tab[i]
b.如果不为空
i.如果put方法传进来的key等于tab[i].key,那么证明存在相同的key
如果不等于tab[i].key,且对应位置的类型是TreeNode,表示这个位置是红黑树,那么将key和value插入到红黑树中,在之前判断红黑树中是否存在相同的key,如果是链表,先遍历链表查找是否存在相同的key,并且在遍历的过程中会对链表的结点数进行计数,当遍历到最后一个结点的时候,将key,value封装成Node插入到链表的尾部,同时判断链表的结点个数是不是大于8,大于则将链表改为红黑树.
iii如果在上述操作中发现存在相同的key,则根据onlyifAbsent标记来判断是否需要更新值,然后返回oldValue
modCount++
HashMap的元素个数size+1
如果size大于扩容的阀值,则进行扩容
1.8中HashMap的get方法的实现过程
1.根据key生成hashCode
2.如果数组为空,则直接返回空
3.如果数组不为空,则利用hashCode和数组长度通过逻辑与操作算出key对应的数组下标i
4.如果数组的第i个位置上没有元素则直接返回空
5.如果数组的第i个位上得元素的key等于get方法传进来的key,则返回该元素,并获取该元素的value
6.如果不等于则判断该元素有没有下一个元素,如果没有,返回空
7.如果有判断该市链表还是红黑树,进行遍历
8.找到即返回元素,没有则返回空
JDK7与JDK8中HashMap的不同点
1.JDK8使用了红黑树
2.JDK7中链表的插入使用的头插法(扩容转移元素的时候也是使用头插法,头插法速度更快,无需遍历链表,但是在多线程情况下会出现循环链表的问题,导致cpu飙升),JDK8中链表使用尾插法,因为反正要去计算链表当前结点的个数,反正要遍历链表的
3.JDK7的hash算法更复杂,hash算法越复杂,生成的hashcode则更散列,那么hashmap中得元素则更散列,hashmap的查询性能更好,jdk7中没有红黑树,所以只能优化hash算法使得元素更散列,而jdk8中增加了红黑树,查询性能能得到保障,所以可以简化一下hash算法
4.扩容的过程中jdk7有可能会重新对key进行hash,重新hash跟hash种子有关系.jdk8没有这部分逻辑
5.jdk8与jdk7的扩容的条件不一样,除了判断size是否大于阀值外,jdk7还判断了tab[i]是否为空,不为空得时候才会进行扩容
6.jdk8中多了一个api:putifabsent(key,value)
7.jdk7和jdk8扩容过程中转移元素的逻辑不一样,jdk7是每次转移一个元素,jdk8是先算出来当前位置上哪些元素在新数组的低位上,哪些在高位上,然后一次性转移
ConcurrentHashMap
JDK7ConcurrentHashMap是如何保证并发安全的
1.主要是利用Unsafe操作+ReentrantLock+分段思想
主要使用了Unsafe操作中的
compareAndSwapObject:通过cas方式修改对象的属性
2.putOrderedObject:并发安全的给数组某个位置赋值
3.getObjectVolatile:并发安全的获取数组某个位置的元素
分段思想的目的
提高ConreentHashMap的并发量,分段数越高则支持的并发量越高,可以通过参数ConcurrencyLevel指定并发量,通过内部类Segment表示一个段
每个Segement就是一个小型HashMap,当调用ConrrentHashMap的put方法,最终会调用Segement的put方法,而Segment类继承ReentrantLock,所以Segement对象自带可重入锁,当调用put方法时,首先会利用可重入锁加锁,加锁成功再将key,value插入到一个小型的hashMap中,最终解锁
JDK7中的ConcurrentHashMap的底层实现原理
底层是由两层嵌套数组实现的
1.ConcurrentHashMap对象中有一个属性segements,类型为Segement[]
Segement对象有一个属性table,类型为HashEntry[]
当调用ConcurrentHashMap的put方法时,首先根据key计算出对应的segment数组的下标j,确当好当前key,value应该插入到哪一个Segment对象中,如果segement[j]为空则通过自旋的方式在这个位置生成一个Segment对象.
再调用Segment对象的put方法,首先会通过自旋加锁加锁,如果超过一定次数则发生阻塞,然后根据key计算出对应HashEntry[]数组下标i,然后将key,value封装成一个HashEntry对象放入到当前位置
JDK8ConcurrentHashMap是如何保证并发安全的
1.主要是利用unsafe操作+synchronized关键字
synchronized主要负责在需要操作某个位置时进行加锁(该位置对象不为空)
当向ConcurrentHashMap中put一个key,value时
首先根据key计算出对应的数组下标i,如果该位置没有元素,则通过自旋的方式赋值
如果该位置有元素,则synchronized会加锁
加锁成功后判断元素类型,如果是链表则进行添加到链表中,如果是红黑树则添加到红黑树中
添加成功判断是否需要树化
addCount方法,这个方法意思是每增加一个元素+1,这个操作也需要并发安全的,并且在添加成功后会继续判断是否要进行扩容
同时一个线程在put时如果发现当前concurrntHashMap正在扩容会帮助扩容
两个不同点
JDK8中没有分段锁了,而是使用synchronized来进行控制
JDK8中的扩容性能更高,支持多线程同时扩容,实际上JDK7中也支持多线程扩容,因为JDK7中的扩容是针对每个Segment的,所以也可能多线程扩容,但是性能没有JDK8高,因为JDK8中对于任意一个线程都可以去帮助扩容
JDK8中的元素个数统计的实现也不一样了,JDK8中增加了CounterCell来帮助计数,而JDK7中没有,JDK7中是put的时候每个Segment内部计数,统计的时候是遍历每个Segment对象加锁统计(当然有一点点小小的优化措施,看视频吧..)。
JDK8中的扩容性能更高,支持多线程同时扩容,实际上JDK7中也支持多线程扩容,因为JDK7中的扩容是针对每个Segment的,所以也可能多线程扩容,但是性能没有JDK8高,因为JDK8中对于任意一个线程都可以去帮助扩容
JDK8中的元素个数统计的实现也不一样了,JDK8中增加了CounterCell来帮助计数,而JDK7中没有,JDK7中是put的时候每个Segment内部计数,统计的时候是遍历每个Segment对象加锁统计(当然有一点点小小的优化措施,看视频吧..)。
中间件(完善中)
概念
在消息的传输过程中保存消息的容器(利用高效可靠的消息传递机制进行与平台无关的数据交流)
目的
提供路由并保证消息传递
注意点
当发生消息接收者不可用时,消息队列会保留消息,直到可以传递为止,当然也有期限
特点
1.采用异步处理模式
2.应用程序和应用程序调用关系为松耦合关系
3.队列消息可以存放在内存中也可以是持久的,保证消息服务出现故障时仍能传递消息
传递模型
点对点模型(PTP)
接收者在成功接收消息之后需向队列应答成功
发布-订阅模型(Pub/Sub)
定义了如何向一个内容节点发布和订阅消息(内容节点只主题)
特点
每个消息可以有多个消费者
消息
概念
由消息头和消息体组成
交换器
概念
用来接收生产者发送的消息并将这些消路由给服务器中得队列
类型
direct发布订阅,完全匹配
famout广播
topic主题,规则匹配
Queue消息队列
概念
用来保存消息直到发送给消费者,是消息的容器
交换器和队列之间的关系
交换器通过路由健和队列绑定在一起,如果消息拥有的路由健跟交换器和队列匹配,消息就会被路由到队列中
RabbitMQ为什么需要信道,为什么不TCP直接通信
1.TCP的创建和销毁开销特别大,创建需要三次握手,销毁需要四次挥手
2.如果不用信道,那么应用程序会以TCP连接rabbitmq,高峰时每秒上千万的链接造成资源浪费,并且操作系统每秒处理的tcp连接数也是有限的,必将造成性能瓶颈.
3.信道的原理是一个线程一条通道,多个线程多个通道同用一个tcp链接,一条tcp链接可以容纳无限的信道.
Rabbitmq消息处理
ACK机制
消费者从rabbitmq接收到消息,并处理完成后,反馈给rabbitmq,rabbitmq接收到反馈才将消息从队列中删除
mybatis(完善中)
概念
ORM映射框架,对象关系映射,就是将Java中得对象与数据库的表对应起来
mybasit与hibernate的区别
1.mybatis是以sql语句得到对象
2.hibernate是以对象得到sql语句
Sql注入问题
进行字符串拼接,如1=1
解决方式
先预编译,再传参数
一级缓存
二级缓存
JVM
概念:一种能够运行java字节码的的虚拟机
注意点:只要生成的编译文件匹配JVM加载编译文件格式要求,kotlin,scala
基本结构
类加载子系统
运行时数据区(内存结构)
执行引擎
类加载机制(要答三个)
类的生命周期
加载.class文件读取到内存
连接:
验证字节码文件格式的正确性
准备:
给类的静态变量分配内存,并由虚拟机赋予默认值
解析:
类装载器装入类所引用的其他所有类
初始化各种静态变量和执行静态代码块
上述的准备阶段为静态变量赋予的是虚拟机默认的初始值,此处赋予的才是程序编写者为变量分配的真正的初始值,执行静态代码块
使用
卸载
类加载器的种类:
启动类加载器Bootstrap JVM内部实现通过c++编写
负责加载jre的核心类库,rt..jar...charsets.jar
扩展类加载器ext
负责加载jre扩展目录ext中Jar类包
系统类加载器AppClassloader
负责加载classpath路径下得类包
用户自定义加载器
负责加载用户自定义路径下得类包
类加载机制
全盘负责委托机制
当一个ClassLoader加载一个类的时候,除非显示的使用另一个ClassLoader,该类所依赖和引用的类也由这个ClassLoader载入
双亲委派机制
指先委托父类加载器寻找目标类,在找不到的情况下在自己的路径中查找并载入目标类
双亲委派机制的优点:
1.沙箱安全机制
比如自己写的String.class类不会被加载,这样可以防止核心库被随意篡改
2.避免类的重复加载
当父classLoader已经加载了该类的时候,就不需要子classLoader再加载一次
java内存结构(运行时数据区)
概念
jvm虚拟机存储空间
方法区:
包含静态变量,常量,类信息(构造方法、接口定义),运行时常量池
jdk 1.8之前叫永久区,1.8之后叫元空间
常量池
概念
用于存放编译器生成的各种字面量和符号引用
字面量
String s1="hello";"hello" 为字面量
特点
受到方法区内存的限制,容易抛OOM
堆:
概念:
存放对象的实例,数组
特点:
对象无法在此空间申请到内存容易抛OOM,垃圾收集器管理的主要区域
新生代
Eden区
刚创建的对象存放
当此区域的空间用完时,程序又需要进行对象创建,JVM垃圾回收器将进行垃圾回收,Minor GC
Survivor space
From区
To区
老年代
频繁使用的对象存放,新生代经过多次GC仍然存在的对象移动到老年代,当老年代也满时发生full GC
元空间(1.8之后代替了永久代)
概念
对JVM规范中方法区的实现,不存在虚拟机中,存在于本地内存.
为什么移除永久代?
移除永久代是为融合HotSpot与 JRockit而做出的努力,因为JRockit没有永久代,不需要配置永久代
栈
概念
作用于方法执行的一块Java内存区域
特点
一个线程对应一个栈,每个方法在执行的同时都会创建一个栈帧(用于存储局部变量表,操作数栈,动态链接,方法出口等信息)不存在垃圾回收问题,只要线程一结束该栈就释放,生命周期和线程一致
本地方法栈
概念
为JVM执行native方法服务
特点
登记native方法,在Execution Engine执行时加载本地方法库
程序计数器
下一次执行的内存指针
对象创建的底层步骤
1.虚拟机在遇到new指令时,首先检查对应的类在常量池中是否定位到类的符号引用
2.检查这个类是否已被加载,解析,初始化
3.为这个新生对象在java堆中分配内存.
指针碰撞
开辟一块内存
移动指针
存在的问题
非原子操作可能存在并发问题,java虚拟机采用CAS配上重试机制保证更新操作的原子性
空闲列表
开辟一块内存
修改空闲列表
同上
4.将分配到得内存空间都初始化为零值
5.设置对象头的相关数据
1.GC分代年龄
2.对象头的hashCode
3.元数据信息
6.执行对象的init方法(静态代码块)
GC算法和收集器
判断对象存活算法
引用计数法
引用一次计数器加1,失效一次计数器减一
可达性分析算法
基本思想
通过GC Roots对象作为起点,向下搜索,节点走过的路径叫做引用链
引用链概念
节点走过的路径
当一个对象到GC Roots没有任何引用链相连的话,则证明此对象是不可用的
可作为GC Roots对象
虚拟机栈中引用的对象(本地变量表),本地方法栈引用的对象,方法区中静态属性引用的对象,方法区中常量引用的对象
如何判断一个常量是废弃常量?必然进行回收
当没有任何对象引用该常量
如何判断一个类是无用的类,可以进行回收?
该类的所有实例都已经被回收
加载该类的类加载器已经被回收
该类对应的java.lang.Class对象没有在任何地方被引用,无法通过反射访问该类的方法
垃圾回收算法
标记-清除算法
概念
首先标记需要回收的对象,最后统一回收。
缺点:
标记和清除的效率低
不是连续的,容易产生碎片化
复制算法(为了解决效率问题)
概念
每次只使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块区,然后再把使用的空间一次清理掉
优点
效率较高
连续性不产生碎片化
缺点
可使用的内存变为原来的一半
标记-整理算法(用于老年代)
概念
标记需要清除的对象,然后把存活的对象压缩到内存一端,而后进行垃圾回收
分代收集算法
概念
根据不同的年代采取不同的算法
垃圾收集器
Serial收集器(串行收集器)
特点
单线程,效率低,工作期间需要暂停所有工作线程
ParNew收集器(并行收集器)
特点
多线程,效率高,应用程序仍暂停
Parallel Scavenge收集器 1.8
特点:
与ParNew类似但吞吐量更高,CMS等垃圾收集器的关注点更多的是用户线程的停顿时间(提高用户体验)
G1收集器
如何选择垃圾收集器?
优先调整堆的大小让服务器自己来选择
如果内存小于100m,使用串行收集器
如果是单核,并且没有停顿时间的要求,串行或JVM自己选择
如果允许停顿时间超过1秒,选择并行或者JVM自己选
如果响应时间最重要,并且不能超过1秒,使用并发收集器
垃圾回收机制的概念及补充
不定时在堆内存清理不可达对象
注意:
执行之前执行Obect.finalize方法
内存溢出
对象创建需要4G 只支持3G
内存泄露
定义过多的静态变量,垃圾回收不会回收
微服务
Spring Cloud
解决什么问题
1.配置管理
2.服务注册和发现
3.熔断
4.路由策略和负载均衡
5.全局锁
6.分布式回话
7.接口网关
8.链路追踪
重要组成
Eureka(注册中心)
概念
服务管理
核心
服务注册表,通过心跳机制动态维护
组成
provider服务提供者
启动的时候向注册中心上报自己的网络信息
consumer服务消费者
启动的时候向注册中心上报自己的网络信息,拉取provider的相关网络地址
优点
微服务应用和机器越来越多,调用方需要知道接口的网络地址,如果靠配置文件的方式去控制网络地址,对于动态新增机器,维护带来很大问题
ribbon
概念
一种负载均衡客户端,类似nginx反向代理
Feign
概念
伪EPC客户端,本质还是用http
优点
默认集成ribbon
写起来思路更加清晰方便
采用注解的方式进行配置,配置熔断等方便
Hystrix(熔断器)
概念
熔断
熔断服务,为了防止整个系统故障
降级
抛弃一些非核心的接口和数据
区别和相同点
相同点
从可用性和可靠性触发,为了防止系统崩溃
最终让用户体验到的时某些功能暂时不能用
不同点
熔断一般是下游服务故障导致的,
降级一般是从整体系统负荷考虑,由调用方控制
作用
解决系统负载过高,突发流量或者网络等各种异常问题
Dubbo
配套组成
通信方式
http+restful
注册中心
zookeper/redis
服务管理,核心是有个服务注册表,通过心跳机制动态维护
好处
微服务的情况下,应用和机器越来越多,调用方需要知道接口的网络地址,如果靠配置文件的方式去控制网络地址,对于动态新增机器,维护带来很大的问题
配置中心
diamond企业中很少用
服务提供者provider
启动的时候向注册中心上报自己的网络信息
服务消费者consumer
启动的时候向注册中心上报自己的网络信息,从注册中心拉取provider的相关信息
Zookeeper注册中心
数据模型
1.类似于linux文件系统,树
2.每一个节点都叫zNode,可以有子节点,也可以有数据
3.每个节点都能设置相应的权限控制用户的访问
4.每个节点的数据存储不宜过大
5.每个节点都带有一个版本号,数据变更时,版本号会变更
6.节点分为临时节点和永久节点
临时节点,session断开,临时节点会自动删除(分布式锁)
session机制
介绍
用于客户端与服务端之间的链接,可设置超时时间,通过心跳机制(客户端发送Ping包给服务端),客户端高速服务端还活着
session过期
该session创建的所有临时节点都会被抛弃
watcher机制
(针对父节点,子节点)对节点进行监听,数据变更时会触发watcher机制,原生每一次执行就消失
get,stat 指针对当前节点进行监听.
ls,ls2 对子节点进行新增和删除会通知父节点.
权限控制
设置权限
set /xdclass auth:xdclass:xdclass:cdrwa
注册用户
addauth digest xdclass:xdclass
三种角色
leader:
可读数据,作为写请求唯一的处理者,并负责系统投票操作决议的发起
follwer
接受客户端请求,能处理读请求,并向客户端返回结果,同时将写请求转让给leader,在选举中参与投票,过半集群不可用
observer
可以看做一种无选举投票权的follwer,主要为了协助follwer处理更多读请求,如果集群负载过高,可用设置一些observer服务器以提高吞吐量,同时宕机不影响集群的正常运行
zookeeper注册中心常见的三种模式(核心是广播机制,保证集群之间数据一致性.)实现机制为ZAB协议【zookeeper原子广播】
恢复模式
当leader崩溃时,恢复模式开启,时集群集群恢复到工作状态,进行选举
同步模式
当选出出新的leader以后,就进入同步模式,各follwer会去同步leader上得数据,结束之后恢复模式就结束了
广播模式
当客户端想可入数据时,这个时候leader发起决议,当leader决议被大多数zookeeper服务器同意以后,leader修改自己的数据,并将自己的数据通过广播的方式广播给其他follower。
【zookeeper集群选举核心概念】
myid
集群中各服务器的唯一标识
zxid【Long类型】
高32位epoch
每个leader都会有一个epoch,表示一个时期,一个时代
低32位xid
zk事务id,每一个写操作都会有一个xid
逻辑时钟
logicalclock,整型,在选举时称为logicclock,在zxid称为epoch
zookeeper选举状态
looking
查找leader的状态
leading
领导者状态
following
随从状态,同时同步leader数据
obsering
观察状态,不同leader数据
分布式锁作用及原理
解决问题
分布式情况下,各个服务节点需要竞争同一资源,没办法使用单机多线程jdk自带锁
zookeeper实现分布式锁原理
去创建临时节点,创建成功,则获取锁,创建失败,则表示获取锁失败
实现方式
注意.创建临时节点,防止宕机导致锁不能释放
1.尝试创建锁,创建成功,则获取锁,获取不到锁,程序进入短暂休眠,之后进行重试
缺点;浪费资源
2.使用zookeeper watcher机制,当节点进行删除时通知程序获取锁
缺点:对程序容易引起羊群效应
3.创建有序节点,基于原生的api实现分布式锁
zookeeper集群选举发生时机及选举算法
发生时机
1.服务刚开始启动的时候
2.leader宕机之后
选举算法
1.服务启动时:
第一台给自己投票并发布myid,zxid,此时处于looking状态
第二台同样给自己投票并发布自己myid,zxid,同样处于looking状态
如果zxid相等的情况下,第二台myid大,第二台胜出,第三台不参与选举
2.服务宕机时
此时各服务处于looking状态,比较算法同上,如果leader给第二台同步数据以后宕机,那么第二台的zxid大于第三台
Dobbo超时机制和集群容错机制
1.服务提供方进行配置
如果方法跟整个服务同时设置超时时间,以方法设置为准
2.如果服务提供方和服务消费方同时设置超时时间,以服务消费方为准
3.服务调用失败,默认重试2次
单体应用和微服务,SOA架构
单体应用
项目分为逻辑层,数据库层,控制层均在一个项目中
缺点
不适合大团队开发
开发速度慢
启动时间长
依赖庞大
微服务
特点
每个服务独立运行,对应一个数据库,轻量级
通讯协议
http协议+restful风格+json
优点
易开发,理解和维护
独立的部署和启动
SOA架构
面向服务架构
服务层
包含业务逻辑,只需要对外提供服务
表现层
只需要处理和页面的交互
出现原因:
解决分布式架构的缺点
分布式架构的缺点
系统之间通讯需要使用远程通信,接口开发增加工作量
各个模块有一些通用的业务无法共用
优点
代码复用,解耦
通讯协议
soap
http协议+xml ,采用xml格式报文格式传输,进行序列化和反序列化操作
分布式
分布式两种理论
CAP理论
一致性C
所有节点在同一时间的数据完全一致,机器越多,同步数据越耗时
可用性A
负载过大时,服务一直可用,而且是正常响应时间
分区容错性P
挂掉几个节点不影响服务正常运行
BASE理论
核心思想
即使无法做到强一致性,但每个应用都可用根据自身特点,采用适当的方式使系统达到最终一致性
基本可用
分布式系统在出现不可预知故障时,允许损失部分可用性
软状态
允许系统在不同节点间副本同步存在延迟
最终一致性
本质
需要系统保证最终数据的一致性,而不需要实时保证系统数据的强一致性
所有的数据副本,在经过一段时间同步之后,最终都能达到一致的状态
分布式与集群的区别?
集群
概念
部署多台相同应用构成集群
作用
减轻单台设备的压力,实现高并发
分布式
概念
根据业务需求将项目拆分成各个子系统,各子系统项目协作
作用
做解耦操作
通信调用方式
RPC
概念
远程过程调用,像调用本地服务方法一样调用服务器的服务
优点
支持同步异步调用
客户端与服务器之间建立TCP连接可以一次建立一个,也可以多个调用复用一个连接
数据包小
存在的问题
编解码
序列化
连接
丢包
协议
RMI
缺点
非 JAVA 语言开发的应用系统的支持不足,不能与非 JAVA 语言书写的对象进行通信
Http
支持多种协议和功能
开发成本低
数据包大
缺点
存在网络延迟
分布式事务问题
编码复杂
分布式事务
产生原因
每个服务器与服务器之间有自己独立的数据源
分布式事务解决框架
TCC
GTS(阿里)
LCN框架
是一个分布式事务解决框架,不产生事务,而是事务的协调者,发起方需要调用参与方接口时,发起方会再tx-manager上创建一个分组id,当发起方调用接口时,会重写feign方法,在请求头上添加分组id传给参与方,参与方获取分组id,会认为要发生协调了,做一个假关闭,重写close方法一直等待,发起方代码无异常时,通知协调者再由协调者通知参与方是提交还是回滚
并发编程
应用程序
概念
可执行的软件
进程
执行中得一个程序,程序一旦被载入到内存中并准备执行,就是一个进程。
多线程的集合
注意
在进程中,一定有一个主线程
线程
概念
正在独立运行的一条执行路径
多线程
概念
分时利用CPU,宏观上就是多个线程一起执行,也叫并发
创建方式
继承Thread类,重写run方法
实现Runnable接口,重写run方法
使用匿名内部类方式
实现Callable接口,通过FutureTask包装器来创建Thread
优势
提高程序效率,每个线程互不影响,独立运行
线程的生命周期
出生状态
new Thead
就绪状态
调用start方法
执行状态
线程获得CPU时间片以后
阻塞状态
1线程发生IO时
2.试图得到一个锁时
死亡状态
run方法执行完
异常终止run方法
休眠状态
sleep()
守护线程
跟主线程与gc线程一起销毁
应用场景
后台下载
用户线程(非守护线程)
用户线程是主线程创建的线程
特征
和主线程互不影响
用途
分批发送短息
迅雷下载的断点续传
线程安全
概念
多个线程同时共享一个全局变量,做写的操作的时候会发生线程安全问题
解决办法
1.使用synchiroized 1.5之前是重量级锁(以上这些最好都答)
前提
必须有两个线程
必须用同一把锁
保证只有一个线程执行
原理
一个线程已经拿到锁,其他线程已经有CPU执行权的,一直排队,等待锁被释放
缺点
效率低,扩展性不高,不能自定义
深入理解(使非原子操作变原子操作,托管给jvm执行)
内置锁
每一个Java对象都可以作为实现同步的锁,java对象的对象头上有一个锁的标志位,通过表实位判定哪个线程获得相应的锁,线程在进入同步代码块或者方法的时候会自动获得该锁,在退出时候释放该锁,获得内置锁的唯一途径就是进入这个锁保护的同步代码块或者方法中
互斥锁
只有一个线程获得锁,其他线程等待
通过悲观锁的形式实现,其他线程只有通过阻塞才能获得锁
一个线程已经拿到锁,其他线程已经有CPU执行权的,一直排队,等待锁被释放
每一个对象都会有一个monitor对象,监视器,某一线程占用这个对象的时候,先看monitor得计数器是不是0,如果是0则没有线程占有,线程占有这个对象,并且将这个对象的monitor+1,如果不为0,这个线程等待,当线程释放占有权的时候,monitor-1
同一线程可以对同一对象多次加锁,体现了重入性.
如果是静态同步方法反编译以后是通过flags:ACC_SYNCHRONIZED进行加锁的,其他是通过monitorenter,monitorexist加锁和解锁的.有两个monitorexist是因为有一个是正常解锁,一个是异常情况下解锁.
JVM虚拟机对synchronized的优化
对象实例
对象头
Mark Word存储对象的hashCode和锁信息
实例变量
填充数据
无锁状态
是否偏向锁为0锁标志位为01
偏向锁
在对象第一次被某一线程占有的时候,是否偏向值为1锁标志位为01,同时写入线程号,当其他线程访问竞争失败升级为轻量级锁
轻量级锁
线程有交替使用,互斥性不是很强,CAS失败,锁标志位为00
重量级锁
互斥强,竞争激烈,锁标志位为10,11为gc标记
自旋锁
竞争失败的时候不会马上升级级别,而是执行几次空循环
2.Lock锁
深入理解
1.通过乐观锁的形式实现CAS的方式,其他线程获取失败继续重试
死锁
同步中嵌套同步,互不释放
乐观锁和悲观锁
概念
乐观锁和悲观锁不是指具体某一把锁而是并发编程中的一种概念,最早被设计于数据库中
乐观锁
乐观锁在获取数据的时候,并不担心数据是否被修改,每次获取数据的时候也不会加锁,只有在更新数据的时候,通过判断现有数据与原数据是否一致来判断数据是否被其他线程操作,如果没有则进行数据修改,没有则不进行数据更新.
悲观锁
悲观锁认为对于同一数据的并发操作,一定会发生修改的,因此悲观锁对于同一数据的并发操作,悲观锁采取加锁的形式.悲观的认为,不加锁的并发操作一定会出问题.
公平锁和非公平锁
概念
根据线程获取锁的抢占机制ReentrantLock默认提供非公平锁
公平锁
多个线程按照申请锁的顺序来获得锁
非公平锁
多个线程获取锁的顺序不是按照申请锁的顺序.
独占锁和共享锁
根据锁能否被多个线程占有
独占锁
任何时候都只有一个线程能执行资源操作
共享锁
可以同时被多个线程读取,但只能被一个线程修改.比如ReentrantReadWriteLock就是共享锁的实现方式,它允许一个线程进行写操作,多个线程进行读操作.
可重入锁
线程获取了该锁之后,可无限次数的进入该锁住的代码
自旋锁
尝试获取锁的线程不会立即阻塞,而是采取循环的方式去获取锁.
好处
减少线程上下文切换的消耗
缺点
循环消耗CPU
CAS
是一种乐观锁的实现,通过非阻塞算法来代替锁,java.util.concurrent下的包
会产生ABA问题,通过版本号控制
JAVA内存模型
多线程三大特性
原子性
保证线程安全
有序性
多线程之间通讯
可用性
Java内存模型
决定了一个线程对另一个线程是否可见
组成
主内存
主要存放共享的全局变量
私有内存
主要存放线程私有变量
Volatile关键字
防止指令重排,刷新主内存
优点和局限性
保证线程可见性,但不保证原子性
static关键字
所有线程共享,存放在永久区
公平锁与非公平锁
公平锁
遵循排队的规则
非公平锁
只要有机会就尝试去抢占资源
缺点
可能导致其他线程抢占不到CPU资源,引起线程饥饿
ReenTranTLock
并发包java.util.concurrnt
原子类
并发类
Lock锁
线程池
概念
管理复用线程,提高程序效率
优点
1.重复利用
2.提高响应速度,无需等待cpu调度
3.管理线程,通过线程池分配和创建线程
线程池原理分析
1.任务数量超过核心线程数时,进入线程缓存工作队列,创建线程,当超过最大线程数量时,执行拒绝策略
线程池中七个参数解析
1.corePoolSize核心线程数,最小的线程数量,即是空闲也不会被销毁
2.maximumPoolSize线程池最大线程数量
3.keepAliveTime空闲线程存活时间,指空闲中得并且大于核心线程数的线程存活时间
4.unit空闲线程存活时间单位
5.workQueue工作队列
1.ArrayBlockingQueue基于数组的有界阻塞队列,新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽的问题
2.LinkedBlockingQuene基于链表的无界阻塞队列,最大值为Integer.MAX.新任务进来会一直存入该队列,而不回去创建新的线程池
3.SynchronousQuene不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务,放入直接被执行
4.PriorityBlockingQueue具有优先级的无界阻塞队列,优先级通过参数comparetor实现
6.threadFactory线程工厂
创建一个新线程时使用的工厂,可以用来设定线程名,是否为daemon线程等等
7.handler拒绝策略,当工作队列达到最大值并且最大线程数达到最大值,执行拒绝策略
1.CallerRunsPolicy
只要线程池未关闭,该策略直接在调用者线程中运行当前被丢弃的任务.调用者线程性能可能急剧下降
2.AbortPolicy
直接丢弃任务,同时抛出RejectedExecutionException
3.DiscardPolicy
直接丢弃任务什么也不做
CAS和ABA问题
Socket网络编程(完善中)
跨域
概念
其实是浏览器的安全机制,请求访问的域名与ajax请求不一致,浏览器会无法直接返回请求结果
跨域问题的解决方案
1.后端配置类添加请求头,允许跨域设置
具体实现方式
response.setHeader("access-control-allow-origin","*")
2.使用JSONP
原理
使用js发送get请求,传参数jsonp,回调回来进行解析
缺点
只支持get请求
3.httpclient转发
4.使用nginx搭建企业api网关
NIO
Netty
BIO
客户端通过ip+端口号定位服务端应用程序
网络模型四层结构
应用层
HTTP协议
传输层
TCP协议
网络层
IP协议
链路层
以太网协议
Socket技术遵循一个规则
二进制+ip+端口号
Socket两个核心概念
UDP
面向无连接,不会建立连接,会发生丢包,无可靠协议
TCP
面向连接,必须经过三次握手才会进行通讯,通过字节流传输,效率没有udp高,协议靠谱
Tomcat
为什么打破双亲委派机制
重定向原理
外部访问,客户端跳转,地址会发生改变,两次请求
转发
内部服务调用
Linux网络编程五种IO模型
IO操作的步骤
1.发起IO请求,等待数据准备
2.实际IO操作,数据从内核复制到用户进程
1.阻塞IO
概念
客户端读写数据时会发生阻塞
工作流程
用户进程发起IO操作会调用内核函数recvfrom函数,内核会检查数据是否准备完毕,一直用户线程一直阻塞,数据准备好时,会同步的将数据从内核复制到用户空间,并返回成功指示
2.非阻塞IO
工作流程
用户进程发起IO操作会调用recvfrom函数,无需等待便可马上得到内核数据是否准备的结果.如果没有准备好会反复发起IO操作,一旦内核中数据准备好了,就会同步的将数据从内核复制到用户进程,并且返回成功指示.
注意点
进程采用轮询的方式反复调用recvfrom函数等待返回成功那个指示
3.IO多路复用
概念
IO多路复用模型中会由一个Selector线程不断轮询Socket状态,直到有读写时间,才会通知用户线程进行读写操作(才会调用recvfrom函数)
工作流程
一个Selector线程管理多个Socket通道,在Socket中有读写事件时才会触发用户线程调用recvfrom函数,同步的将数据从内核拷贝到用户线程,并返回成功指示
优点
1.一个Selector线程可以管理多个Socket通道,并且在真正有读写请求时,才会使用操作系统的IO资源,大大节省了系统资源
2.效率高,IO多路复用是在系统内核中检查Socket状态的.
缺点
1.如果事件的响应体很大时,Selector线程就会成为性能瓶颈,导致后续的事件迟迟得不到处理,影响下一次时间轮询,一般只做事件的接受和转发。
2.进程受阻于select调用,等待可能多个Socket中任意一个变为可读
信号驱动IO
概念
用户线程发起一个IO请求操作后,调用sigaction函数进行注册,在内核数据准备好时,系统会发送一个信号到用户线程,用户线程在接受到信号后,会调用recvfrom函数,同步的将数据从内核拷贝到用户空间,并返回成功指示.
异步IO
工作流程
用户线程发起一个asynchronous read操作到内核,内核在接收到以后会返回一个状态,用户表名是否发起成功.用户线程不发生任何阻塞,内核待数据准备好之后,将数据从内核复制到用户线程,完成之后内核会发送一个信号到用户线程,通知用户线程asyncread操作已经完成.可以直接使用数据。
基于futrure-listner回调监听机制,复制数据到用户线程也是异步的
几个重要知识点
1.阻塞和非阻塞是针对线程
2.同步和异步是针对消息的通知机制
3.同步和异步针对用户进程和内核进行交互
反射
概念
动态获取当前类的所有信息
作用
1、初始化对象
2.为类的私有属性赋值
优点
提供程序的扩展性,封装一些工具类用于编写框架,如jdbc连接驱动框架,Sring IOC
如何禁止?
将构造函数私有化
缺点
初始化对象效率低,好资源
事务(完善中)
目的
保证数据一致性
事务的特征
原子性
要么全部成功,要么全部失败
一致性
隔离性
多个事务之间互不影响
事务的隔离级别
脏读
幻读
不可重复读
spring事务
Spring事务分类
1.编程式事务
原理
获取数据源API,数据源API会封装一些手动begin,commit,rollback.
2.声明式事务
原理
运用aop编程的环绕通知方法之前或者之后执行,发生异常抛出异常通知并进行回滚.
多数据源下如何解决
补偿机制,MQ,TCC,重试机制
传播行为
概念
当事务方法被另一个事务方法调用时,必须指定事务如何传播
Spring(完善中)
Spring
一种容器,管理bean与bean之间的关系,使用spring进行管理.
好处
1.解耦
2.单例,节约内存
IOC
控制反转,将bean的对象的关系交给spring容器进行管理。
核心
反射机制+解析xml
DI
依赖注入,解决对象之间的依赖关系
依赖注入的几种方式
set方法注入
xml中p标签注入
注解注入
spring作用域
1.单例,使用恶汉式保证线程安全
2.多例
AOP
概念
相当于在方法执行之前做了一些处理
实现原理
jdk静态代理
cglib字节码加载,动态代理
应用场景
权限控制,事务
关注点
重复代码
切面
提取重复代码
切入点
拦截哪些方法
bean生命周期
1.创建bean对象,通过反射实现实例化对象
2.初始化属性,执行属性注入
3.通过BeanNameAware获取查找beanName
4.拿到beanFactory
5.获取上下文
6.执行bean的后置处理器
7.销毁bean
Springmvc
概念
web方向的控制层框架
核心技术
对servlet包装
源码的简单分析
1.springmvc将请求交给disPatcherServlet进行管理
2.执行disPatcherServelet的doService方法,然后交给doDispatch方法处理请求
3.通过doDispatcher方法获得请求的信息
4.通过实现HandlerAdapter开始执行拦截器
5.执行完毕后获取当前ModelAndView
6.执行视图解析
高可用(完善中)
Nginx
概念
反向代理,代理服务器,静态服务器
作用
1.集群(减轻单台服务器压力)
2.采用负载均衡策略进行轮训机制
提高网站吞吐量
3.反向代理(不暴露真实ip地址)
优点
1.占内存少,并发能力强,轻量级服务器
网站安全架构的搭建
1.使用nginx不暴露网站真实ip地址
2.使用https防止抓包分析http请求
3.搭建企业黑名单白名单系统,
4.模拟请求token+验证码
5.XSS攻击,使用过滤器拦截所有请求,将特殊字符转成html
6.sql注入,通过预编译进行sql拼接
7.ddos流量攻击,nginx
集群和分布式有什么不同
集群
减轻单台服务器压力
分布式
将一个项目进行拆分成多个子项目,分布式开发
目的
完成同一大体功能,RPC远程调用
nginx宕机容错机制实现高可用
1.一主一备,多主多备,配置宕机轮训规则,使用高可用工具keepalive重启脚本,自动重启.
子主题
高并发高可用解决方案
数据库层面
1.sql语句优化之前定位慢查询
2.通过执行计划任务看sql语句是否全表扫描
3.使用索引
注意事项
4.分库分表
5.水平分隔取模算法
6.主从复制,通过二进制日志文件
7.读写分离,mycat
缓存机制
1.使用redis缓存数据内容
2.redis集群,主从复制,读写分离
3.使用redis哨兵机制监听
服务器端优化
1.使用nginx反向代理
2.负载均衡,集群部署
3.使用动静分离
4.使用cdn加速,宽带从近访问服务器,多个地区进行部署
客户端
1.减少请求
2.用户体验感好,使用ajax异步加载
3.动静分离
项目优化
1.代码重构
2.jvm调优,通过垃圾回收机制,老年代新生代配置参数
3.采用微服务分布式架构
任务调度平台
传统任务调度缺点
1.没有补偿机制,发生异常必须等待下一次
2.不支持集群
3.不支持轮训,不支持路由策略
4.无管理平台
5.无法统计哪些有问题
6.无报警邮箱,状态监控
分布式任务调度框架
xxl-job
执行流程
任务
分布式任务调度平台(包含任务表,需要执行的任务)
执行器(Job运行服务器)
注意点
Job调度在调度平台执行
分布式调度平台原理
任何job先在调度平台执行,再由任务调度平台路由分发到实际job服务器
Elastic-job
收藏
收藏
0 条评论
下一页