first

291 阅读19分钟

缺点:

  1. 大而全,比如redis-数据结构 那里
  2. 不好理解,不如自己的语言
  3. 只需要整理综合几个jl的内容就行了,以北大的为主, 整理添加之前jd实习的那个;
  4. 别忘了这个脑图还有后边一部分是知识点,知识点前几个水,后边质量很高,下边有答案,还得结核之前整理的本子一起吧,有些地方还不如自己整理的

整理添加北大的哪个;

北大的jl;

敖丙的jl;

自己的jl设计;三大块

内容换成自己本子整理的+根据jl整理(重点)(内容很多,根本学不过来),这才是重点

他的这些东西怎么和 鸡蛋 的这么相似

数据库调优查看6.11好的微信收藏

一、集合

  1. hashmap
  • 1.7
1. 数组+链表

2. 头插
  • 1.8
1. 数组+链表+红黑树
2. 尾插
  • 扩容机制
LoadFactory默认是0.75
创建一个空数组重新hash---hash公式跟长度有关
  • 线程不安全

  • 2的幂次

方便位运算
均匀分布
  • 重写equals必须重写HashCode
  1. concurrenthashmap
  • 安全失败
  • 1.7
1. 数组+链表
2. segment分段锁
    - 继承了reentranLock
    - 尝试获取锁存在并发竞争 自选 阻塞
3. get高效 volatile修饰 不需要加锁
4. volatile修饰节点指针
5. HashEntry

  • 1.8
1. 数组+链表+红黑树
2. CAS+synchronized ————cas失败自旋保证成功————再失败就sync保证
3. node
  1. ArrayList
  • 数组
  • 查找 访问速度快 增删效率低 线程不安全
  1. LinkedList

二、基础

  1. UDP
  • 语音
  • 视频
  • 直播
  1. TCP
  • 三次握手
syn seq
syn ack seq
ack seq
为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误
  • 四次握手
fin ack seq
ack seq
fin ack seq
ack seq
  • 场景
网络会话
文件传输
发送接收邮件
远程登录
  • 如何保证可靠
  1. HTTP
  2. HTTPS ————为什么安全
  3. BIO
  • 阻塞等待链接
  • 阻塞等待数据
  • 开线程处理并发
  • 耗资源
  1. BIO
  • 非阻塞IO
  • epoll
  1. 粘包/拆包————在报文末尾增加换行符表明一条完整的消息,这样在接收端可以根据这个换行符来判断消息是否完整。将消息分为消息头、消息体。可以在消息头中声明消息的长度,根据这个长度来获取报文(比如808协议)。规定好报文长度,不足的空位补齐,取的时候按照长度取即可。
  2. 多路复用
  • select
单个进程可监视的fd数量被限制,即能监听端口的大小有限。
对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低
需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大
  • poll
大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义
poll还有一个特点是“水平出发”,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd。
  • epoll
没有最大并发连接的限制,能打开的fd的上限远大于1024(1G的内存上能监听约10万个端口);
效率提升,不是轮询的方式,不会随着fd数目的增加效率下降
内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递;即epoll使用mmap减少复制开销。
  1. neetty 非异步 阻塞 response trse id 感觉
  2. 序列化

三、多线程

  1. synchronized
  • 对象(header)
1. 对象头
Mark Word (存储对象的HashCode,分代年龄和锁标志位信息)
Klass Point (对象只想它的类源数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例)
Monitor 分为EntryList、Owner(会指向持有Monitor对象的线程)、WaitSet
2. 实例数据
3. 对齐填充
  • 方法————ACC_SYNCHRONIZED
  • 代码块
monitorenter
monitorexit
程序计数器count————加减
  • 锁膨胀
偏向->轻量级(乐观)->自旋->重量级
  1. ThreadLocal
  • 内存泄露
  • session
  1. Lock
  • ReentrantReadWriteLock
ReadLock
WriteLock
  • ReentrantLock
NonfairSync
1. tryAcquire
2. acquireQueued
3. CAS
FairSync
1. hasQueuedPredecessors
2. 如果是当时持有锁的线程 可重入
AbstractQueuedSynchronizer
1. 入队出队
2. 头结点设计
3. 共享和独享的实现
4. - CAS实际应用
   - 存在的问题
        cpu开销
        只能保证一个共享变量院子操作————AtomicReference
        ABA
  • StampedLock
  1. volatile
  • MESI
当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此,当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取
锁bus
volitale会一直嗅探cas不断循环无效交互 导致带宽达到峰值————总线风暴
  • java内存模型LMM————高速缓存
  • 可见性————嗅探机制 强制失效————处理器嗅探总线
  • 有序性
