编程技术框架
2021-07-18 17:57:33 56 举报
AI智能生成
个人编程框架
作者其他创作
大纲/内容
索引的创建原则
DDL
三星原则
只查询需要的字段、注意大字段的查询
注意命中索引,减少回表
语句编写
问题原因
减少回表(先定位主键值,再根据主键值定位行记录)查询列少,建立联合索引(覆盖索引)
查询列多,先查询主键列,再根据查询结果join查询其他列
如果数据根据id自增 可以算出id设置where 条件,再limit
优化方案
order by 偏移量大
分片 query
限流
结果归并 再 order by limit
分布式数据库 order by limit
sql优化思路
可重复读是在事务开始的时候生成一个当前事务全局性的快照,而读已提交则是每次执行语句的时候都重新生成一次快照
原理
没有加锁、没有隔离
脏读
在同一事务中,同样的条件,第一次读的数据和第二次读的「数据不一样」
不可重复读
在同一事务中,同样的条件,第一次和第二次读出来的「记录数不一样」
幻读
读未提交
每次执行语句的时候都重新生成一次快照
读已提交
在事务开始的时候生成一个当前事务全局性的快照,
行锁和间隙锁合并在一起,解决了并发写和幻读的问题
部分防止幻读
可重复读(mysqlinnoDB采用)
读的时候加共享锁,也就是其他事务可以并发读,但是不能写。
写的时候加排它锁,其他事务不能并发写也不能并发读。
串行读
隔离级别,解决什么问题?
非叶子节点上是不存储数据的,仅存储键值,而 B 树节点中不仅存储键值,也会存储数据
B和B+树主要用在文件系统以及数据库做索引
索引,B+树的特点
为了实现事务的隔离性,通过版本号,避免同一数据在不同事务间的竞争
MVCC只在READCOMMITTED和REPEATABLEREAD两个隔离级别下工作。其他两个隔离级别够和MVCC不兼容
InnoDB在每行数据都增加三个隐藏字段,一个唯一行号,一个记录创建的版本号,一个记录回滚的版本号。
快照读是通过MVVC(多版本控制)和undolog来实现的,当前读是通过加recordlock(记录锁)和gaplock(间隙锁)来实现
实现机制
MVVC
bin log 、 undo log
Mysql 存储引擎-innoDb
FE 的磁盘空间主要用于存储元数据
FE 分为 Leader,Follower 和 Observer 三种角色
FE
BE 的磁盘空间主要用于存放用户数据
coordinator节点 汇总处理结果 返回 FE
BE
一台机器上可以部署多个 BE 实例,但是只能部署一个 FE
从第三方存储系统导入数据,需要部署相应的 Broker
BROKER
架构与部署
只会存储聚合后的数据。即明细数据会丢失
AGGREGATE KEY
UNIQUE KEY 相同时,新记录覆盖旧记录
适用于有更新需求的分析业务
UNIQUE KEY
只指定排序列,相同的行不会合并。适用于数据无需提前聚合的分析业务。
DUPLICATE KEY
数据模型
Schema Change
Analyze负责对AST进行前期的一些处理
SinglePlan根据AST进行优化生成单机查询计划
DistributedPlan将单机的查询计划拆成分布式的查询计划
Schedule阶段负责决定查询计划下发到哪些机器上执行
查询流程
查询列与索引列顺序一致
建立rollup 表 命中索引
rollup 与 前缀索引
doris
数据库-Mysql 存储引擎-innoDb
任意多次执行所产生的影响均与一次执行的影响相同
查询、删除 是天然的幂等操作
新增 : 唯一索引,避免重复新增
token 防止重复提交
分布式锁 防止并发操作
状态机管理
数据库记录版本管理,update 限制版本号利用数据库的 事务隔离级别控制
幂等性处理
两个字段必须传,一个是来源source,一个是来源方序列号seq,这个两个字段在提供方系统里面做联合唯一索引,这样当第三方调用时,先在本方系统里面查询一下,是否已经处理过,返回相应处理结果;没有处理过,进行相应处理
对外提供接口的api如何保证幂等
先更新数据库,再删除缓存
高并发下的缓存一致性
主从架构->读写分离->水平扩容支撑高并发
优化hash规则,使请求分布均匀
优化热点key 的value大小,转移redis压力
多级缓存
热点key的单机瓶颈,缓存击穿
经典问题以及解决方案
管理固定对象,避免频繁建立、销毁,提高使用效率
双重检查,volitail 修饰固定对象,synchronized 代码块获取 对象
枚举方式(简单、安全),防止反射、反序列化
单例模式笔记
单例模式
实现相同接口,代理类在方法前后增加原类方法
静态代理
只能代理接口
代理类 需要实现 InvocationHandler 接口, 重写 invoke 方法
通过Proxy.newProxyInstance 生成代理类的实例,最终调用 invoke方法
jdk动态代理
字节码技术,动态生成 目标类的子类
不能代理 被 final 关键字修饰的类
实现 MethodInterceptor , 重写 intercept() 方法
通过 Enhancer 生成代理类的实例
cglib代理
动态代理
代理类增强原类的方法
代理模式
工厂模式
装饰模式
设计模式
链表的倒数第k个节点
数据结构、算法
实现 Comparable 接口
排序
iterator
遍历删除元素
list
put方法源码
key 的选择,最好是不可变对象,因为put的时候会对key 进行 hash
entrySet
遍历hashmap
HashMap
重写HashMap的Node,增加了after和before字段,遍历 entrySet 时 通过 双向链表来维护有序性
5个构造方法,其中有4个的构造方法都是指定了accessOrder为falseaccessOrder为false表示根据插入的顺序进行排序,当为true的时候表示根据获取排序
图解LinkedHashMap原理
为什么有序?
LinkedHashMap是如何实现有序的
LinkedHashMap
锁住头节点
减小锁粒度 + CAS
volatile变量
ConcurrentHashMap
map
List<?>:是一个泛型,在没有赋值前,表示可以接受任何类型的集合赋值,但赋值之后不能往里面随便添加元素,但可以remove和clear
List<Object> 可以接受任何类型的对象
泛型不可变,无继承关系
list<?> 与 list<Object> 区别
<T> T : 表示返回值类型不一定
T method(List<T> list) : 表示返回类型和传入类型一致
泛型
强引用 GC 不会回收 , 弱引用会被回收
强应用、弱引用的区别
ThreadLocal的内存泄露?什么原因?如何避免?
ThreadLocal
Java基础
AQS、CAS
无锁状态偏向锁状态轻量级锁状态重量级锁状态
锁降级发生在Stop The World期间,当JVM进入安全点的时候,会检查是否有闲置的锁,然后进行降级
锁降级
当对象状态为偏向锁时,Mark Word存储的是偏向的线程ID
轻量级锁时,Mark Word存储的是指向线程栈中Lock Record的指针
重量级锁时,Mark Word为指向堆中的monitor对象的指针。
锁升级
Java 6 以前,所有的锁都是”重量级“锁Java 6 及其以后,一个对象其实有四种锁状态,它们级别由低到高
Mark Word 占一个字节 存储对象的hashCode或锁信息
Class Metadata Address 占一个字节 存储到对象类型数据的指针
Array length 占一个字节 数组的长度(如果是数组)
一个对象的“锁”的信息是存放在 Java对象头非数组对象 的对象头占 两个字节数组对象 占3个字节
ReentrantLock 可以立即中断
不一定立即响应中断
等待可中断
ReentrantLock 可以实现公平锁
公平锁
ReentrantLock 是 API层面的锁 , 底层使用 CAS + 自旋
synchronized 是 JVM层面的 , 通过指令控制
锁的层面
await、signal
wait、notify
synchronize
使用多个条件
synchronize VS ReentrantLock
synchronized
可重入锁和非可重入锁
公平锁与非公平锁
读写锁和排它锁
”可重入“锁
支持”公平锁“和”非公平锁“。
排他锁
ReentrantLock
还支持”读写锁“
ReentrantReadWriteLock
读线程非常多而写线程非常少的场景下非常适用
StampedLock
锁接口和类
阻塞队列的原理
队列选择
丢弃策略
线程池
同步容器
线程安全的原理
常见参数
JMM : java memory model
JVM
线程安全的类
new
runnable
blocked
waiting
time-waited
terminated
线程的几种状态
线程基础
并发
反射
1、沙箱安全机制:自己写的java.lang.String.class类不会被加载,这样便可以防止核心API库被随意篡改
双亲委派
类加载
等待数据准备 (Waiting for the data to be ready)
将数据从内核拷贝到进程中
两个阶段
阻塞IO(BIO)
非阻塞IO 、 第一个阶段不是阻塞的,需要不断的主动问kernel数据好了没;第二阶段依然总体是阻塞的。
IO多路复用(NIO): 单个process就可以同时处理多个网络连接的IO
程序发起read操作之后,立刻就可以开始去做其它的事
kernel会等待数据准备完成,然后将数据拷贝到用户内存
一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了
异步IO(AIO)
四种常用模型
IO
Java进阶
链表加多级索引的结构,就是跳跃表
跳表
设计思路,架构图
redis高可用:如果做主从架构部署,加上哨兵就可以了,任何一个实例宕机,自动会进行主备切换。
用户和redis-proxy建立连接,redis-proxy会识别出客户端连接发送过来的请求是读还是写,然后按照权重作负载均衡,将请求转发到后端不同的DB节点中,写请求转发给master,读操作转发给read-only replica(master默认也提供读,可以通过权重控制)。
Redis读写分离技术解析
读写分离
主从 + 哨兵
服务端分片, redis Cluster - 采用16384个槽位进行路由规则的转发 - 在线数据迁移、节点扩容缩容
高可用
RDB
AOF
持久化策略
一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤
输入值的合法性校验
查询结果为空的情况也进行缓存,缓存时间设置短一点
缓存穿透
- redis高可用, 集群
- 限流 、 降级
- 缓存预热,打散过期时间
- 多级缓存 、 应用内缓存
缓存雪崩
面试题:如何保证redis的高并发及高可用?
缓存 redis
rocket mq
kafka
怎么避免消息丢失? 服务宕机会发生什么
一个很简单的 Topic 路由注册中心,支持 Broker 的动态注册和发现,保存 Topic 和 Borker 之间的关系。通常也是集群部署,但是各 NameServer 之间不会互相通信, 各 NameServer 都有完整的路由信息,即无状态。
NameServer
主要负责消息的存储、查询消费,支持主从部署,一个 Master 可以对应多个 Slave,Master 支持读写,Slave 只支持读。Broker 会向集群中的每一台 NameServer 注册自己的路由信息;
Broker
消息生产者,可以集群部署。它会先和 NameServer 集群中的随机一台建立长连接,得知当前要发送的 Topic 存在哪台 Broker Master上,然后再与其建立长连接,支持多种负载平衡模式发送消息;
Producer
消息消费者,也可以集群部署。它也会先和 NameServer 集群中的随机一台建立长连接,得知当前要消息的 Topic 存在哪台 Broker Master、Slave上,然后它们建立长连接,支持集群消费和广播消费消息;
Consumer
rocket mq
多个副本,保证数据安全
没有到达确认 : 网络异常可能丢消息
异步发送:客户端批量发送,然后宕机
acks设置为1时,Leader副本接收成功,Kafka集群就返回成功确认信息,而Follower副本可能还在同步
副本异常
消息丢失的场景
异步+到达不确认
允许丢失部分消息
同步 + 当Leader和Follower副本都接收成功后,返回接收成功确认信息
不丢失消息数据
吞吐量 VS 消息完整性
消费逻辑进行幂等性处理
重复消费的场景
数据文件分段存储
分布式:kafka是分布式部署的,能通过横向扩展提升读写效率
分区:通过分区的方式提升性能
日志编码:降低了消息的大小
消息压缩 、 批量处理
提升消费者端读取 Offset 时访问物理存储的效率
用跳表思想,设计 Log 和 Index 文件
稀松索引 + 顺序写
允许操作系统将数据直接从页缓存发送到网络上
避免从磁盘到内核到socket
零拷贝技术,减少数据在不同环节的数据来回复制,从而提升写入和读取的超快速度
高性能
消息队列
zookeeper
eureka
注册中心
中间件
bean的生命周期
三层依赖
IOC : 源码阅读
隔离级别
传播等级
默认配置
事务
spring
启动流程
springboot
Java框架
编程技术框架
收藏
0 条评论
回复 删除
下一页