kafka
1. 为什么快? 1. partition文件采用追加, 且数据批量压缩 2. 利用了OS中内存-磁盘映射公里, 提高读写速度 3. 消息消费后, 不删除, offset偏移量增加
redis
哨兵机制
主从复制
持久化
redis数据备份原理,RDB和AOF
- RDB : 子线程通过父线程建立的快照, 创建持久化文件, 更加紧凑,
- AOF: 类似日子, Redis收到写入命令记录到AOF文件中,更实时
同步机制
初次同步, 执行一次快照(RDB)文件 传输给从服务器,之后同步AOF指令
- 细节: 主服务器会维护一个AOF指令队列,如从服务器断开再连,对比同步偏移量判断缺失数据是否在AOF指令池,如果超过,执行全量同步
master挂了选举
- 哨兵从slave中踢出与 master断开时长超过一定指的机器
- 按slave优先级, 优先级越低, 选中机会越大,
- 选取与master同步数据最多的
- 如果都相同, run id最小
为什么快
- 单线程, 无线程间同步/阻塞
- 字典结构, 存内存,0(1)
- NIO
内存满了
- 拒绝写入数据
- 随机淘汰key
- 移除使用最少
- 移除过期时间里面使用最少
- 移除最早过期
LRU 算法
- 简单版: 维护链表,每次访问,移到表头(缺点:需要遍历)
- 优化版: 链表字典,字典存储前后索引,替代链表遍历功能
Bloom Filter
- K个计算散列函数,算出结果在数组位点记录1,查询时判断是否全为1
- Pipeline
JVM
JAVA内存模型:
- Java分工作内存, 主内存, 每个线程都有自己独立工作内存, 在CPU高速缓存中, 针对变量操作都在工作内存中进行.
结构图
- 计数器, 本地方法区 堆区, 执行栈, 元数据内存区(1.8中, 永久代 字符串,常量存入,元数据)
垃圾回收:
- Serial YGC, 单线程收集, 简单, 但Stop the world, 一般用在client端
- ParNew YGC 多线程版 Serial
- Parallel Scavenge 默认 可控吞吐量
- CMS 多线程搜集, 少占用用户线程时间, 但有碎片
- G1 没有年轻代,老年代, 通过region划分区域, 收集完成会压缩整理, java9 默认.
类加载机制
- 启动类加载器(java_home/lib),拓展类加载器(java_home/lib/ext),应用程序加载器(用户代码)
JAVA容器
- HashMap,CurrentHashMap
数据库
锁:
- 行锁
- 页锁
- 表锁
事物:
- 丢失更新,脏读,不可重复读,幻读
隔离级别:
- UnCommit,
- Commit
- 可重复读(事物内读的数据一样, 但这些数据不允许修改) MYSQL默认
- 串行化, 只准一个事物进行
- (解释: 幻读, select不在, 插入发现有了, 事务内读取到的状态无法支撑后续操作)
数据结构算法
- B树,B-树
- B+树 适合存储数据量巨大, 因为数据均匀,层数少, 查找路径段段, 存储在磁盘上查找快
- 红黑树 适合内存级别, 效率比B+树快
并发
线程池
队列,
SynchronousQueue,
- 不暂存, 提交给任务线程, 最好设置maxNumberPoolSize
LinkedBlockingQueue,
- 使用corePoolSize,其他暂存
ArrayBlockingQueue
- 使用maxNumberPoolSize, 其他暂存
拒绝策略
- 报异常(默认 RejectedExecutionException)
- 什么都不做
- 丢弃老任务
- 右提交的线程执行
线程协作类
- CountDownLatch: 计数器, CountDown到0, 任务才开始执行
- CyclicBarrier: 大家等着一起执行.达到规定数后一起执行
- Semaphore: 信号量, 类似砸门, 限流
- Exchanger: 线程见交换数据
- ExecutorCompletionService
分布式事务(数据一致性)
2阶段提交
执行上分为 参与者,协调者
步骤
- 执行者执行好事务, 做好redo/undo准备, 告知协调者准备好,等待通知commit指令
- 协调者收到执行者待准备好消息, 通知大家可以提交事务
缺点:
- 协调者挂了, 执行者无畏等待,
- 2阶段过程中, 有执行者网络不稳定, 未接收到指令, 造成其他执行者提交, 产生数据不一致问题
3阶段提交
同样分为 参与者/执行者
步骤:
CanCommit —> preCommit—>doCommit
- canCommit: 协调者依次通知执行者, 是否尅执行事务, 反馈Yes, 进入预提交阶段
- preCommit : 执行者接收到协调者指令, 进行事务操作, 并记录好redo/undo日志, 并告知协调者准备就绪
- doCommit: 所有执行者准备就绪, 告知可以提交事务 , 进行最后commit操作.
优点:
- 执行者/协调者都加入了超时机制, 避免无谓等待
- 加入了准备阶段, 保证最后提交之前各执行者状态一致
缺点:
- 在最后doCommit阶段, 依然无法避免某执行者网络问题, 未接收到提交指令
- 终极方案, 引入 Paxos算法
JDK代理 Cglib代理
Spring默认用JDK(SpringBoot2.x会改为Cglib ,注入的是实现, 非接口时 会报错, 因为 JDK 动态代理是基于接口的,代理生成的对象只能赋值给接口变量。)
- 通过InvocationHandler 接口实现, 通过Proxy创建代理类
- Cglib 实现基层类