禁止指定重排序————lock前缀指令 内存屏障————源代码->编译器优化重排序->指令级并行重排序->内存系统重排序->最终执行的指令序列
happens-before————volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。
as-if-serial
  • Atomiclnteger
  • 跳出死循环
  1. 线程池
  • newFixedThreadPool
  • newCacheThreadPool————SynchronousQueue
  • newSingleThreadExecutor
  • newScheduledThewadPool————DelayedWorkQueue
  • newWorkStealingPool
  • ThreadPoolExecutor
  • 参数意义
核心线程数————默认没线程等任务来了才调用 除非调用了 预创建线程 一个或者全部
最大线程数
空闲时间&单位————没有执行任务多久会终止 当线程数大于核心线程数才会起作用 调用allowCoreThreadTimeOut会起作用
缓冲队列
    LinkedBlockingQueue————无界 当心内存溢出
    ArrayBlockingQueue
                有界队列
                加锁保证安全 一直死循环阻塞 队列不满就唤醒
                入队
                    阻塞调用方式put(e)或offer(e,timeout,unit)
                    阻塞调用时,唤醒条件为超时或者队列非满(因此,要求在出队是,要发起一个唤醒操作)
                    进队成功之后,执行notEmpty.signal()唤起被阻塞的出队线程
                    在进行某项业务存储操作时,建议采用offer进行添加,可以寄获取boolean进行判断,如用put要考虑阻塞情况(队列的出队操作慢于进队操作),资源占用
    Synchronous  
工厂方法
拒绝策略
    抛异常
    丢弃
    重试
    丢弃最早提交的
使用Has表维护线程的引用
submit————使用future获取任务的执行结果
  • 实际使用
商品详情页面
批处理
  • 执行过程————核心线程->队列->最大线程->拒绝策略
  • 运行状态
有个Volatile的状态码
    running
    shutdown
    stop
    terminated————所有线程销毁
corePoolSize、maxnumPoolSize、largestPoolSize 有意思
  • 故障
  1. JUC

  2. 常见问题

  • 线程间是怎么进行通信的?
主要可以介绍一下wait/notify机制,共享变量的synchronized或者Lock同步机制
volatile
CountDownLatch
CyclicBarrier

ThreadLocal用来解决什么问题?————可以尽量减少临界区范围,使用ThreadLocal,减少县城切换、使用读写或copyonwrite等机制这些方面来回答 如何尽可能提供多线程并发性能?————ThreadLocal是如何实现的?可以重点回答ThreadLocal不是用来解决线程变量的问题,而是用来解决线程数据隔离 读写锁适用于什么场景?————可以回答读写锁适合读并发多,写并发少的场景,另外一个解决这种场景的方法是copyonwrite 如何实现一个生产者与消费者模型?————可以尝试通过锁、信号量、县城通信、阻塞队列等不通方式实现。

  1. 线程状态————线程就绪 start selle休眠超时

  2. countDownLatch

  • 只有一个构造方法 只会被赋值一次
  • 没有别的方法可以修改count

四、JVM

  1. JVM内存模型
  • 方法区
  • 本地方法栈
  • 程序计数器
  1. 类加载机制
  • 加载->验证->准备->解析->初始化->使用->卸载
  • 双亲委派机制————父类加载 不重复加载
  1. 分代回收
  • 年轻代————eden/s1/s2
  • 老年代
  • 永久带/元空间
  • 晋升机制————根据存活时间
  1. 垃圾回收机制
  • 标记清楚
适用场景
    对象存活比较多的时候适用
    老年代
缺点
    提前GC
    碎片空间
    扫描了两次
        标记存活对象
        清楚没有标记的对象
  • 标记复制
适用场景
    存货对象少 比较高效
    扫描了整个空间(标记存活对象并复制移动)
缺点
    需要空闲空间
    需要复制移动对象
  • 引用计数————没办法解决循环引用的问题
  • 标记整理
  1. 垃圾回收器
  • CMS
分代
    年轻
        edan
        s1
        s2
        minor gc ————通过阈值晋升
    老年————major gc 等价于full gc
    永久
缺点
    对cpu资源敏感
    无法处理浮动垃圾
    给予标记清除算法 大量空间碎片
  • G1
分区概念 弱化分代
标记整理算法 不会产生空间碎片 分配大对象不会提前full gc
可以设置预设停顿时间
充分利用cpu 多喝条件下 缩短 stw
收集步骤
    初始标记 stw 从gc root开始直接可达的对象
    并发标记 gc root 对象进行可达性分析 找出存活对象————可达性分析算法
    最终标记
    筛选回收————根据用户期待的gc停顿时间指定回收计划
