Java知识点
2022-04-13 11:37:53 18 举报
Java面试知识点
作者其他创作
大纲/内容
网络
网络模型
五层
应用层
HTTP
传输层
TCP/UDP
网络层
数据链路层
物理层
TCP
特性
面向链接
可靠
如何保证可靠性
Socket
由 IP 地址和端口号组成
序列号
用来解决乱序问题等
窗口大小
用来做流量控制
字节流
格式
序列号
确认应答号
控制位
ACK
RST
SYC
FIN
TCP连接
三次握手
为什么要三次握手
避免历史连接
同步双方的初始序列号
避免资源浪费
TCP断开
四次挥手
为什么要有TIME_OUT
常见问题
什么是 SYN 攻击?如何避免 SYN 攻击?
UDP
格式
目标和源端口
主要是告诉 UDP 协议应该把报文发给哪个进程
包长度
该字段保存了 UDP 首部的长度跟数据的长度之和
校验和
校验和是为了提供可靠的 UDP 首部和数据而设计
TCP与UDP区别
连接
TCP 是面向连接的传输层协议,传输数据前先要建立连接
UDP 是不需要连接,即刻传输数据。
服务对象
TCP 是一对一的两点服务,即一条连接只有两个端点
UDP 支持一对一、一对多、多对多的交互通信
可靠性
TCP 是可靠交付数据的,数据可以无差错、不丢失、不重复、按需到达
UDP 是尽最大努力交付,不保证可靠交付数据
拥塞控制、流量控制
TCP 有拥塞控制和流量控制机制,保证数据传输的安全性
UDP 则没有,即使网络非常拥堵了,也不会影响 UDP 的发送速率
首部开销
TCP 首部长度较长,会有一定的开销,首部在没有使用「选项」字段时是 20 个字节,如果使用了「选项」字段则会变长的
UDP 首部只有 8 个字节,并且是固定不变的,开销较小
IP
工作原理
分片
增加协议头
寻址
组成
4 个 8 位(Octet)排列而成
寻址步骤
找各层网络
与子网掩码做位与运算
IPv4 的网络分成这样 4 层
通过地址找设备
路由(Routing)
路径的选择,已知道地址
ES
核心概念
Cluster:集群
Node:节点
每个es实例称为一个节点
自动分配
可手动配置
Index:索引
创建规则
仅限小写字母
不能包含\、/、 *、?、"、<、>、|、#以及空格符等特殊符号
不包括引号
不能以-、_或+开头
不能超过255个字节
倒排索引
Posting List(倒排表)
Term Dictionary(词典)
Term Index(词典索引)
其他核心
FST
有穷状态转换器
Frame Of Reference
索引帧
Roaring Bitmaps
咆哮位图
缓存的filter放到内存里面
数量小于4096
short数组保存
数量大于等于4096
bitmap保存
Document:文档
es中的最小数据单元
相当于数据库一行记录
Field:字段
数据库中的列(Columns)
定义每个document应该有的字段
Type:类型
每个索引里都可以有一个或多个type,type是index中的一个逻辑数据分类,一个type下的
document,都有相同的fifield
7.x没有了
shard:分片
replica:副本
将每个index的分片都备份存到另外的机器上
问题
脑裂
定义
原因
解决方案
springcloud
注册中心
nacos
特性
服务发现
服务发现
权重管理
打标管理
优雅上下线
配置管理
在线编辑
历史版本
一键回滚
灰度发布
推送轨迹
集群
理论
推举算法
Raft 选举算法
Leader节点产生
节点数据同步
Leader消息分发
部署
安装环境
cluster.conf
配置数据库
负载均衡
客户端负载均衡器
Ribbon
实现
RestTemplate+注释
使RestTemplate自动负载均衡
@LoadBalanced
RestTemplate.getForObject()
链接写服务名
均衡策略
轮询(默认)
随机
重试
最小连接数
可用过滤
判断该 server 是否超时可用、当前连接数是否超限
区域权衡
自定义均衡
实现IRule接口
服务通信
OpenFeign
必要
启用 OpenFeign 声明式通信
@EnableFeignClients
创建OpenFeign的通信接口
@FeignClient
可选
开启负载均衡
开启数据压缩功能
切换通信组件
API网关
gateway
关键
路由
谓词
谓词决定了路径的匹配规则
过滤器
对请求或响应作出实质的前置、后置处理
自定义过滤器
熔断器
配置中心
日志管理
链路追踪
资源
文档
Spring Cloud Alibaba 官方文档
算法
排序算法
比较类排序
交换排序
冒泡排序
快速排序
插入排序
简单插入排序
希尔排序
选择排序
简单选择排序
堆排序
归并排序
二路归并排序
多路归并排序
非比较排序
计数排序
桶排序
基数排序
Java sort()
对象
小于等于7
冒泡
大于7
归并
普通类型
小于7
插入排序
大于等于7
快速排序
size=7
首个元素为基准
7<size<=40
首、中、末三个元素中间大小的元素作为划分元
size>40
从待排数组中较均匀的选择9个元素,选出一个伪中数做为划分元
时间复杂度
leetcode
字符串中寻找子串
KMP算法
判断是否是回文
马拉车算法
JVM
内存
堆外内存
NIO的零拷贝
元数据区(JDK1.8)
使用本地内存
共享
方法区
永久代
存储
静态变量
类信息
类的版本
字段
方法
接口描述
即时编译机器码
运行时常量池
常量
常量
堆
内存比例
新生代(1/3)
结构
Eden(8/10)
存储
新创建的对象
配置
设置大对象的大小
XX PretenureSizeThreshold
ServivorTo(1/10)
保留幸存者
ServivorFrom(1/10)
保留幸存者,活下来的留到ServivorTo
存放
年轻对象
小对象
老年代(2/3)
存放
大对象
长生命周期的对象
永久代(JDK1.7)
存放
Class
Meta 元数据
使用JVM内存
回收算法
引用计数法
可达性分析法
私有
程序计数器
存储行数
不会溢出
虚拟机栈
栈帧
记录方法的执行过程
存储
局部变量表
存放局部变量
操作数栈
临时开辟一篇区域 做引用
动态链接
符号引用变成直接应用
本地方法区
为本地方法服务的本地方法栈
垃圾回收
垃圾确定
引用法
问题
循环引用
可达性分析
root
虚拟机栈中引用的对象
方法区中类静态属性引用的对象
方法区中常量引用的对象
本地方法栈中Native方法引用的对象
启动类加载器加载的类和创建的对象
回收算法
复制算法
配置
XX:MaxTenuringThreshold
进入老年代的回收次数
XX PretenureSizeThreshold
设置大对象的大小
缺点
一半内存可用
长期存活对象回一直被复制
标记清除
缺点
效率低
内存碎片多
标记整理法
分代收集法
引用类型
强引用
软引用
弱引用
虚引用
垃圾回收器
新生代
Serial
单线程复制
ParNew
多线程复制
配置
-XX:ParallelGCThreads
调整工作线程数
Parallel Scavenge
配置
-XX:MaxGCPauseMillis
最大停顿时间
-XX:GCTimeRatio
吞吐量大小
UseAdaptiveSizePolicy
自适应
关注
关注系统的吞吐量
老年代
CMS
多线程标记清除
关注
最短回收停顿时间
Serial Old
单线程标记整理
Parallel Old
多线程标注整理
整合
G1
多线程标记整理
关注
可预测的停顿
ZGC
只能在64位的linux上使用
选择合适的垃圾收集器
性能调优
CPU占用率高
工具
jstack
jstack PID
查看线程情况,发现没有死锁或者IO阻塞的情况
jmap
jmap -histo:live PID | more
获取到jvm.hprof文件,上传到指定的工具分析,比如heaphero.io
jmap -heap PID
查看堆的情况
生成堆转储快照
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof
内存溢出时,会自动dump出该文件
jps
查找java进程
与ps -ef | grep java 类似
jinfo
jinfo -flag [+|-] PID
查看JVM的参数配置
jstat
查看类装载信息
jstat -class PID 1000 10
查看某个java进程的类装载信息,每1000毫秒输出一次,共输出10次
查看垃圾收集信息
jstat -gc PID 1000 10
可视化
jconsole
jvisualvm
第三方
arthas
阿里
内存分析
MAT
获取dump
手动
jmap -dump:format=b,file=heap.hprof 44808
自动
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof
dump信息
编译器
C1和C2
AOT
Java9引入
而AOT是在程序运行之前,将字节码转换为
机器码
Graal VM
Java10引入
类加载机制
加载阶段
加载
加载Class文件
在方法区中创建Class对象
验证
验证Class文件
准备
类变量分配空间
设置类中初始值
final类型
准备节点
解析
符号引用变成直接引用
初始化
执行类构造器进行初始化
类加载器
启动类加载器
(Bootstrap Classloader)
加载
lib目录中的类库
扩展类加载器
( Extention Classloader)
( Extention Classloader)
加载
lib/ext目录中的类库
应用程序类加载器
(Application Class loader)
加载用户路径(classpath)上的类库
自定义加载器
(User Class loader)
通过继承 java. lang classLoader 实现向定义的类加载器
双亲委派模型
OSGI
并发
线程创建
原生方式
无返回值
继承Thread
实现Runnable接口
有返回值
实现Callable接口
异常
类型
Exception
RuntimeException 运行时异常)
NullPointer Exception
ClassCastException
ArraylndexOutOfBundsException
CheckException (检查异常)
ClassNotFoundException
SQLException
IO Exception
Error
启动失败
处理异常方式
抛出异常
throws
定义方法可能抛出的异常
throw
作用在方法内, 表示明确抛出一个异常
处理异常
try catch finally
MYSQL
执行计划
explain
id
select_type
primary
主查询
subquery
子查询
simple
简单查询
derived
衍生查询,使用到临时表
table
type
system
只有一条数据
const
仅仅能查到一条数据的SQL,用于主键和唯一键
eq_ref
唯一性索引
ref
非唯一性索引
range
范围查询
index
查询索引列
all
查询所有数据
三大范式
第一范式(1NF)
要求数据库的每一列都是不可分割的原子数据项,即原子性
第二范式(2NF)
表中的每一列都和主键相关,而不能至于主键的某一部分相关(主要针对联合主键而言),即每张表只描述一件事情
第三范式(3NF)
任何非主属性不依赖于其他非主属性(在2NF基础上,消除传递依赖)。即确保数据表中的每一列数据都和主键直接相关,而不能间接相关
索引
类型
普通索引
唯一索引
全文索引
主键索引
存储模型推演
数组
二分查找
缺点
修改需要挪动大量数据
优化
使用可以二分查找的链表(查找树)
可以二分查找的链表
二叉搜索数
缺点
查找耗时和数的深度有关
变成链表
最坏变成O(n)
优化
避免最坏情况
使用自平衡树
平衡二叉树
特点
左右旋自平衡
存储
左右子树指针
数据
缺点
访问一个节点需要一次IO
数据量多要多次IO
操作一页有16K
一个节点才几字节造成IO浪费
优化
减少树深度
B树
红黑树
节点为红色或者黑色
根节点必要黑色
叶子节点必须黑色
红色节点的子节点必须为黑色
任意节点到每一个叶子节点包含的黑色节点数目相同
B树(多路平衡查找树)
特点
有多个子节点
根据数据分裂与合并
缺点
索引无序
造成大量磁盘浪费,频繁分裂与合并
范围查询要IO的次数多
需要返回上层节点查找数据
一次IO能读到的节点少
B+树
特点
只有叶子节点存储数据
叶子节点用的是双向链表
有序
优点
每个节点存储更多数据,路数更多
扫遍能力强
遍历叶子节点的链表
磁盘读写能力强
根枝节点不保存数据,一次IO可以读取更多节点信息
排序能力强
叶子节点为链表
效率稳定
永远从叶子节点拿数据
千万级数据只要3次IO
一页16K可以读取1000路
哈希
innoDB不能显式创建hash索引
hash是自适应hash
innoDB自动为buffer pool仲的热点页创建索引
memory可以使用hash
存储文件
innoDB
.frm
表结构定义文件
.idb
数据和索引文件在一起
myisam
.frm
表结构定义文件
.myd
数据文件
.myi
索引文件
索引的区别(innoDB)
一级索引(聚集索引)
主键索引
叶子节点存储的是数据
查询数据快
避免了回表查询
没有主键索引
用唯一索引
没有唯一索引
内置6字节ROWID的值所为索引
二级索引
叶子节点存储的是主键的值
为什么不存地址
地址会变化
细分
单列索引
联合索引
最左匹配原则
从左到右查找
索引覆盖
只需从二级索引拿数据
查询的属性就是索引值
避免了回表查询
索引创建
经常用于where,order,join的值
索引个数不能太多
浪费空间,更新慢
过长字段建立前缀索引
区分度低(性别)不建立索引
扫面行数多
频繁更新的值不作为主键或索引
页分裂
无序的不作为索引
无序分裂
组合索引把散列高的放前面
索引失效
索引列使用了函数
字符串不加引号
like前面带%
用全文索引
负向查询
not like
!= not in
索引有序的话就可以
事务
事务的特性
原子性(Atomicity)
要么全成功要么全失败
实现
通过undo log实现
隔离性(Isolation)
多个事务之间的操作是透明的
持久性(Durabilit)
事务提交就是永久的
实现
redo log和 double write buffer(双写缓冲)
一致性(Consistent)
数据前后一致
手动开启事务
事务隔篱级别(SQL92标准)
Read Uncommitted(未提交读)
允许读取尚未提交的更改
可出现脏读、幻读或不可重复读
Read Committed(已提交读)
允许从已经提交的并发事务读取
可出现幻读和不可重复
Repeatable Read (可重复读)默认
对相同字段的多次读取的结果是一致的
幻读
Serializable(串行化)
串行化
事务i并发出些的问题
脏读
事务A读到了事务B未提交的数据,事务B又回滚了
不可重复读
事务A读取数据后事务B修改了值,事务A再读发现不一样了
幻读
事务A读取值的时候事务B新插入了一条,事务A再次读取发现多了一条数据
实现事务的两大方案
LBCC
MVCC
原则
能看到的数据版本
第一次查询之前已经提交的事务修改
本事务修改
不能看到的版本
本事务第一次查询之后创建的事务
活跃的(未提交的)事务的修改
原理
InnoDB事务都有编号且不断递增
每行字段有两个隐藏字段
DB_TRX ID(事务ID)
DB_ROLL_PTR(删除版本号)
指向undo log链的指针
旧版本数据的存储
undo log链
事务
结构
每个事务有一个视图
每个事务都有Read View(可见性试图)
Repeatable Read (可重复读)
Read View 是事务第一次查询的时候建立的
Read Committed(已提交读)
允许从已经提交的并发事务读取
Read View 是事务每次查询的时候建立的。
规则
可见性规则的流程
锁
锁分类
行级锁
Shared(共享锁)
手动加锁
select ……. lock in share mode;
Exclusive Locks(排他锁)
修改会自动加排他锁
表级锁
自增锁
用来防止自增字段重复
插入意向锁
锁允许多个事务同时插入数据到同一个范围
我们给数据加锁系统会自动加上意向锁
Intention Locks
Predicate Locks for Spatia Indexe()
原理
行锁
InnoDB 的行锁,就是通讨锁住索引来实现的
锁算法
Record Locks(记录锁)
等值查询查询到记录
Gap Locks(间隙锁)
查询记录不存在时用到
Next-KeyLocks(临键锁)
范围查询中包含存在的记录
隔离级别
Read Uncommited
不加锁
Serializable
Serializable 所有的select 语句都会被隐式的转化为 selec …in share mode,会
和 update、delete 互斥
和 update、delete 互斥
Read Commited
普通的 select 都是快照读,使用MVCC实现。
加锁的 select 都使用记录锁,因为没有 Gap Lock。
除了两种特殊情况——外键约束检查((foreign-key constraint checking)以及重复
键检查(duplicate-key checking)时会使用间隙锁封锁区间。
除了两种特殊情况——外键约束检查((foreign-key constraint checking)以及重复
键检查(duplicate-key checking)时会使用间隙锁封锁区间。
不使用间隙锁,所以会幻读
Repeatable Read
普通的 select
使用快照读(snapshot read),底层使用 MVCC来实现
加锁的 select(selec …in share mode /selec …for update)以及更新操作
update,delete 等语句使用当前读(current read),底层使用记录锁、或者间隙锁、
临键锁
update,delete 等语句使用当前读(current read),底层使用记录锁、或者间隙锁、
临键锁
死锁
死锁的条件
锁互斥
一次只能有一个事务持有锁
不可剥夺
其他事务要等持锁事务释放锁才能获得
形成等待环路
多个事务形成等待环路
查看锁信息
show status like 'innodb_row_lock_%'
select*from information_schema.INNODB_TRX;
当前运行的所有事务,还有具体的语句
select*from information_schema.INNODB_LOCKS;
当前出现的锁
select*from information schema.INNODBLOCK_WAITS;
锁等待的对应关系
打开锁监控
set GLOBAL innodb status output=ON:
set GLOBAL innodb_status output locks=ON;
sql优化
mysql查询流程
查看环境
select version();
查看版本
show variables like '%engine%;
查看环境
优化连接
使用连接池
阿里
Druid
默认最大连接大小8
springboot2.0默认
Hikari
Hikari的默认最大连接池大小是10
建议连接数
机器核数乘以2加1
避免频繁的上下文切换
缓存
集群,主从复制
分库分表
慢查询日志
show variables like 'slow query%'
参数的两种修改方式∶
set 动态修改参数(重启后失效)
修改配置文件my.cnf
分析工具
mysqldumpslow
MySQL的 bin目录下
命令
最慢的十条
显示运行线程
执行计划
sql优化用例
优化结构
分表分区
字段定义
使用最小类型
字符类型
固定长度用char
尽量使用非空
不用外键,触发器
字段冗余
io
多路复用io模型
select
poll
epoll
kqueue
NIO
Buffer(缓冲区)
重要属性
position∶
指定下一个将要被写入或者读取的元素索引,它的值由 get/put()方法自动更新
创建Buffer 对象时,position被初始化为0。
limit
从缓冲区写入通道时
指定还有多少数据需要取出
在从通道读入缓冲区时
多少空间可以放入数据(
capacity
存储在缓冲区中的最大数据容量
它指定了底层数组的大小
∶0<= position<=limit<=capacity
类型
Selector(选择器)
Channel()
集合
Collection
List
ArrayList
扩容因子
为什么线程不安全
初始容量值
Vector
线程安全
LinkedList
可以作为队列,堆栈使用
CopyOnWriteArrayList
实现原理
Set
HashSet
值不同(HashCode,equal)
TreeSet
有序
Comparable 接口
LinkedHashSet
有序
Queue
LinkedList
PriorityQueue
比较器
DelayQueue
Map
HashMap
1.7和1.8的区别
键一条为空
基础参数
capacity
当前数组容量
loadFactor
负载因子,默认为0.75
为什么加载因子是0.75
threshold
扩容的阈值
常用方法
put
resize()扩容
高位运算判断是否需要移动
高一位为 0
不移动
高一位为 1
新的下标位置等于原下标位置 + 原数组长度
ConcurrentHashMap
1.7
Segment组成
1.8
CAS
HashTable
TreeMap
默认升序
有序
LinkHashMap
基础的知识
String
方法
equals()
可以接收一个 Object 类型的参数
返回值为 Boolean
compareTo()
只能接收一个 String 类型的参数
compareTo() 的返回值则为 int
indexOf()
查询字符串首次出现的下标位置
KMP算法
trim()
去掉字符串首尾空格
实现
final修饰
安全高效
创建方式
new()
先创建一个字符串对象,查看常量值有没有,没有就在常量池创建
直接赋值
常量池有就直接从常量池引用,没有就在常量值创建
JDK8把字符串常量池从方法区移到了 Java 堆上
深拷贝与浅拷贝
浅拷贝
复制对象的时候只复制地址
深拷贝
重新复制一个新对象
实现方式
实现克隆方法
构造方法实现深克隆
JDK字节流实现
Apache Commons Lang
SerializationUtils.clone(p1)
JSON工具
Gson
FastJSON
反射
API
Class类
获取类的属性,方法
Field类
设置获取类中的属性值
Method类
获取方法的描述信息或者执行某个方法
Constructor类
类的构造方法
步骤
获取Class对象
子主题
MQ
MQ的作用
解耦
异步
削峰
高可用性
RabbitMQ
镜像集群模式
配置开启
缺点
无法线性拓展
Kafka
组成
broker
partition
topic
partition
partition
HA 机制
重复消费
有哪里场景会重复消费
Kafka
业务处理完offset未提交成功
保证幂等性
先查询在更新
Redis的set
传一个唯一id
数据库主键插入
消息丢失
RabbitMQ
丢失的情况
解决
生产者丢了数据
confirm 机制
异步
生产者配置开启
事务机制
同步
吞吐量下降
RabbitMQ 弄丢了数据
开启 RabbitMQ 的持久化
设置持久化
创建 queue 设置为持久化
deliveryMode 设置为 2
消费端丢数据
关闭RabbitMQ 的自动 ack
Kafka
解决
消费端丢了数据
关闭自动提交 offset
Kafka丢失数据
给 topic 设置 replication.factor 参数
每个 partition 必须有至少 2 个副本
Kafka 服务端设置 min.insync.replicas
一个 leader 至少感知到有至少一个 follower 还跟自己保持联系
在 producer 端设置 acks=all
写入所有 replica才成功
在 producer 端设置 retries=MAX
要求一旦写入失败,就无限重试
消息顺序性
RabbitMQ
Kafka
消息挤压
消息未满
加快消费速度
紧急扩容
RocketMQ
提高并行度
增加 Consumer 实例数量来提高并行度
配置
修改参数 consumeThreadMin、consumeThreadMax
批量方式消费
配置
consumeMessageBatchMaxSize
跳过非重要消息
如果消息不重要,跳过消息不消费
优化每条消息消费过程
优化消息执行时间
满了丢了
批量重导
把数据查询回来
防止丢失
消息不要设置过期时间
提前预防
判断消息数量,设置预警
设计一个MQ
数据迁移
双写方案
分布式系统
主键生成策略
UUID直接生成
优点
效率高
不用网络请求
不会重复
子主题
没法排序
存储占用空间大,建立索引不友好
没有规律
改进
Comb 算法
批量号段式数据库
每个数据库申请一批id号
Redis自增
incr原子自增
优点
基于内存,速度快
天然排序,自增,有利于排序搜索
缺点
需要关注持久化,可用性等,增加系统复杂度
美团Leaf服务
snowflake(雪花算法)
8字节64位
1位:不使用,二进制中最高位是为1都是负数,但是要生成的唯一ID都是正整数,所以这个1位固定为0
41位:记录时间戳(毫秒)
10位:记录工作机器的ID,可以机器ID,也可以机房ID + 机器ID
12位:序列号,就是某个机房某台机器上这一毫秒内同时生成的 id 序号
特点
强依赖于时间
时间回拨可能会重复
解决
判断是否小于上次时间戳
回拨之后在拓展位上加1
百度 uid-generator
基于雪花算法
分布式锁
数据库级别锁
redis原子操作锁
Zookeeper锁
Redisson
多线程
线程锁
锁类型
独占锁和共享锁
可重入锁
乐观锁
悲观锁
锁应用
synchronized
特点
独占式悲观锁
JVM实现
应用
单例模式
volatile
禁止指令重排
原理
JVM隐式实现
修饰代码块
monitorenter
monitorexit
修饰方法
ACC_SYNCHRONIZED
1.6后升级原理
使用方式
修饰实例方法
修饰静态方法
修饰代码块
ReentrantLock
特点
可实现公平非公平
只能修饰代码块
手动加解锁
基础AQS实现
方式
lock()
获取锁
acquire()排队
unlock()
解锁
死锁
死锁的必要条件
互斥条件
请求和保持条件
不剥夺条件
循环等待
线程状态
线程的状态
NEW
新建
RUNNABLE
就绪
BLOCKED
阻塞等待锁的线程状态
WAITING
等待状态
TIMED_WAITING
计时等待状态
TERMINATED
终止状态
线程方法
线程优先级
Thread.setPriority()
让出执行权
让子线程执行
other.join()
愿意让出使用权
yield()
start()
synchronized修饰保证安全
Thread 自身的方法
run()
Runnable 的抽象方法
join()
主线程调用,会让出执行权给子线程
线程优先级
优先级级别
10最大,1最小
默认为5
创建线程的方法会默认继承创建它的线程的优先级
优先级越大,抢占 CPU 时间片的概率越高
不一定大的就能抢到
线程池
ThreadPoolExecutor
参数
corePoolSize
核心线程数
maximumPoolSize
最大可以创建的线程数
keepAliveTime
存活时间
unit
存活时间单位
workQueue
线程池执行的任务队列
threadFactory
线程创建工厂
RejectedExecutionHandler
拒绝策略
AbortPolicy(默认)
终止策略
线程池会抛出异常并终止执行
CallerRunsPolicy
把任务交给当前线程来执行
DiscardPolicy
忽略此任务(最新的任务)
DiscardOldestPolicy
忽略最早的任务(最先加入队列的任务)
自定义策略
方法
execute
new Runnable(){}
submit
new Callable<String>()
执行流程图
内存屏障
volatile
作用
防止重排序
强制把写缓冲区/高速缓存中的脏数据等写回主内存,让缓存中相应的数据失效
语义中的内存屏障
内存屏障
Load Barrier
读屏障
在指令前插入Load Barrier,可以让高速缓存中的数据失效,强制从新从主内存加载数据
Store Barrier
写屏障
在指令后插入Store Barrier,能让写入缓存中的最新数据更新写入主内存,让其他线程可见
AQS
三大部分
状态(state)
应用
CountDownLatch
需要倒数的数量
ReentrantLock
锁的占有情况
0没锁
大于0 被其他线程持有
2,3,4表示重入次数
方法
compareAndSetState
CAS设置值
setState
直接赋值
使用volatile 内存屏障
线程队列
排队管理器
线程获取方法
应用
ReentrantLock
lock
Semaphore
acquire
CountDownLatch
await
线程释放方法
应用
Semaphore
release
去释放一个许可证,会让 state 加 1
CountDownLatch
countDown
作用是倒数一个数,让 state 减 1
继承要实现的方法
tryAcquire
tryRelease
tryAcquireShared
tryReleaseShared
Redis
数据结构
String
通过redisObject存储
value值指向SDS动态字符串
有三种编码
int
embstr
raw
Simple Dynamic String 简单动态字符串。
操作命令
Hash
内层
ziplist
hashtable
操作命令
List
quicklist
ziplist 和 linkedlist 的结合体
操作命令
Set
操作命令
组成
整形
intset
元素个数超过512个,也会用 hashtable 存储
非整形
hashtable
SortedSet
操作命令
组成
元素数量小于128
ziplist
元素数量大于128或任意menber长度大于64
skiplist(跳表)+dict存储
进阶
HyperLogLog
Geo
Pub/Sub
Redis Module
BloomFilter
Redis Search
Redis-ML
BitMap
Bitmaps是在字符串类型上面定义的位操作。一个字节由8个二进制位组成。
分布式锁
锁代码
2.6版本以上
2.6之前
过期策略
惰性删除
访问该值才判断是否过期
定期删除
每隔一段时间检查是否有过期
默认10次每秒
配置
redis.conf
hz
定期删除算法
随机抽取20
比例过25%
定时删除
设置过期时间
定时器定时删除
最大执行时间
25ms
内存淘汰策略
命令
查看
config get maxmemory-policy
设置
config set maxmemory-policy noeviction
重启失效
配置
redis.conf
maxmemory-policy noeviction
重启生效
6种策略
noeviction(默认)
淘汰算法
LRU
最久未使用
LFU
生产问题
缓存雪崩
原因
key同一时间同时过期
小问题
Redis卡顿
普i他解决
给Redis时间设置随机过期值
其他解决
加互斥锁或者使用队列,针对同一个key 只允许一个线程到数据库查询
缓存定时预先更新避免同时失效
缓存永不过期
缓存穿透
布隆过滤器
Guava 的实现
变种
布谷鸟过滤器
redisson分布式
缓存击穿
解决
缓存空数据
缓存特殊字符串,比如&&
面试题
大数据是否存在
哈希函数
MD5
SHA-1
缓存一致性
先更新数据库后更新缓存
重试的机制
删除缓存失败,捕获这个异常,把需要删除的key发送到消息队列。
让后自己创建一个消费者消费,尝试再次删除这个 key
让后自己创建一个消费者消费,尝试再次删除这个 key
异步更新缓存
监听binlog日志
先更新缓存再更新数据库
延时双删
写入数据之后,再删除一次缓存
Java工具
Redisson
RedisTemplate
Jedis
高可用
数据持久化
RDB
AOF
AOF日志
写后日志
不用检验命令
不会阻塞当前的写操作
写回策略
重写机制
解决
性能问题
系统无法保存过大文件
文件大追加命令效率慢
宕机后恢复慢
实现原理
多变一
避免阻塞线程
一拷贝两日志
bgrewriteaof线程实现
RDB + AOF(redis默认)
命令
查询是否开启
config get aof-use-rdb-preamble
主从同步
主从模式
优点
缺点
从从模式
哨兵模式
存储
src/redis-sentinel
启用命令
./src/redis-sentinel sentinel.conf
工作原理
集群模式(3.0版本)
槽位
crc16算法
使用场景
string
单值缓存
SET key value,GET key
对象缓存
SET user:1 value(json字符串);<br>存:MSET user:1:name zhangsan user:1:age 10<br>取:MGET user:1:name user:1:age<br>比json格式好,方便单属性操作,性能更好一点,最优选择HASH
分布式锁
SETNX product:10001 true // 发返回1表示加锁成功,有弊端不要使用 SETNX product:10001 true // 发返回0表示加锁失败 DEL product:10001 // 释放锁 SET product:10001 true ex 10 nx // 防止程序意外终止导致死锁
计数器
阅读量统计在Redis中的使用:<br>INCR article:readcount:{文章Id} 文章的阅读量统计<br>GET article:readcount:{文章Id}
分布式系统唯一id生成
INCRBY orderId 1000 redis生成序列号,提升性能。
list
Stack(栈)=LPUSH+LPOP-&gt;FILO 先进后出 Queue(队列)= LPUSH+RPOP-&gt;FIFO 先进先出 Blocking MQ(堵塞队列)= LPUSH+BRPOP
set
无序去重
集合操作
随机事件
sortset
维护顺序
集合操作
排序实现
hash
对象存储
HSET user:10001 name zhangsan age 10 // 设置对象属性<br>HGET user:10001 name age // 获取属性信息
电商购物车
以用户ID为key 商品ID为field 商品数量为value
q'we'q'we
bitmap
通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身。我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省储存空间。
setbit,getbit,bitcount
setbit等命令只不过是在set上的扩展
指令 SETBIT key offset value
设置或者清空key的value(字符串)在offset处的bit值(只能只0或者1)。
空间占用、以及第一次分配空间需要的时间
大概的空间占用计算公式是:($offset/8/1024/1024)MB
在一台2010MacBook Pro上,offset为2^32-1(分配512MB)需要~300ms,offset为2^30-1(分配128MB)需要~80ms,offset为2^28-1(分配32MB)需要~30ms,offset为2^26-1(分配8MB)需要8ms。
使用场景
用户签到
根据日期 offset =hash % 365 ; key = 年份#用户id
统计活跃用户
使用时间作为cacheKey,然后用户ID为offset,如果当日活跃过就设置为1<br>那么我该如果计算某几天/月/年的活跃用户呢(暂且约定,统计时间内只有有一天在线就称为活跃),有请下一个redis的命令<br>命令 BITOP operation destkey key [key ...]<br>说明:对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。<br>说明:BITOP 命令支持 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种参数<br><br>20190216 活跃用户 【1,2】<br>20190217 活跃用户 【1】<br>统计20190216~20190217 总活跃用户数: 1
用户在线状态
使用bitmap是一个节约空间效率又高的一种方法,只需要一个key,然后用户ID为offset,如果在线就设置为1, 不在线就设置为0,和上面的场景一样,5000W用户只需要6MB的空间。
布隆过滤器BloomFilter
简介:
布隆过滤器实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。
原理
当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。
优点
相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入/查询时间都是常数(O(k))。而且它不存储元素本身,在某些对保密要求非常严格的场合有优势。
缺点
一定的误识别率和删除困难。 结合以上几点及去重需求(容忍误判,会误判在,在则丢,无妨),决定使用BlomFilter。
思想
实现
geo
redis提供地理位置相关的操作
Spring
bean的注册方式
XML 配置
注解
API
常见问题
同名bean问题
不同Spring配置文件
后面的覆盖前面的
同一个Spring配置文件
后面的覆盖前面的
bean生命周期
spring循环依赖
三级缓存
三个Map
bean的作用域
singleton(默认)
prototype
request
session
application
IoC
名词
控制反转
依赖注入(DI)
容器
设计模式
好莱坞法则
注入方式
构造方法注入
Setter 注入
接口注入
注解注入
AOP
注释
代码实例
动态代理
JDK 动态代理
实现 InvocationHandler 接口
CGLIB
ASM字节码操作框架
当 Bean 实现了接口时,Spring 就会使用 JDK Proxy,在没有实现接口时就会使用 CGLib
核心知识
组成
切面(aspect)
横切关注点
连接点(joinpoint)
切入点(pointcut)
通知(advice)
目标对象
织入(weave)
引入(introduction)
springboot启动原理
设计模式
工厂模式
spring中的BeanFactory就是简单工厂模式的体现,根据传入唯一的标识来获得bean对象
单例模式
提供了全局的访问点BeanFactory
代理模式
AOP功能的原理就使用代理模式(1、JDK动态代理。2、CGLib字节码生成技术代理。
装饰器模式
依赖注入就需要使用BeanWrapper
观察者模式
spring中Observer模式常用的地方是listener的实现。如ApplicationListener
策略模式
Bean的实例化的时候决定采用何种方式初始化bean实例(反射或者CGLIB动态字节码生成)
门面模式
日志框架,JDCB中各种数据库的选择
事务传播机制
事务特性
原子性
一致性
隔离性
持久性
传播机制
PROPAGATION_REQUIRED
外层有就用外层没有就新建
PROPAGATION_REQUES_NEW
每次都开新事务
B异常
B处理异常
A不回滚
B不处理异常
A回滚
A异常
不会滚B
PROPAGATION_SUPPORT
外层有就用没有就非事务
PROPAGATION_NOT_SUPPORT
有没有事务都不回滚该层代码
PROPAGATION_NEVER
外层有事务就抛出异常
PROPAGATION_MANDATORY
外层没事务就抛出异常
PROPAGATION_NESTED
A异常
AB都回滚
B异常
B处理异常
A不回滚
B不处理异常
A回滚
事务失效
发生自调用
方法不是public的
数据库不支持事务
没有被Spring容器管理
异常没有抛出
事务隔篱级别
ISOLATION_DEFAULT
使用数据库默认隔篱级别
ISOLATION_READ_UNCOMMITTED
允许读取尚未提交的更改
可出现脏读、幻读或不可重复读
ISOLATION_READ_COMMITTED(Oracle默认)
允许从已经提交的并发事务读取
可出现幻读和不可重复
ISOLATION_REPEATABLE_READ(mysql默认)
对相同字段的多次读取的结果是一致的
幻读
mysql系统有mvcc不会幻读
ISOLATION_SERIALIZABLE
串行化
只读事务
@Transactional(readOnly=true)
事务的超时性
@Transactional(timeout=30)
回滚
指定单一异常类
@Transactional(rollbackFor=RuntimeException.class)
指定多个异常类
@Transactional(rollbackFor={RuntimeException.class, Exception.class})
mybatis
0 条评论
下一页