目录
Mybatis
-
SqlSessionFatoryBuilder
-
SqlSessionFatory
-
SqlSession
-
\1. 通过SqlSessionFatoryBuilder构建SqlSessionFatory的时候会处理指定的xml文件,创建MapperProxy
-
\2. 执行的时候获取到一个SqlSession,拿到一个Executor来执行MapperProxy。
-
\3. MapperProxy的invoke方法中来执行sql。
Spring
-
Hystrix:
-
一定时间内(10s) 请求达到一定次数(20次) 失败率达到50%。
-
断路器关闭、全开、半开。
-
-
容器初始化流程-refresh流程
-
获取工厂对象,包括通过xml中加载BD
-
prepareBeanFactory:设备一些忽略策略、ClassLoad等
-
PostProcessBeanFactory:一个钩子,这时所有xml加载的BD完成,Bean还没初始化。
-
InvokePostProcessBeanFactory: 初始化并执行BeanFactory的后置处理,@Configuration是在这里执行的,
-
registerBeanPostProcessors:实例化Bean后置处理
-
…
-
onRefresh:钩子,SpringBoot的tomcat是在这里启动的。
-
finishBeanFactoryInitialization:
-
实例化Bean
-
依赖注入
-
AOP等
-
-
-
三级环境
-
singletonFactories
-
earlySingletonObjects
-
SingletonObjects
-
-
依赖注入方法:populateBean->postProcessProperties
锁AQS CAS
-
AQS
-
head、tail、thread、status
-
Node:pre、next、Thread、stat(Signal、propagete)
-
-
显式锁
-
非公平锁,尝试加锁->tryAcquire中尝试->入队->唤醒
-
公平,tryAcquire如果是首节点尝试->入队->唤醒
-
JVM
-
CMS
-
初始标记,并发标记,重新标记,并发清除,重置
-
三色标记
-
-
G1
-
初始标记,并发标记,最终标记,根据指定时间筛选回收。
-
-
内存划分
-
堆区。
-
栈区:虚拟机栈(一个线程一个栈,一个方法一个帧)、程序计数器(程序执行位置)、本地方法栈(原生方法)。
-
本地内存:元空间、直接内存。
-
Mysql
-
优化记录
-
# 采用前缀索引过短,导致离散率不高。
-
SELECT * FROM imuser_validate WHERE access_token =''
-
# 未添加索引
-
update third_push_token set validity=0 where third_token='' and origin=
-
# 联合索引末端字段,大概率不会走索引
-
SELECT userId FROM imgatewaysubdev WHERE subUserId = '4440433'
-
# 字段类型不一样,int string等。 会导致不走所以
-
delete from iosusertoken where userId=6173390
-
# join过多,导致笛卡尔积太大
-
-
ACID
-
读未提交(Read uncommitted),
-
可能出现脏读。
-
就是一个事务能够看到其他事务尚未提交的修改,这是最低的隔离水平,允许脏读出现。
-
-
读已提交(Read committed)
-
可能不可重复读和幻象读(Phantom Read)出现。
-
事务能够看到的数据都是其他事务已经提交的修改,也就是保证不会看到任何中间性状态,当然脏读也不会出现。读已提交仍然是比较低级别的隔离,并不保证再次读取时能够获取同样的数据,也就是允许其他事务并发修改数据。
-
-
可重复读(Repeatable reads)
-
可能出现幻读。
-
保证同一个事务中多次读取的数据是一致的,这是 MySQL InnoDB 引擎的默认隔离级别,但是和一些其他数据库实现不同的是,可以简单认为 MySQL 在可重复读级别不会出现幻象读。
-
-
串行化(Serializable)
-
并发事务之间是串行化的,通常意味着读取需要获取共享读锁,更新需要获取排他写锁,如果 SQL 使用 WHERE 语句,还会获取区间锁(MySQL 以 GAP 锁形式实现,可重复读级别中默认也会使用),这是最高的隔离级别。
-
-
-
B+数的演变
-
1 二分查找
-
2 二叉树:二分查找如果放到数组中查找方便,但是插入十分困难。链表没有下标也不行。 所以引入了二叉树
-
3 平衡二叉树:二叉树虽好,但是容易产生数据倾斜问题,如,只有左链,或者只有右链。
-
4 B树:平衡二叉树虽好,但是如果数据量太大,树会特别高,影响查询效率。
-
5 B+树:B树虽好,但是查询效率不稳定:查询靠近顶级的节点最快,叶子节点最慢。
-
查询效率稳定
-
磁盘IO次数少
-
范围查询效率高
-
-
-
成本计算 IO成本, CPU成本
-
找出所有可使用的索引。
-
计算出全表扫描的成本。
-
计算出所有可使用的索引的的成本。
-
对比各个方案,找出成本最优的。
-
Zookeeper
-
四种节点:持久临时&是否有序
-
leader负责读和写,follow和Observer只负责读。
-
写的时候需要发起投票,过半数才能写入。所以Follow不能太多
-
-
ZAB协议分为两种 崩溃恢复和消息广播
-
选主流程
-
先比较zxid,然后比较myid,
-
首次启动只能挨个比较myid
-
运行期间都投票给自己,然后交换信息选出最大,不行就再来一轮。
-
-
-
脑裂
-
通过法定人数法 n/2+1
-
Rabbit
-
channel.size: 提高此参数防止大量的channel不断的打开与关闭。
-
prefetch:提高预取值来减少NetIO
-
concurrency:提高允许同时连接rabbit的客户端数量。
-
rabbit单个queue可以支撑几k的tps,使用多个queue可以将单台tps提升到2w+
-
如果两万无法满足需求可以使用并列多个rabbit
RocketMQ
-
Nameser,producer,consumer,broker的关系
-
namesrv:broker需要注册到所有namesrv,consumer和producer连接到一台namesrv来获取broker信息。
-
producer:连接所有master节点。
-
consumer:连接所有master和slave,高可用切换使用。
-
-
消息存储:
-
CommitLog:一个broker有一个commitLog,存储所有的消息
-
ComsumeQueue:每个topic有多个queue,queue中存储消息的指针信息,真实消息在CommitLog中。
-
IndexFile:通过messageKey查消息的索引
-
-
高可用部署
-
多组Master+Slave,同步复制异步刷盘。
-
-
零拷贝
-
磁盘->copy到内核缓存区->copy到应用程序缓存区->copy到网络缓存区->网络传输
-
磁盘->copy到内核缓存区(内存映射可以给应用程序直接读)->copy到网络缓存区->网络传输
-
-
特殊功能
-
事务
-
延时消息
-
广播
-
等
-
Redis
-
RESP协议
-
数据类型String,Set,List,Map,ZSet
-
一个字符串类型可以存储的最大 512M
-
RDB AOF
-
Redis过期策略
-
定时,
-
LRU
-
random
-
-
Redis 集群方案什么情况下会导致整个集群不可用?
-
有 A,B,C 三个节点的集群,在没有复制模型的情况下,如果节点 B 失败了,那么整个集群就会以为缺少 5501-11000 这个范围的槽而不可用。
-
-
说说 Redis 哈希槽的概念?
-
Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 个哈希槽,每个 key 通 过 CRC16 校验后对 16384 取模来决定放置哪个槽,集群的每个节点负责一部分 hash 槽。
-
-
弱事务
-
redis性能问题
-
master不要持久化
-
主从尽量选择线性的。
-
-
Redis集群方案
-
哨兵,
-
监控各个节点的stat,消息通知,故障转移,配置中心。
-
哨兵集群至少需要3个实例,高可用,但不能保证不丢数据。
-
-
集群
-
哨兵模式监控权交给了哨兵系统,集群模式中是工作节点自己做监控
-
哨兵模式发起选举是选举一个leader哨兵节点来处理故障转移,集群模式是在从节点中选举一个新的主节点,来处理故障的转移
-
-
分布式锁
-
redis Hash{ lockname:{ uuid: 1 }}
-
zk 通过临时顺序节点,后一个节点watch前一个节点来实现
微服务调优经验
场景接口 200qps > 1200qps
-
mysql 连接池 改大
-
hystrix 改大
-
tomcat 500
-
打通所以keepalive
-
fegin连接池
-
JVM
-
jackson
-
logback
生产OOM
-
Jprofile & visualvm & gceasy
类加载和双亲委派
-
加载: 从本地或者流中加载数据
-
验证: 验证数据的正确性
-
准备:给基本数据类型赋值等
-
解析:将常量池引用改为真实值等。
-
初始化:执行用户代码,例如static代码块
-
使用:new出来实例
-
卸载:jvm中卸载类
排序
java自带的排序:
-
小于286是双轴快排
-
小于47:插入
-
否则:双轴快排
-
-
大于286
-
连续升降性 好:归并排序
-
不好:快排
-
冒泡:每次找到最大的元素放到最右边。
归并:和java的fork很像
快排:首先用最左端的数字将数组拆分为两部分,左边的小,右边的大。然后左右一次递归这样做。
双轴快排:和快排类似,只是第一次是使用首尾两个数字将数组拆分为三段。
插入排序:自然人最接近的排序方式,我们整理扑克牌经常使用。
TCP握手
三次握手
-
a发起连接确认信息
-
b确认,
-
b发起连接确认信息
-
a确认连接信息
四次挥手同样的。
timewait 是因为不能确定最后一次close的ack能被对方收到,另外房子这个连接通道被立马重用。