回收模式
    young gc————回收所有的eden s区————复制一些存活对象到old区s区
    mixed gc
gc模式
  • 区别
g1分区域 每个区域室友老年代概念的 但是收集器以整个区域为单位收集
g1回收后马上合并空闲内存 cms在stw的时候做
  • 内存区域设置
XX:G1HeapRegionSize
复制成活对象到一个区域 暂停所有线程
  1. full gc
  • 老年代写满
  • system.gc
  • 持久代空间不足
  1. STW
  2. 实战
  • 性能调优
设置堆的最大最小值 -xms -xmx
调整老年和年轻代的比例———— -XX:newSize设置绝对大小————防止年轻代堆收缩:老年代同理
主要看是否存在更多持久对象和临时对象
观察一段时间 看峰值老年代如何不影响gc就加大年轻代
配置好的机器可以用 并发收集算法
每个线程默认会开启1M的对战 存放栈帧 调用调参 局部变量 太大了 500k够了
原则就是减少gc stw
  • FullGC内存泄露排查
jasvism
dumo
监控配置 自动dump
  1. OOM种类
  2. 逃逸分析
  3. 可达性
  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法去中常量变量引用的对象
  • 本地方法栈中JNI(一般说的Nativa方法)引用的对象
  • 活跃线程的引用对象
  1. JVM调优
  • OOM
  • 内存泄露
  • 线程死锁
  • 锁争用
  • java进程消耗CPU过高
  1. JVM性能检测工具
  • Jconsole
  • Jprofiler
  • jvisualvm
  • MAT
  1. 内存泄露
  • help dump
  • 生产机dump
  • mat
  • jmap
  • -helpdump
  1. CPU100%
  • topc -c
  • top -Hp pid
  • jstack————进制转换
  • cat

五、spring

  1. 设计模式
  • 单例
  • 工厂
  • 适配器————根据不同商家适配
  • 责任链————集成process链路执行
  1. 源码
  2. Bean
  • 生命周期
扫描类————invokeBeanFactoryPostProcessors
封装beanDefinition对象 各种信息
放到map
遍历map
验证
    能不能实例化 需要实例化么 根据信息来
    是否单例等等
    判断是不是factory bean
    单例池 只是一个ConcurrentHashMap而已
    正在创建的 容器
得到class
腿短构造方法
    格局注入模型
    默认
得到构造方法
反射 实例化这个对象
后置处理器合并beanDefinition
判断是否允许 循环依赖
提前暴露bean工厂对象
填充属性————自动注入
执行部分aware接口
继续执行部分aware接口 生命周期回调方法
完成代理AOP
beanProstprocessor的前置方法
实例化bean
放到单例池
销毁
  • 作用域
单例(singleton)
多例(prototype)
Request
Session
  1. 循环依赖
  • 情况
属性注入可以破.解
构造器不行————三级缓存没自己 因二级之后去加载B了
  • 三级缓存
去单例池拿
判断是不是正在被创建的
判断是否支持循环依赖
二级缓存 放到 三级缓存
干掉二级缓存————GC
下次再来直接 三级缓存拿 缓存
  • 缓存 存放
一级缓存 单例Bean
二级缓存 工厂 产生Bean ————产生bean复杂
三级缓存 半成品
  1. 父子容器
  2. 事务实现原理
  • 采用不同的连接器
  • 用AOP新建立一个 链接————共享链接
  • ThreadLocal当前事务
  • 前提是 关闭AutoCommit
  1. AOP
  • 静态代理————实现类
  • 动态代理
JDK动态代理————实现接口————java反射几只生成一个代理接口的匿名类————调用具体方法的时候调用invokeHandler
cjlib————asm字节码编辑技术动态创建类 给予classLoad装在————修改字节码生成自雷去处理
  1. IOC
  2. 类加载机制
  • 过程
加载————生成一个class对象
验证
    文件格式验证
    元数据验证
    字节码验证
    符号引用验证
准备
    默认值
    static会分配内存
解析————解析具体类的信息————引用等
初始化————父类没初始化 先初始化父类
使用
卸载
  • 加载方式
- main()
- class.forName
- ClassLoader.loadClass
  • 类加载器
- Appclass Loade
- Extention ClassLoader
- Bootstrap ClassLoader
  • 双亲委派原则
- 可以避免重复加载
- 安全

六、redis

  1. 数据结构
  • string
  • hash
  • set
  • zset
score
随机层数————只需要调整前后节点指针
不止比较score————还会比较value
场景
    成绩
    积分
    排行榜
  • list————分页的坑
  • HyperLogLog
  • Geo
  • Pub/Sub
  • BitMap
  • 底层
SDS
        保存键值
        AOP缓存区
        记录本身长度 C需要遍历
        修改字符减少内存重新分配
            空间预支配
            惰性空间释放
        二进制安全
链表
    保存多个客户端的状态信息
    列表订阅发布 慢查询监视器
字典
    hashhash表节点
    hash算法 索引值
    渐进式rehash
    每个字典带 两个hash表
压缩列表
整数集合
  1. 常见命令
  • keys
  • setnx
  • exprie
  1. 高可用
  • 持久化
    RDB
        5分钟一次
        冷备
        回复的时候比较快
        快照文件生成时间久 消耗cpu
    AOF
        appendOnly
        数据齐全
        恢复慢文件大
    数据初始化————从节点发送命令主节点做bgsave同时开启buffer
  • 数据同步机制
主从同步————指令流————offset
快照同步————RDB————缓冲区
  • 哨兵
集群监控
消息通知
故障转移
配置中心
脑裂
  • 集群
链表
多主————横向扩容
分片
  1. 常见问题
  • 缓存雪崩
加随机机制
集群部署
  • 缓存击穿
互斥锁
热点数据不失效
  • 缓存穿透————布隆过滤器
  • 双鞋一致性————演示双删
  • 并发竞争————分布式锁
  • 大Key
bigkey命令 找到干掉
redis4.0引入了memory usage命令和azyfree机制
  • 热点key
缓存时间不失效
多级缓存
布隆过滤器
读写分离
  1. 过期策略
  • 定时删除————消耗内存————创建一个定时器
  • 惰性删除————可能存在大量key
  1. 淘汰机制————LUR————最少使用
  2. 备用方案
  • 主从+哨兵—+cluster
  • 额擦车+hystrix+降级+熔断+隔离
  • 持久化
  1. 限流
  • setnx ex
  • zset
窗口滑动
zset会越来越大
  • 令牌
定时push
然后leftpop
问题————空轮训————blpop————空连接异常————重试
  • 漏桶 funnel————make_space灌水之前调用漏水 腾出空间取决于流水速度————Hash————原子性有问题————Redis-Call
  • redis cell————热点key(1.二级缓存 2.备份热key 走不同的机器)
  1. 选择方案
  2. 扩展
  • 跳跃表
  • 令牌
  • 漏桶
  • scan
  1. 多路IO复用
  • read得读到很多才返回 为0会卡在那 知道新数据来或者链接关闭
  • 写不会阻塞除非缓冲区满了
  • 非阻塞的IO 提供了一个选项no_blocking读写都不会阻塞 读少写多少 取决于内核的套接字字节分配
  • 非阻塞IO也有问题 秀按成要读数据 读了一点就返回了 线程什么时候知道继续读? 写一样
  • 一般都是select解决但是性能低 现在都是epoll

七、mysql

  1. 分库分表————唯一主键
  2. 事务隔离级别
  • 读未提交————没视图概念 都是返回最新的
  • 读已提交————不同的read view
  • 可重复读————用一个read view
  • 序列化
  • 回滚日至————没更早的read view删除————5.5之前回滚段删了文件也不会变小
  1. 索引
  • B+
  • Hash————等值查询
  • 优化流程
预发跑sql explain
排除缓存sql nocache
看一下行数对不对不对可以用analyze table t矫正
添加索引 索引不一定是最优的 force index强制走索引不建议用
存在回表的情况
覆盖索引避免回表 不要*
联合索引 不能无限建 高频场景
最左前缀原则按照索引定义的字段顺序写sql
合理安排联合索引的顺序
5.6之后 索引下推 减少回表次数
  • 聚集索引
  • 非聚集索引————多扫描一次————减少回表
  • 索引维护
页满了 页分裂 页利用率下降
数据删除 页合并
自增 之追加可以不考虑 页分裂
索引长度
  • 索引选择
普通索引————找到第一个之后 直到碰到不满足的
唯一索引————找到第一个不满足的就停止了
页的概念
更新
    change buffer
    更新操作来了 如果数据页不在内存 就缓存下来 下次来了 更新 在就直接更新
    唯一索引 需要判断 所以 用不到change buffer
    innodb的处理流程
        记录在页内存
            唯一索引 判断没冲突插入
            普通索引 插入
        记录不在页中
            数据页读入内存 判断 插入
            change buffer
        数据读是随机IO 成本高
        机械硬盘 change buffer收益大 写多读少 marge
  1. MVCC
  • 版本链 在聚集索引中 有两个隐藏列 trx_id roll_pointer
  • 读未提交————直接读取最新版本
  • 序列化————加锁
  • read view
读已提交————每次读取前生成一个
可重复读————第一次生成一个
  • 全局锁————全库逻辑备份
  • 表锁
lock table read/write
读锁不互斥 写锁互斥
  • 行锁
需要的时候才加上 并不是马上释放 等事务结束才释放 两阶段锁协议
死锁
    超时时间————innodb_lock_wait_timeout
    死锁机制 事务回滚————innodb_deadlock_detect=on
热点行
    死锁消耗CPU————临时关闭
    控制并发度
    分治
  • 间隙锁
  • 读写锁
读
    lock in share mode
    for update
    行锁
写
  • innodb如何加锁
record lock:对索引项加锁
Gap lock:对索引项之间的'间隙',第一条记录前的间隙,或者最后一条记录后的间隙 加锁
Next-Key:前两种的组合,对记录以及前面的间隙加锁
  1. B+
  2. log
  • undo log ————回滚mvcc
  • redo log
  • binlog
  • 两段式提交redo 准备binglog提交
  1. count1*————mvcc影响
  2. 主备延迟
  • 强制走主
  • sleep
  1. join————驱动表
  2. id用完
  • bigint
  • row_id 没设置主键的时候
  • thread_id
  1. 真实故障————数据库挂了 show processlist 一千个查询在等待 有个超长sql kill 但是不会引起flush table 周末 优化脚本 analyze会导致mysql检测到对应的table 做了修改 必须flush close reopen 就不会释放表的占用了

八、zookeeper

  1. 选举机制
  2. 过半机制
  3. 预提交 ack spc

九、dubbo

  1. netty
  2. 链路调用
  3. 服务暴露过程
  4. 服务引用
  5. SPI
  6. 容错机制
  7. 降级
  8. 负载均衡
  9. 协议

十、rocketmq

  1. 基础组成
  2. 支持集群模式
  3. 消费保证
  4. 高可用
  5. 顺序消息
  6. 消息去重
  7. 分布式消息
  8. 分布式事务
  9. 完整的一个调用链路
  10. 消息重试
  11. 死信队列
  12. 事务消息
  13. 消息丢失
  14. 消息积压

十一、分布式锁

  1. zookeeper
  • 死锁
  • 羊群效应
  • 临时节点顺序
  • 性能没redis高
  1. redis
  • jedis.set(String key,String value,String nxxx,String expx,int time)
  • 性能比较高
  1. 数据库
  • 死锁
设置一个失效时间用定时任务去跑
数据库集群 主备同步
搞个死循环排队
可冲入设计一个字段累加
  • 排他锁
用数据库自身的锁就可以了 行锁 索引
select XX for update
记得 提交
宕机数据库也会自动释放锁
  • 缺点
比其他的更消耗资源
复杂
  1. 特点
  • 互斥
  • 安全性
  • 死锁
  • 容错

十二、算法

  1. 贪心
  2. 分治
  3. 动态规划
  4. 快排
  5. 二叉树
  6. 链表反转
  7. 成环
  8. 环节点
  9. 跳楼梯

十三、扩展知识

  1. 内存屏障
  2. 指令乱序
  3. 分支预测
  4. NUMA
  5. CPU亲和性

十四、遇到的坑

  1. sync遇到了bgsave————CPU飙升————bgsave之后会做一个emptyDB————之歌时候做bgsave cow的机制就没了————会重新加载整个RDB————然后就swap
  2. 高并发场景下无限同步————tps过高的时候————master复制缓存挤压区的时候 有个参数 client-output-buffer-limit默认1M————大量请求会让值升高 超出阈值断开————重连
  3. slave做RDB同步的时候会导致TPS过高无法加载————阻塞久了复制缓冲区的数据就被冲掉了,是个队列会踢掉之前的数据————slave重连对比offset发现空挡重新sync————预估体量参数动态调整
  4. canal并发修改
  5. es自动机构建
  6. redis es 深分页

十五、为什么想换gz————想去阿里

十六、有什么想问我的

  1. 我的回答有什么建议吗
  2. 阿里的解决方案
  3. 团队主要做的事情

十七、项目

  1. 竞价服务
  • 竞价策略
  • 开关
  • 频控
  • 出价
  1. 监控服务
  • 行为监控
获胜
点击
曝光
播放完成
  1. 物料
  • 送审
  • 合成
  • 商品自动拼装
  • 流量监控
  • 自动化

十八、设计方案

  1. 高并发下单
  2. 订单生成