MindMap

JMM

mindmap
  root((JMM<br/>Java Memory Model))
    本质
      并发访问共享变量的规则
      不是JVM物理内存分区
      解决线程间可见性与有序性问题
    核心目标
      原子性
      可见性
      有序性
    抽象模型
      主内存
        存共享变量
      工作内存
        每个线程私有副本
        线程先读副本再写回主内存
    问题来源
      缓存不一致
      指令重排
      并发交错执行
    关键机制
      volatile
        保证可见性
        禁止部分指令重排
        不能保证复合操作原子性
      synchronized
        保证原子性
        保证可见性
        保证有序性
      final
        构造完成后安全发布
        对final字段有特殊可见性保障
    Happens-Before
      程序次序规则
      锁规则
      volatile规则
      start规则
      join规则
      传递性
    重排序
      编译器优化
      CPU乱序执行
      单线程遵守as-if-serial
      多线程可能出问题
    经典场景
      volatile标志位
      DCL单例
      i++线程不安全

JUC

mindmap
  root((JUC<br/>Java Util Concurrent))
    本质
      Java并发编程工具箱
      高层并发组件
      覆盖任务执行 锁 容器 协作 异步
    包结构
      java.util.concurrent
      java.util.concurrent.locks
      java.util.concurrent.atomic
    任务执行
      Executor
      ExecutorService
      ScheduledExecutorService
      ThreadPoolExecutor
      Future
    锁体系
      Lock
      ReentrantLock
      ReadWriteLock
      ReentrantReadWriteLock
      Condition
    底层支撑
      AQS
      LockSupport
      CAS
      volatile
    原子类
      AtomicInteger
      AtomicLong
      AtomicReference
      AtomicStampedReference
      LongAdder
    并发容器
      ConcurrentHashMap
      ConcurrentLinkedQueue
      CopyOnWriteArrayList
      ConcurrentSkipListMap
      ConcurrentSkipListSet
    阻塞队列
      BlockingQueue
      ArrayBlockingQueue
      LinkedBlockingQueue
      PriorityBlockingQueue
      SynchronousQueue
    同步器
      CountDownLatch
      Semaphore
      CyclicBarrier
      Phaser
    异步与并行
      ForkJoinPool
      ForkJoinTask
      CompletableFuture
      CompletionStage
    面试主线
      线程池参数与拒绝策略
      AQS原理
      CAS与ABA
      ConcurrentHashMap
      BlockingQueue生产者消费者
      CountDownLatch与CyclicBarrier区别
      CompletableFuture链式编排

设计模式

mindmap
  root((设计模式 Design Patterns))
    设计目标
      提高可维护性
      提高可复用性
      提高可扩展性
      降低耦合
      提升沟通效率

    设计原则
      SOLID
        SRP["单一职责原则 SRP
        一个类只做一类事"]
        OCP["开闭原则 OCP
        对扩展开放 对修改关闭"]
        LSP["里氏替换原则 LSP
        子类可替换父类"]
        ISP["接口隔离原则 ISP
        接口要小而专"]
        DIP["依赖倒置原则 DIP
        面向抽象编程"]
      其他原则
        CARP["合成复用原则
        多用组合 少用继承"]
        LoD["迪米特法则
        只和直接朋友通信"]

    分类
      创建型模式
        核心["关注对象怎么创建"]
        简单工厂
        工厂方法
        抽象工厂
        单例
        建造者
        原型
      结构型模式
        核心["关注类和对象如何组合"]
        适配器
        代理
        装饰器
        外观
        桥接
        组合
        享元
      行为型模式
        核心["关注对象如何协作和分配职责"]
        观察者
        责任链
        策略
        状态
        模板方法
        命令
        迭代器
        中介者
        备忘录
        访问者
        解释器

    创建型高频
      工厂模式家族
        简单工厂
          优点["创建逻辑集中"]
          缺点["新增产品要改工厂
          违反开闭原则"]
        工厂方法
          优点["扩展新产品更方便
          符合开闭原则"]
          缺点["类数量增加"]
        抽象工厂
          核心["创建一整套产品族"]
          优点["同一风格产品统一切换"]
          缺点["新增产品等级结构困难"]
      单例模式
        核心["一个类只有一个实例"]
        写法
          饿汉式
          懒汉式
          同步方法懒汉式
          DCL["双重检查锁 DCL"]
          静态内部类["推荐"]
          枚举单例["推荐"]
        关注点
          线程安全
          懒加载
          防反射破坏
          防反序列化破坏

    结构型高频
      适配器模式
        核心["接口不兼容时做转换"]
        角色
          Target["目标接口"]
          Adaptee["被适配者"]
          Adapter["适配器"]
        实现
          类适配器["继承实现"]
          对象适配器["组合实现 更推荐"]
      代理模式
        核心["控制对目标对象的访问"]
        作用
          权限控制
          日志
          事务
          延迟加载
          远程调用
        Java实现
          静态代理
          JDK动态代理
          CGLIB代理
      装饰器模式
        核心["不改原类前提下动态增强功能"]
        对比代理
          装饰器更强调功能增强
          代理更强调控制访问

    行为型高频
      观察者模式
        核心["一对多通知机制"]
        适用
          事件发布订阅
          消息通知
          状态变化广播
      责任链模式
        核心["多个处理器串成链逐个处理"]
        适用
          过滤器链
          拦截器链
          审批流
      策略模式
        核心["封装可替换算法"]
        优点
          消除大量 if else
          算法可自由切换
          符合开闭原则
        适用
          支付方式
          促销计算
          负载均衡
      状态模式
        核心["状态不同 行为不同"]
        适用
          订单状态流转
          工作流状态机
        对比策略
          策略["重点在算法替换"]
          状态["重点在状态驱动行为变化"]

    面试回答主线
      第一步["先说属于哪一类模式"]
      第二步["再说解决什么问题"]
      第三步["讲核心角色和结构"]
      第四步["补优缺点"]
      第五步["结合框架或项目举例"]

    框架里的影子
      Spring
        工厂["BeanFactory"]
        代理["AOP 事务"]
        观察者["事件机制"]
      JDK
        单例["Runtime"]
        工厂["Calendar getInstance"]
        迭代器["Iterator"]
      Netty
        责任链["Pipeline"]
      Dubbo
        代理
        装饰器
        策略
        责任链

API

输入输出&字符串

mindmap
  root((输入输出与字符串))
    输入处理
      Scanner
        next
        nextInt
        nextLine
        常见坑
          nextLine吞换行
      BufferedReader
        readLine
        配合StringTokenizer
        性能高于Scanner
      StringTokenizer
        分词处理
        高效输入拆分
    输出处理
      System.out
        print
        println
        printf
      格式化输出
        %d %s %f
    String基础
      创建方式
        字面量
        new String
      常用方法
        length
        charAt
        equals
        compareTo
        indexOf
        lastIndexOf
        contains
      截取与拼接
        substring
        concat
      判断类
        startsWith
        endsWith
        isEmpty
    StringBuilder
      可变字符串
      append
      insert
      delete
      reverse
      toString
      应用
        高频拼接
        回文处理
    StringBuffer
      线程安全
      性能较低
      使用较少
    字符数组
      char
        toCharArray
        new String(char)
      应用
        双指针
        原地修改
    转换操作
      字符串转数字
        Integer.parseInt
        Long.parseLong
        Double.parseDouble
      数字转字符串
        String.valueOf
        Integer.toString
      字符转换
        Character
          isDigit
          isLetter
    分割与替换
      split
        正则分割
      replace
      replaceAll
    常见技巧
      去空格
        trim
      大小写转换
        toLowerCase
        toUpperCase
      字符频率统计
        Map结合String

数组和工具类

mindmap
  root((数组与工具类))
    数组基础
      定义与初始化
        int
        new int[n]
        静态初始化
      访问与遍历
        for循环
        增强for
        下标访问
      多维数组
        二维数组
        不规则数组
    Arrays工具类
      排序
        sort
          基本类型排序
          对象排序
          自定义Comparator
      查找
        binarySearch
          前提有序
          返回插入点规则
      填充
        fill
      拷贝
        copyOf
        copyOfRange
      转字符串
        toString
        deepToString
      比较
        equals
        deepEquals
    System工具
      数组拷贝
        arraycopy
          高性能native方法
          浅拷贝
      时间计算
        currentTimeMillis
        nanoTime
    排序技巧
      基本排序
        升序默认
      自定义排序
        lambda表达式
        Comparator接口
      二维数组排序
        按某列排序
      TopK问题
        排序解法
    二分查找
      手写模板
        左边界
        右边界
      API方式
        Arrays.binarySearch
      常见场景
        查找目标值
        查找插入位置
    前缀和
      一维前缀和
        prefixi=sum[0,i)
      二维前缀和
      应用
        区间求和
        子数组问题
    差分数组
      原理
        区间更新
      构造
        diff数组
      应用
        批量区间修改
    常见技巧
      数组反转
        双指针交换
      滑动窗口
        左右指针
      双指针
        对撞指针
        快慢指针
      离散化
        排序+去重+映射
    易错点
      越界问题
        index<length
      binarySearch误用
        未排序数组
      浅拷贝问题
        多维数组坑

集合框架

mindmap
  root((集合框架))
    总体结构
      Collection
        List
        Set
      Map
        键值对结构
      Iterable
        for-each基础
    List体系
      ArrayList
        底层结构
          动态数组
        特点
          随机访问快
          插入删除慢
        常用API
          add
          get
          set
          remove
        扩容机制
          1.5倍扩容
      LinkedList
        底层结构
          双向链表
        特点
          插入删除快
          查询慢
        常用API
          addFirst
          addLast
          removeFirst
        兼容Deque
    Set体系
      HashSet
        底层
          HashMap
        特点
          无序
          不重复
        判重机制
          hashCode+equals
      TreeSet
        底层
          红黑树
        特点
          有序
        排序方式
          Comparable
          Comparator
      LinkedHashSet
        特点
          保持插入顺序
    Map体系
      HashMap
        底层
          数组+链表+红黑树
        核心机制
          hash扰动
          位运算定位
        常用API
          put
          get
          remove
          containsKey
        高频场景
          计数
          映射关系
      TreeMap
        底层
          红黑树
        特点
          有序Map
      LinkedHashMap
        特点
          维护顺序
          LRU基础
    Queue与Deque
      Queue
        接口
          offer
          poll
          peek
        应用
          BFS
      Deque
        双端队列
          addFirst
          addLast
          pollFirst
          pollLast
        实现
          ArrayDeque
        应用
          单调队列
          滑动窗口
    PriorityQueue
      本质
        堆结构
      特点
        默认小顶堆
      常用API
        offer
        poll
        peek
      自定义排序
        Comparator
      应用
        TopK问题
        贪心算法
    Collections工具类
      排序
        sort
      反转
        reverse
      查找
        binarySearch
      最大最小
        max
        min
      频率统计
        frequency
    常见刷题模式
      去重
        Set
      计数
        Map
      分组
        Map+List
      滑动窗口
        Map+Deque
      BFS
        Queue
      TopK
        PriorityQueue
    易错点
      HashMap遍历
        entrySet优于keySet
      判重问题
        equals未重写
      并发问题
        非线程安全
      null处理
        HashMap允许null
        TreeMap不允许

数学与位运算

mindmap
  root((数学与位运算))
    Math工具类
      常用方法
        abs
        max
        min
        pow
        sqrt
        ceil
        floor
        round
      随机数
        random
      应用场景
        数值处理
        几何计算
    位运算基础
      基本操作
        按位与
        按位或
        按位异或
        按位取反
        左移
        右移
        无符号右移
      核心性质
        异或同数得零
        异或零得本身
        满足交换律
        满足结合律
    位运算技巧
      判断奇偶
        与一判断最低位
      清除最低位的一
        与上减一
      获取最低位的一
        与上相反数
      判断是否为二的幂
        与上减一后为零
      交换两个数
        异或交换
      统计二进制中一的个数
        BrianKernighan算法
    Integer工具类
      bitCount
        统计一的个数
      toBinaryString
        转二进制字符串
      highestOneBit
        最高位的一
      lowestOneBit
        最低位的一
    进制转换
      十进制转二进制
      二进制转十进制
      任意进制转换
      常用API
        Integer.parseInt
        Integer.toString
    数学技巧
      最大公约数
        辗转相除法
      最小公倍数
        乘积除以最大公约数
      快速幂
        分治思想
      质数判断
        平方根优化
    随机与概率
      Random类
        nextInt
      洗牌算法
        FisherYates
    常见刷题场景
      位掩码
        状态压缩
      子集枚举
        位枚举
      异或问题
        找唯一数
      数学规律
        找周期
        找不变量
    易错点
      位运算优先级
        建议加括号
      溢出问题
        int越界
      负数位运算
        补码表示
      pow精度问题
        double误差

排序与比较器

mindmap
  root((排序与比较器))
    排序基础
      排序目标
        升序
        降序
        自定义规则
      排序对象
        基本类型数组
        对象数组
        集合
    Arrays排序
      基本类型
        默认升序
      对象排序
        依赖Comparable
        或传入Comparator
      常用方式
        Arrays.sort
      二维数组排序
        按某一列排序
        多条件排序
    Collections排序
      List排序
        Collections.sort
      底层实现
        调用Arrays.sort
      适用场景
        ArrayList等集合
    Comparable接口
      定义
        类内部实现
      核心方法
        compareTo
      规则
        返回负数
        返回零
        返回正数
      特点
        固定排序规则
      应用
        自定义类排序
    Comparator接口
      定义
        外部比较器
      核心方法
        compare
      写法
        匿名类
        lambda表达式
      特点
        灵活
        可多规则切换
      应用
        临时排序需求
    Lambda排序
      基本写法
        简化Comparator
      示例
        按某字段排序
        多字段排序
      优点
        简洁
        可读性强
    PriorityQueue
      本质
        堆结构
      默认规则
        小顶堆
      自定义排序
        Comparator
      常用操作
        offer
        poll
        peek
      应用
        TopK问题
        贪心
    多条件排序
      先主条件
      再次条件
      链式比较
      常见写法
        if比较
        Comparator组合
    常见刷题场景
      区间问题
        按起点排序
      贪心问题
        按权重排序
      TopK问题
        堆或排序
      字符串排序
        字典序
    易错点
      compare返回值
        不能只返回1或0
      整数溢出
        相减比较风险
      稳定性
        排序是否稳定
      Comparator逻辑错误
        导致顺序异常

其他高频工具

mindmap
  root((其他高频工具))
    Collections工具类
      排序
        sort
      反转
        reverse
      打乱
        shuffle
      最大最小值
        max
        min
      频率统计
        frequency
      填充
        fill
    Objects工具类
      判空
        isNull
        nonNull
      比较
        equals
      空安全处理
        requireNonNull
    Character工具类
      判断类型
        isDigit
        isLetter
        isLetterOrDigit
      大小写判断
        isUpperCase
        isLowerCase
      转换
        toUpperCase
        toLowerCase
    BigInteger
      大数运算
        add
        subtract
        multiply
        divide
      应用场景
        超大数计算
    BigDecimal
      高精度小数
        add
        subtract
        multiply
        divide
      注意点
        精度控制
        舍入模式
    时间工具
      System
        currentTimeMillis
        nanoTime
      应用
        性能测试
    Random工具
      随机数生成
        nextInt
        nextDouble
      应用
        随机测试数据
    Stream流
      创建
        stream
      常用操作
        filter
        map
        forEach
      注意
        刷题中较少用
    常见刷题技巧
      判空处理
        防止空指针
      快速初始化
        Arrays.asList
      简化代码
        工具类方法
    易错点
      BigDecimal比较
        不能用equals
      Random范围
        注意边界
      Stream滥用
        影响性能

MyBatis

mindmap
  root((MyBatis 上))
    定义与定位
      本质
        半自动ORM
        SQL映射框架
        面向接口编程
      核心价值
        减少JDBC样板代码
        SQL可控
        映射灵活
      适用场景
        复杂查询多
        需要SQL优化
        对性能可控性要求高
      对比
        JDBC
          开发繁琐
        JPA
          复杂SQL不够灵活
        MyBatis Plus
          是增强
          底层仍是MyBatis
    核心架构
      配置层
        mybatis-config
        mapper.xml
        typeAliases
        plugins
        environments
      接口层
        Mapper接口
        动态代理
        方法与SQL绑定
      执行层
        SqlSession
        Executor
        StatementHandler
        ParameterHandler
        ResultSetHandler
      映射层
        MappedStatement
        ParameterMap
        ResultMap
        BoundSql
    核心流程
      启动阶段
        读取全局配置
        解析Mapper XML
        注册MappedStatement
        创建SqlSessionFactory
      调用阶段
        获取SqlSession
        获取Mapper代理对象
        调用接口方法
        定位MappedStatement
      执行阶段
        Executor调度
        StatementHandler创建预编译对象
        ParameterHandler设置参数
        JDBC执行SQL
        ResultSetHandler封装结果
      返回阶段
        对象映射
        一级缓存处理
        提交或回滚
        关闭SqlSession
    重要对象
      SqlSessionFactory
        工厂对象
        全局唯一
        线程安全
      SqlSession
        会话对象
        非线程安全
        一次数据库交互上下文
      MapperProxy
        JDK动态代理
        拦截接口方法调用
      Executor
        SimpleExecutor
        ReuseExecutor
        BatchExecutor
      MappedStatement
        一条SQL的完整定义
        包含参数映射结果映射
    SQL映射
      参数传递
        单参数
        多参数
          Param注解
          Map封装
        对象参数
        集合参数
          List
          Array
      占位符
        井号占位符
          预编译参数
          防SQL注入
          最常用
        美元占位符
          字符串拼接
          有注入风险
          常用于表名排序字段
      返回映射
        resultType
          简单直接
          适合单表简单对象
        resultMap
          复杂映射核心
          更灵活
      复杂映射
        字段别名
        一对一
          association
        一对多
          collection
        继承映射
          discriminator
    动态SQL
      核心标签
        if
          条件拼接
        where
          自动处理前导and或or
        set
          自动处理更新逗号
        trim
          自定义前后缀
        choose
          类似switch
        foreach
          in查询批量操作
      高频场景
        条件查询
        动态更新
        批量插入
        批量删除
        排序分页
      易错点
        空集合foreach
        where前多余and
        set后多余逗号
        美元占位符误用
mindmap
  root((MyBatis 下))
    缓存机制
      一级缓存
        作用域SqlSession
        默认开启
        本质本地缓存
        相同SQL可复用结果
      一级缓存失效
        不同SqlSession
        增删改后清空
        手动clearCache
      二级缓存
        作用域Mapper级别
        需显式开启
        多SqlSession共享
      二级缓存问题
        脏数据风险
        命中条件苛刻
        分布式场景不常直接用
      面试点
        一级缓存底层
        一级和二级区别
        为什么生产少用二级缓存
    延迟加载
      作用
        按需查询关联对象
        降低初次查询开销
      使用场景
        一对一
        一对多
      本质
        代理对象拦截getter
        访问属性时再发SQL
      优点
        减少无效查询
      缺点
        容易出现N加1问题
        调试不直观
      面试点
        延迟加载原理
        aggressiveLazyLoading
        何时关闭更合适
    插件机制
      本质
        拦截器链
        基于动态代理增强
      可拦截对象
        Executor
        StatementHandler
        ParameterHandler
        ResultSetHandler
      常见用途
        分页
        SQL审计
        多租户
        性能监控
        数据脱敏
      注意点
        插件顺序影响结果
        过度拦截增加复杂度
    Spring整合
      常见组件
        SqlSessionFactoryBean
        MapperScannerConfigurer
        MapperScan
      注入方式
        Mapper接口注入IOC
        Spring管理代理对象
      事务管理
        声明式事务
        SqlSession与事务同步
      优势
        简化配置
        更好管理连接事务
    MyBatis Plus
      定位
        MyBatis增强工具
        不是替代品
      常用能力
        BaseMapper
        条件构造器
        分页插件
        自动填充
        逻辑删除
      优势
        CRUD开发快
      边界
        复杂SQL仍回到原生MyBatis
    面试高频
      执行流程
        接口调用到SQL执行全链路
      占位符
        井号与美元区别
      映射
        resultType与resultMap区别
      缓存
        一级与二级区别
      延迟加载
        原理与N加1
      插件
        能拦截哪些对象
      Executor
        Simple
        Reuse
        Batch
      Mapper代理
        为什么接口无实现也能调用
      事务
        MyBatis事务
        Spring事务整合
    工程实践
      Mapper设计
        一个聚合一个Mapper
        SQL按业务分组
      XML规范
        SQL片段复用
        命名统一
        复杂查询优先XML
      性能优化
        避免N加1
        批量操作用Batch
        只查需要字段
        合理索引配合SQL
      安全
        优先用井号占位符
        严控动态表名排序字段
      可维护性
        SQL与业务注释清楚
        复杂resultMap拆分
        参数对象化
      排错
        打印SQL日志
        关注参数为空
        检查字段别名与映射
    常见误区
      误以为MyBatis自动生成所有SQL
      误以为懒加载一定更快
      误以为二级缓存生产必开
      误以为美元占位符只是另一种写法
      误以为SqlSession线程安全
      误以为MyBatis Plus等于MyBatis
    关联知识
      JDBC
        Connection
        PreparedStatement
        ResultSet
      设计模式
        工厂模式
        代理模式
        模板方法
      Spring
        IOC
        AOP
        事务
      数据库
        索引
        事务
        锁
        SQL优化

Spring

SpringMVC

mindmap
  root((SpringMVC))
    核心定位
      Web层框架
      基于Servlet
      处理请求与响应
      属于Spring生态

    核心目标
      请求分发
      参数绑定
      返回响应
      视图解析
      统一异常处理

    核心组件
      DispatcherServlet
        前端控制器
        统一接收请求
        统一调度流程
      HandlerMapping
        查找处理器
        根据请求路径匹配方法
      HandlerAdapter
        适配调用处理器
        屏蔽不同Handler差异
      Controller
        编写业务入口
        接收参数返回结果
      ViewResolver
        解析视图名
        定位页面资源
      View
        页面渲染
        输出响应
      Interceptor
        前后置拦截
        登录校验
        日志统计
      ExceptionResolver
        统一异常处理

    请求处理流程
      用户发送请求
      DispatcherServlet接收
      HandlerMapping找Controller方法
      HandlerAdapter执行目标方法
      Controller处理业务
      返回结果
      结果分流
        返回视图名
          ViewResolver解析
          View渲染页面
        返回数据
          HttpMessageConverter转换
          输出Json或Xml
      响应给客户端

    常用注解
      Controller
        返回视图
      RestController
        返回数据
        等于Controller加ResponseBody
      RequestMapping
        通用映射
      GetMapping
      PostMapping
      PutMapping
      DeleteMapping
      RequestParam
        接收请求参数
      PathVariable
        接收路径参数
      RequestBody
        接收Json请求体
      ResponseBody
        返回Json数据
      RequestHeader
        取请求头
      CookieValue
        取Cookie

    参数绑定
      基本类型
      包装类型
      数组
      集合
      JavaBean
      日期类型
      Json对象
      文件上传
      常见来源
        请求参数
        路径变量
        请求头
        请求体

    返回值处理
      String
        视图名
      ModelAndView
        模型加视图
      对象
        转Json
      List
        转Json数组
      ResponseEntity
        自定义状态码响应头响应体
      void
        直接操作response

    域对象与数据传递
      Model
      ModelMap
      Map
      ModelAndView
      作用域
        request
        session
        application

    视图体系
      JSP
      Thymeleaf
      重定向
        redirect
      转发
        forward
      前后端分离
        多数直接返回Json

    拦截器
      作用
        登录校验
        权限控制
        日志埋点
        性能统计
      方法
        preHandle
        postHandle
        afterCompletion
      对比Filter
        Filter属于Servlet规范
        Interceptor属于SpringMVC

    异常处理
      ExceptionHandler
        局部异常处理
      ControllerAdvice
        全局异常处理
      HandlerExceptionResolver
        底层异常解析机制

    数据转换
      HttpMessageConverter
        Json转换
        字符串转换
        表单数据转换
      类型转换器
        Converter
        Formatter

    上传下载
      MultipartFile
        单文件上传
        多文件上传
      文件下载
        设置响应头
        输出文件流

    高频面试点
      DispatcherServlet作用
      HandlerMapping和HandlerAdapter作用
      Controller和RestController区别
      RequestParam和RequestBody区别
      转发和重定向区别
      Filter和Interceptor区别
      SpringMVC执行流程
      Json返回底层是谁做转换

    与SpringBoot关系
      SpringBoot自动配置SpringMVC
      内嵌Tomcat
      默认消息转换器
      默认静态资源映射
      开发更省配置

注解

mindmap
  root((SpringMVC 常用注解))
    控制器
      Controller
        返回视图
      RestController
        返回Json
        等于Controller加ResponseBody

    请求映射
      RequestMapping
        类上做模块前缀
        方法上做接口映射
      GetMapping
      PostMapping
      PutMapping
      DeleteMapping
      PatchMapping

    参数获取
      RequestParam
        接收查询参数
        适合name=xx
      PathVariable
        接收路径参数
        适合user或id这类路径值
      RequestBody
        接收Json请求体
      RequestHeader
        取请求头
      CookieValue
        取Cookie
      ModelAttribute
        表单对象绑定

    返回响应
      ResponseBody
        返回Json
      ResponseStatus
        指定响应状态码

    结果传递
      RequestAttribute
        取request域数据
      SessionAttribute
        取session域数据

    异常处理
      ExceptionHandler
        当前类异常处理
      ControllerAdvice
        全局增强
      RestControllerAdvice
        全局异常加Json返回

    数据绑定
      InitBinder
        自定义参数绑定
      DateTimeFormat
        时间格式转换
      Valid
        参数校验
      Validated
        分组校验

    跨域与会话
      CrossOrigin
        允许跨域
      SessionAttributes
        往session存模型数据

    高频组合
      前后端分离
        RestController
        GetMapping
        PostMapping
        RequestBody
      传统页面
        Controller
        RequestMapping
      全局异常
        RestControllerAdvice
        ExceptionHandler

Spring

mindmap
  root((Spring 常用注解))
    组件注册
      Component
        通用组件
      Service
        业务层
      Repository
        持久层
      Controller
        控制层
      Scope
        singleton
        prototype
        request
        session
      Lazy
        懒加载

    依赖注入
      Autowired
        按类型注入
      Qualifier
        指定Bean名称
      Resource
        先按名称再按类型
      Value
        注入普通值
        读取配置

    配置类
      Configuration
        配置类
      Bean
        注册第三方Bean
        方法名默认Bean名
      ComponentScan
        扫描组件
      PropertySource
        加载配置文件
      Import
        导入配置类
        导入组件
      ImportResource
        导入xml配置

    生命周期
      PostConstruct
        初始化后执行
      PreDestroy
        销毁前执行
      DependsOn
        指定先初始化谁

    AOP相关
      Aspect
        切面类
      Pointcut
        切点
      Before
        前置通知
      After
        后置通知
      AfterReturning
        返回后通知
      AfterThrowing
        异常后通知
      Around
        环绕通知
      EnableAspectJAutoProxy
        开启AOP

    事务
      Transactional
        开启事务
        作用在类
        作用在方法
      EnableTransactionManagement
        开启事务管理

    异步与定时
      EnableAsync
        开启异步
      Async
        异步方法
      EnableScheduling
        开启定时任务
      Scheduled
        fixedRate
        fixedDelay
        cron

    缓存
      EnableCaching
        开启缓存
      Cacheable
        查缓存
      CachePut
        更新缓存
      CacheEvict
        删除缓存

    环境与配置读取
      ConfigurationProperties
        批量绑定配置
      EnableConfigurationProperties
        开启配置绑定
      Profile
        环境切换
      Primary
        默认优先Bean

    常见组合
      注册Bean
        Component
        Configuration
        Bean
      注入Bean
        Autowired
        Resource
        Qualifier
      配置读取
        Value
        ConfigurationProperties
      横切增强
        Aspect
        Transactional
        Async
        Cacheable

    高频记忆
      Component负责注册
      Autowired负责注入
      Bean负责第三方对象
      Configuration负责配置类
      Transactional负责事务
      Aspect负责切面
      Value负责单个配置
      ConfigurationProperties负责批量配置

SpringBoot

mindmap
  root((SpringBoot 常用注解))
    启动类
      SpringBootApplication
        启动入口
        组合注解
        包含SpringBootConfiguration
        包含EnableAutoConfiguration
        包含ComponentScan
      SpringBootConfiguration
        本质上是Configuration
      EnableAutoConfiguration
        开启自动配置

    配置绑定
      ConfigurationProperties
        批量绑定配置
        适合前缀式配置
      EnableConfigurationProperties
        开启配置类绑定
      ConfigurationPropertiesScan
        扫描配置属性类
      Value
        读取单个配置
      PropertySource
        导入额外配置文件

    条件装配
      ConditionalOnClass
        类存在才生效
      ConditionalOnMissingBean
        容器里没有Bean才生效
      ConditionalOnBean
        有指定Bean才生效
      ConditionalOnProperty
        配置满足条件才生效
      ConditionalOnMissingClass
        类不存在才生效
      ConditionalOnResource
        资源存在才生效
      ConditionalOnWebApplication
        Web应用才生效
      ConditionalOnNotWebApplication
        非Web应用才生效

    自动配置开发
      AutoConfiguration
        自定义自动配置类
      AutoConfigureBefore
        指定先于谁生效
      AutoConfigureAfter
        指定后于谁生效
      ImportAutoConfiguration
        导入自动配置

    环境与装配
      Profile
        区分开发测试生产环境
      Primary
        多个Bean时优先注入
      Lazy
        懒加载
      Import
        导入配置类或组件
      Bean
        注册第三方Bean
      Configuration
        配置类

    Web相关扩展
      ServletComponentScan
        扫描Servlet
        扫描Filter
        扫描Listener

    测试常用
      SpringBootTest
        启动Boot测试环境
      MockBean
        用Mock对象替换Bean

    最该记住
      SpringBootApplication
      EnableAutoConfiguration
      ConfigurationProperties
      ConfigurationPropertiesScan
      EnableConfigurationProperties
      ConditionalOnClass
      ConditionalOnMissingBean
      ConditionalOnProperty
      SpringBootTest
      Profile

Bean

mindmap
  root((Spring Bean))
    Bean是什么
      Spring容器管理的对象
      负责创建
      负责注入
      负责销毁

    Bean来源
      Component
        组件扫描注册
      Service
        业务层Bean
      Repository
        持久层Bean
      Controller
        控制层Bean
      Configuration加Bean
        手动注册第三方对象

    Bean作用域
      singleton
        默认单例
        容器中一份
      prototype
        每次获取新对象
      request
        一次请求一个
      session
        一个会话一个
      application
        整个应用一个

    Bean创建流程
      扫描或解析配置
      BeanDefinition注册
      实例化
      属性注入
      初始化
      放入容器
      后续获取使用

    依赖注入
      Autowired
        按类型注入
      Qualifier
        指定Bean名字
      Resource
        先按名称再按类型
      Value
        注入普通值

    生命周期
      实例化
      依赖注入
      Aware回调
      BeanPostProcessor前置
      初始化方法
        PostConstruct
        afterPropertiesSet
        initMethod
      BeanPostProcessor后置
      使用
      销毁方法
        PreDestroy
        destroy
        destroyMethod

    重点机制
      BeanDefinition
        Bean的元数据
      BeanFactory
        最基础容器
      ApplicationContext
        更高级容器
      单例池
        singletonObjects
      三级缓存
        解决循环依赖
      BeanPostProcessor
        扩展点核心
      FactoryBean
        生产Bean的Bean

    常见注解
      Component
      Bean
      Scope
      Lazy
      Primary
      DependsOn
      PostConstruct
      PreDestroy

    高频问题
      Bean和对象区别
        Bean受Spring管理
      Bean和Component关系
        Component是注册方式
      Bean和FactoryBean区别
        一个是对象
        一个是生产对象的工厂
      单例Bean线程安全吗
        看成员变量是否共享可变
      为什么默认单例
        节省资源
        便于统一管理
      多例Bean会不会注入单例
        可以
        生命周期管理不同
      循环依赖怎么解决
        单例加三级缓存
      构造器循环依赖能解决吗
        不能

    最该记住
      Bean就是交给Spring管理的对象
      默认是singleton
      注册方式主要是Component和Bean
      注入常用Autowired和Resource
      生命周期有初始化和销毁
      扩展核心是BeanPostProcessor
      循环依赖核心是三级缓存

数据库

MySQL

总览

mindmap
  root((MySQL 总览与体系架构))
    定义与本质
      关系型数据库
        基于表组织数据
        通过 SQL 访问
      核心能力
        数据存储
        数据查询
        并发控制
        事务处理
        崩溃恢复
      本质定位
        数据管理系统
        查询与更新平台
        面向 OLTP 场景
    整体分层
      Server 层
        连接管理
          建立连接
          权限校验
        SQL 通用能力
          解析器
          预处理器
          优化器
          执行器
        通用组件
          查询缓存已废弃
          函数与存储过程
          视图与触发器
          日志管理
      存储引擎层
        负责数据落盘
        负责索引组织
        负责事务细节
        常见引擎
          InnoDB
            默认主流
            支持事务
            支持行锁
            支持 MVCC
          MyISAM
            不支持事务
            表锁粒度
            已非主流
    核心架构认知
      逻辑架构
        客户端
        MySQL Server
        Storage Engine
        文件系统
      物理视角
        内存
          Buffer Pool
          各类缓存结构
        磁盘
          表数据
          索引数据
          redo log
          binlog
      关键思想
        分层解耦
        计算与存储协作
        先内存后刷盘
        日志优先
    SQL 执行主链路
      连接阶段
        客户端发起连接
        身份认证
        权限校验
      编译阶段
        解析 SQL
          词法分析
          语法分析
        预处理
          表字段检查
          别名处理
        优化
          选择索引
          决定连接顺序
          生成执行计划
      执行阶段
        调用执行器
        与存储引擎交互
        读取或修改数据
        返回结果
      写入补充
        更新 Buffer Pool
        记录 redo log
        提交写 binlog
    核心功能模块
      存储
        表
        行
        页
        表空间
      查询
        单表查询
        多表连接
        聚合排序
      事务
        原子性
        一致性
        隔离性
        持久性
      并发
        锁机制
        MVCC
      恢复
        redo log
        undo log
        binlog
      复制
        主从复制
        读写分离
    InnoDB 为什么重要
      默认引擎
      面试主战场
      核心优势
        事务可靠
        行级锁
        崩溃恢复
        高并发友好
      学习重点
        索引
        事务
        锁
        日志
        MVCC
    常见工程场景
      Web 应用后端
        用户系统
        订单系统
        内容系统
      业务特征
        高频读写
        强一致需求
        事务更新
      常见搭配
        Java
        SpringBoot
        MyBatis
        Redis
    高频面试点
      MySQL 架构分几层
      Server 层和引擎层区别
      一条 SQL 是怎么执行的
      InnoDB 和 MyISAM 区别
      为什么默认使用 InnoDB
      MySQL 核心组件有哪些
    易错点
      MySQL 不等于 InnoDB
      数据库不只会存数据
        还负责并发控制
        还负责恢复机制
      SQL 执行不只是查表
        还要解析
        还要优化
        还要选择执行计划
      事务不只靠 begin commit
        底层依赖锁与日志
    与后续知识点的联系
      索引体系
        B+树
        回表
        覆盖索引
      事务与 MVCC
        undo log
        Read View
      锁机制
        行锁
        间隙锁
        临键锁
      日志系统
        redo log
        binlog
      性能优化
        explain
        慢 SQL

索引体系

mindmap
  root((MySQL 存储引擎与 InnoDB))
    存储引擎
      是什么
        表的存储实现
        决定索引 锁 事务
      插件式架构
        Server 层处理 SQL
        引擎层负责落盘
      常见引擎
        InnoDB
        MyISAM
    InnoDB 为什么主流
      支持事务
      支持行锁
      支持 MVCC
      支持崩溃恢复
      适合高并发 OLTP
    InnoDB 核心结构
      逻辑结构
        表空间
        段
        区
        页
        行
      重点单位
        页 Page
          默认 16KB
          磁盘管理基本单位
        行 Row
          数据最终存在页里
    索引组织
      聚簇索引
        叶子节点存整行数据
        一张表只有一个
      二级索引
        叶子节点存索引列加主键
        查整行常要回表
      主键设计
        短
        稳定
        递增更优
    内存与性能
      Buffer Pool
        缓存数据页和索引页
        减少磁盘 IO
      脏页
        先改内存
        后续异步刷盘
      核心思想
        读写优先走内存
        日志辅助持久化
    事务基础
      redo log
        保证持久性
        支持崩溃恢复
      undo log
        支持回滚
        支持 MVCC
      锁
        行锁为主
    InnoDB vs MyISAM
      事务
        InnoDB 支持
        MyISAM 不支持
      锁
        InnoDB 行锁
        MyISAM 表锁
      恢复
        InnoDB 强
        MyISAM 弱
      使用
        默认优先 InnoDB
    高频面试点
      什么是存储引擎
      为什么默认 InnoDB
      聚簇索引是什么
      二级索引为什么会回表
      Buffer Pool 有什么作用
      redo 和 undo 分别做什么
    易错点
      MySQL 不等于 InnoDB
      行不是直接独立落盘
      聚簇索引是数据组织方式
      二级索引不直接存整行

SQL执行流程

mindmap
  root((MySQL SQL 执行流程))
    主链路
      连接器
        建立连接
        身份认证
        权限校验
      解析器
        词法分析
        语法分析
        判断 SQL 是否合法
      预处理器
        检查表和列是否存在
        处理别名与 * 展开
      优化器
        选择索引
        决定多表连接顺序
        生成执行计划
      执行器
        调用存储引擎
        按执行计划取数或改数
        返回结果
    查询执行
      select
        先看能否走索引
        再决定扫描方式
        最后回表或直接返回
      核心目标
        少扫描
        少回表
        少排序
    更新执行
      insert update delete
        先定位数据
        再修改内存页
        同时写日志
      关键日志
        undo log
          支持回滚
        redo log
          保证持久性
        binlog
          主从复制
    优化器关注点
      访问方式
        全表扫描
        索引扫描
        范围扫描
      代价选择
        不看语法顺序
        看成本更低方案
      常见影响因素
        索引设计
        数据分布
        查询条件
    执行计划 explain
      核心字段
        type
          看访问效率
        key
          看用了哪个索引
        rows
          预估扫描行数
        Extra
          看是否回表 排序 临时表
      重点判断
        是否命中索引
        是否出现 filesort
        是否出现 using temporary
    慢 SQL 根因
      没走索引
      回表过多
      联合索引没用好
      排序分组代价高
      扫描行数过大
    高频面试点
      一条 SQL 是怎么执行的
      解析器 预处理器 优化器 执行器分别做什么
      优化器为什么会选错索引
      explain 重点看哪些字段
      慢 SQL 一般怎么排查
    易错点
      SQL 写出来的顺序
        不等于真实执行顺序
      建了索引
        不代表一定会走
      explain 好看
        不代表实际一定快
      查询慢
        不一定只是索引问题

事务隔离级别 & MVCC

mindmap
  root((MySQL 事务 隔离级别 与 MVCC))
    事务本质
      是什么
        一组 SQL 的整体执行单元
        要么都成功
        要么都失败
      核心目标
        保证数据正确
        保证并发下结果可信
    ACID
      原子性
        undo log 支持回滚
      一致性
        事务最终目标
        由原子性隔离性持久性共同保证
      隔离性
        锁
        MVCC
      持久性
        redo log
    并发问题
      脏读
        读到别人未提交数据
      不可重复读
        同一事务两次读结果不同
      幻读
        同一事务两次范围读行数变化
    隔离级别
      读未提交
        可能脏读
        隔离性最弱
      读已提交
        解决脏读
        可能不可重复读
      可重复读
        MySQL 默认
        解决不可重复读
        配合临键锁抑制幻读
      串行化
        隔离性最强
        并发性能最差
    MVCC
      是什么
        多版本并发控制
        让读写尽量不互斥
      依赖
        undo log
        Read View
        隐藏字段 trx_id roll_ptr
      解决什么
        快照读下减少加锁
        提升并发读性能
      读取方式
        快照读
          普通 select
          读历史可见版本
        当前读
          select for update
          update delete
          读最新版本并加锁
    Read View
      核心作用
        决定哪个版本对当前事务可见
      本质判断
        版本是不是已提交
        版本是不是属于当前事务
        版本是不是在活跃事务范围内
    锁与 MVCC
      分工
        MVCC 处理读多写少场景
        锁处理当前读和写写冲突
      常见锁
        行锁
        间隙锁
        临键锁
      关键理解
        MVCC 不能替代锁
        当前读仍要加锁
    面试主线
      事务四大特性怎么实现
      四种隔离级别区别
      MySQL 默认隔离级别是什么
      MVCC 原理是什么
      Read View 是什么
      快照读和当前读区别
      可重复读为什么还能防大部分幻读
    易错点
      一致性不是单独机制
      MVCC 主要提升读并发
      可重复读解决的是不可重复读
      幻读常和不可重复读混淆
      普通 select 通常是快照读

锁机制

mindmap
  root((MySQL 锁机制))
    锁的作用
      保证隔离性
      防止并发冲突
      保护当前读与写操作
    锁的主线
      表锁
        锁整张表
        粒度大
        并发低
      行锁
        InnoDB 主流
        粒度小
        并发高
        本质锁索引记录
    行锁类型
      记录锁
        锁住某一条记录
      间隙锁
        锁住一个范围
        防止插入
      临键锁
        记录锁加间隙锁
        MySQL 默认重点
        用来抑制幻读
    共享与排他
      共享锁 S
        可读
        不可改
      排他锁 X
        可读可改
        阻塞其他写
    加锁场景
      当前读
        select for update
        select lock in share mode
        update
        delete
      快照读
        普通 select
        主要靠 MVCC
        通常不加锁
    行锁生效条件
      走索引
        精准命中
        锁范围更小
      不走索引
        可能扫描大量记录
        锁范围变大
      核心理解
        行锁本质依赖索引
    死锁
      是什么
        事务互相等待
        谁也拿不到锁
      常见原因
        访问顺序不一致
        交叉更新多行
      解决
        统一加锁顺序
        小事务快提交
        命中索引减少锁范围
    面试主线
      InnoDB 有哪些锁
      行锁和表锁区别
      记录锁 间隙锁 临键锁区别
      为什么能防幻读
      普通 select 为什么不加锁
      为什么说行锁本质是锁索引
      死锁怎么产生 怎么解决
    易错点
      行锁不等于只锁一行
      不走索引时锁范围会变大
      普通 select 通常不是当前读
      MVCC 和锁是配合关系

日志系统

mindmap
  root((MySQL 日志系统))
    日志主线
      redo log
        保证持久性
        用于崩溃恢复
      undo log
        支持回滚
        支持 MVCC
      binlog
        记录逻辑操作
        用于主从复制
    redo log
      作用
        先记日志
        后刷数据页
      核心思想
        WAL
          先写日志再写磁盘
        随机写转顺序写
      特点
        InnoDB 独有
        物理日志
        记录页修改
      关键价值
        事务提交后即使宕机
        数据也能恢复
    undo log
      作用
        事务失败可回滚
        提供历史版本
      特点
        逻辑日志
        与事务版本链相关
      关键价值
        原子性
        MVCC
    binlog
      作用
        记录数据库变更
        主从复制依据
      特点
        Server 层日志
        逻辑日志
        所有引擎都可用
      常见格式
        statement
        row
        mixed
    三大日志分工
      redo log
        持久性
        崩溃恢复
      undo log
        回滚
        一致性读
      binlog
        复制
        数据恢复
    提交流程
      写 undo log
        留回滚与版本数据
      写 redo log
        进入 prepare
      写 binlog
        记录本次事务
      提交 redo log
        进入 commit
    两阶段提交
      为什么需要
        保证 redo 和 binlog 一致
      核心过程
        redo prepare
        写 binlog
        redo commit
      避免问题
        防止主从不一致
        防止恢复后数据错乱
    崩溃恢复
      依赖 redo log
        已提交事务可恢复
      未提交事务
        借助 undo log 回滚
      核心理解
        redo 负责重做
        undo 负责撤销
    高频面试点
      redo log 和 binlog 区别
      undo log 有什么作用
      WAL 是什么
      为什么需要两阶段提交
      MySQL 宕机后怎么恢复
      三种日志分别解决什么问题
    易错点
      redo log 不负责主从复制
      binlog 不直接保证崩溃恢复
      undo log 不等于持久化日志
      两阶段提交是为了一致性

性能优化 & 表设计

mindmap
  root((MySQL 性能优化 与 表设计))
    优化主线
      少扫描
      少回表
      少排序
      少临时表
    慢 SQL 根因
      没走索引
      扫描行数过多
      回表次数过多
      排序分组代价高
      join 不合理
    explain
      核心字段
        type
          看访问方式
        key
          看用了哪个索引
        rows
          看扫描行数
        Extra
          看排序 临时表 回表
      重点信号
        using filesort
        using temporary
        using index
    索引优化
      核心方向
        命中联合索引
        尽量覆盖索引
        减少索引失效
      设计原则
        高频条件放前面
        区分度高放前面
        不乱建索引
    SQL 优化
      where
        先过滤再取数
      order by
        尽量利用索引有序性
      group by
        尽量减少额外排序
      join
        小表驱动大表
        关联字段建索引
      limit
        深分页代价高
    表设计
      主键
        短
        稳定
        递增更优
      字段
        能小就小
        尽量非空
        避免超大字段滥用
      冗余设计
        适度反范式
        用空间换查询性能
    高频问题
      count
        count主键
        count1
        count星
      分页
        limit 很深会慢
      模糊查询
        前缀匹配可走索引
        %开头常失效
    面试主线
      慢 SQL 怎么排查
      explain 重点看什么
      为什么深分页慢
      为什么回表会慢
      联合索引怎么设计
      表字段为什么不建议太大
    易错点
      有索引不一定快
      索引多会拖慢写入
      explain 好看不等于真实快
      优化不只看 SQL
        也看表结构和数据分布

主从复制 & 高可用 & 分库分表

mindmap
  root((MySQL 主从复制 高可用 与 分库分表))
    主从复制
      作用
        读写分离
        数据备份
        故障切换基础
      核心流程
        主库写 binlog
        从库拉取 binlog
        从库重放日志
      三线程
        主库 dump 线程
        从库 IO 线程
        从库 SQL 线程
    主从延迟
      是什么
        主库已提交
        从库还没跟上
      常见原因
        从库执行慢
        大事务
        锁冲突
        从库压力大
      影响
        读到旧数据
        主从数据短暂不一致
      优化
        拆小事务
        优化 SQL
        提升从库配置
        关键读回主库
    读写分离
      思想
        主库负责写
        从库负责读
      优点
        分担读压力
        提高吞吐
      风险
        主从延迟
        一致性问题
      常见策略
        读主兜底
        延迟敏感请求走主库
    高可用
      核心目标
        主库故障后快速切换
        保证服务连续
      常见方案
        主从加故障转移
        MHA
        Orchestrator
        半同步复制
      关键问题
        新主选举
        数据一致性
        脑裂
    分库分表
      为什么拆
        单表过大
        单库压力过高
        扩展性不足
      拆分方式
        垂直拆分
          按业务拆库
          按字段拆表
        水平拆分
          按数据范围或哈希拆
      核心难点
        分片键设计
        跨库 join
        分布式事务
        分页排序聚合
    分片键
      设计原则
        分布均匀
        高频查询可命中
        尽量稳定
      常见选择
        user_id
        order_id
        tenant_id
      影响
        决定数据路由
        决定热点问题
    分布式 ID
      为什么需要
        分表后主键不能冲突
      常见方案
        数据库自增段
        UUID
        雪花算法
      重点
        全局唯一
        趋势递增更友好
    面试主线
      主从复制流程是什么
      binlog 在复制里做什么
      主从延迟怎么产生
      读写分离有什么问题
      高可用怎么做故障切换
      为什么要分库分表
      水平拆分和垂直拆分区别
      分库分表后有哪些难点
    易错点
      主从复制默认不是强一致
      读写分离不等于高可用
      分库分表不只是性能优化
      分片后很多单机 SQL 能力会变复杂

高频问题

mindmap
  root((MySQL 高频问题排查 与 面试串联))
    排查主线
      先看现象
        查询慢
        写入慢
        锁等待
        主从延迟
      再找位置
        SQL 问题
        索引问题
        锁问题
        日志刷盘
        架构瓶颈
    查询慢
      先查 explain
        是否走索引
        扫描行数是否过大
        是否 filesort
        是否 temporary
      常见根因
        索引失效
        回表过多
        深分页
        join 不合理
      优化方向
        补联合索引
        做覆盖索引
        改写 SQL
    写入慢
      常见根因
        索引太多
        大事务
        批量更新过大
        磁盘刷盘压力
      优化方向
        减少冗余索引
        拆小事务
        分批提交
        避免热点更新
    锁等待与死锁
      看什么
        是否当前读
        是否范围更新
        是否未命中索引
      常见根因
        锁范围过大
        事务太长
        加锁顺序不一致
      优化方向
        命中索引
        统一更新顺序
        快速提交
    主从延迟
      现象
        主库已写
        从库未同步
      常见根因
        大事务
        从库执行慢
        复杂 SQL 重放慢
      处理方向
        拆小事务
        优化 SQL
        关键读走主库
    高并发主线
      读性能
        Buffer Pool 命中
        索引设计合理
        减少随机 IO
      写性能
        redo 顺序写
        控制索引数量
        降低锁冲突
      扩展能力
        读写分离
        分库分表
        缓存配合
    面试串联
      查询为什么快
        索引
        B+树
        覆盖索引
      并发为什么稳
        锁
        MVCC
        隔离级别
      宕机为什么能恢复
        redo log
        undo log
        两阶段提交
      为什么能扩展
        主从复制
        分库分表
    高频追问
      一条 SQL 怎么优化
      为什么走了索引还慢
      为什么可重复读还能防大部分幻读
      死锁怎么产生怎么解决
      主从延迟怎么处理
      分库分表后难点有哪些
    易错点
      排查慢 SQL 不只看索引
      有时瓶颈在锁和 IO
      高并发问题常是组合问题
      单机优化和分布式优化不是一回事

Redis

总览

mindmap
  root((Redis 总览))
    定义与定位
      内存数据库
      Key Value存储
      高性能NoSQL
      支持持久化
      常作缓存中间件
      也可作轻量消息与计数系统

    核心特性
      读写快
        基于内存
        命令执行路径短
      数据结构丰富
        不只是String
        支持多种结构化操作
      支持高并发
        适合热点访问
      支持原子操作
        单命令天然原子性
      支持过期时间
        TTL
        EXPIRE
      支持持久化
        RDB
        AOF
      支持高可用
        主从复制
        哨兵
      支持分布式扩展
        Cluster集群

    为什么快
      内存访问
        少磁盘IO
      单线程命令执行
        避免线程切换
        避免锁竞争
      IO多路复用
        高效处理大量连接
      高效数据结构
        哈希表
        跳表
        压缩结构
      C语言实现
        执行开销低

    数据类型
      五大基础类型
        String
        List
        Hash
        Set
        ZSet
      特殊类型
        Bitmap
        HyperLogLog
        GEO
        Stream
      学习重点
        使用场景
        常用命令
        底层结构
        时间复杂度

    核心机制
      过期机制
        惰性删除
        定期删除
      内存淘汰
        LRU
        LFU
        random
        noeviction
      持久化
        RDB快照
        AOF追加日志
        混合持久化
      事务与脚本
        MULTI EXEC
        Lua
      发布订阅
        Pub Sub
      Pipeline
        减少网络往返

    高可用与扩展
      主从复制
        读写分离
        数据副本
      Sentinel
        故障发现
        自动故障转移
      Cluster
        分片存储
        槽位机制
        横向扩展

    常见应用场景
      缓存
        热点数据缓存
        查询结果缓存
      计数器
        点赞
        浏览量
        库存计数
      排行榜
        ZSet
      分布式锁
        set nx ex
      会话共享
        session存储
      消息队列
        List
        Stream
      去重与签到
        Set
        Bitmap

    典型缓存问题
      缓存穿透
      缓存击穿
      缓存雪崩
      热Key
      大Key
      双写一致性

    优点
      性能高
      使用简单
      数据结构丰富
      扩展方案成熟
      社区生态强

    局限
      基于内存
        成本高
        容量受限
      不适合复杂查询
      不适合强事务核心业务
      持久化能力弱于关系型数据库
      缓存与数据库存在一致性问题

    与MySQL关系
      MySQL
        持久存储
        复杂查询
        强一致业务
      Redis
        高速访问
        热点数据
        临时状态
      常见组合
        MySQL做主存储
        Redis做缓存层

    面试主线
      Redis是什么
      Redis为什么快
      Redis有哪些数据类型
      Redis怎么做持久化
      Redis怎么保证高可用
      Redis常见缓存问题有哪些
      Redis和MySQL如何配合

五大数据结构

mindmap
  root((Redis 五大基础数据结构))
    String
      本质
        字符串对象
        最常用类型
        可存字符串数字二进制
      常用命令
        set
        get
        mget
        incr
        decr
        append
        setnx
        setex
      底层
        SDS
          记录长度
          减少重复计算长度
          二进制安全
      典型场景
        缓存对象
        计数器
        分布式锁
        共享标记位
      面试点
        为什么适合计数
        为什么是二进制安全
        setnx加expire为什么常一起说

    List
      本质
        有序可重复
        双端链式操作
      常用命令
        lpush
        rpush
        lpop
        rpop
        lrange
        blpop
      底层
        quicklist
          链表加压缩列表思想
      典型场景
        消息队列
        最新消息列表
        栈
        队列
      面试点
        为什么适合双端操作
        为什么现在底层不是单纯双向链表
        和Stream做消息队列区别

    Hash
      本质
        键值对集合
        适合存对象
      常用命令
        hset
        hget
        hmget
        hgetall
        hincrby
        hexists
      底层
        hashtable
        listpack
          小对象更省内存
      典型场景
        用户信息
        商品属性
        配置项
      面试点
        和String存对象区别
        为什么更适合存部分字段
        什么时候会从紧凑结构转成哈希表

    Set
      本质
        无序唯一集合
        自动去重
      常用命令
        sadd
        srem
        smembers
        sismember
        scard
        sinter
        sunion
        sdiff
      底层
        hashtable
        intset
          整数集合时更省空间
      典型场景
        去重
        共同关注
        标签系统
        抽奖候选池
      面试点
        为什么能去重
        交并差集怎么做
        intset何时升级

    ZSet
      本质
        有序唯一集合
        元素带分数score
      常用命令
        zadd
        zrem
        zrange
        zrevrange
        zscore
        zrank
        zincrby
      底层
        skiplist
        hashtable
      典型场景
        排行榜
        延时队列
        权重排序
        范围查询
      面试点
        为什么用跳表
        为什么还要配哈希表
        和Set区别
        和Heap区别

    横向对比
      String
        最简单
        最通用
      List
        强在双端操作
      Hash
        强在对象字段存储
      Set
        强在去重与集合运算
      ZSet
        强在排序与范围查询

    选型思路
      只存一个值
        String
      存对象多个字段
        Hash
      需要先进先出或双端操作
        List
      需要去重
        Set
      需要排行榜或按分数排序
        ZSet

    高频易错点
      String不只是字符串
      List允许重复
      Set无序且唯一
      ZSet唯一的是元素不是score
      Hash适合局部字段修改
特殊数据结构
mindmap
  root((Redis 特殊数据结构))
    Bitmap
      本质
        位数组
        按bit存0和1
        底层依赖String
      常用命令
        setbit
        getbit
        bitcount
        bitop
      核心特点
        极省空间
        适合大规模状态标记
        支持位运算
      典型场景
        用户签到
        在线状态
        活跃统计
        布尔标记集合
      面试点
        为什么节省内存
        底层为什么属于String
        和Set做签到对比

    HyperLogLog
      本质
        基数统计
        统计去重数量
        不是精确去重集合
      常用命令
        pfadd
        pfcount
        pfmerge
      核心特点
        占用空间极小
        统计值有误差
        适合海量去重计数
      典型场景
        UV统计
        独立访客数
        搜索词去重计数
      面试点
        为什么省内存
        为什么有误差
        为什么不能拿出具体元素

    GEO
      本质
        地理位置集合
        存经纬度
        底层依赖ZSet
      常用命令
        geoadd
        geopos
        geodist
        georadius
        geosearch
      核心特点
        支持附近的人
        支持距离计算
        支持范围搜索
      典型场景
        附近门店
        附近骑手
        LBS位置服务
      面试点
        为什么底层是ZSet
        如何支持距离范围查询
        和普通经纬度表查询区别

    Stream
      本质
        消息流
        可持久化消息队列
        支持消费组
      常用命令
        xadd
        xrange
        xread
        xgroup
        xreadgroup
        xack
      核心特点
        消息可回溯
        支持多消费者
        支持消费确认
        比List更像正式消息队列
      典型场景
        异步任务
        消息分发
        日志流处理
      面试点
        和List做队列区别
        消费组有什么用
        为什么能避免消息丢失一部分问题

    特殊结构对比
      Bitmap
        强在状态压缩
      HyperLogLog
        强在海量去重计数
      GEO
        强在地理位置搜索
      Stream
        强在消息流与消费组

    选型思路
      只关心某状态是否存在
        Bitmap
      只关心去重后的数量
        HyperLogLog
      只关心附近位置与距离
        GEO
      需要可靠消息流
        Stream

    高频易错点
      Bitmap底层不是独立新结构
      HyperLogLog不能精确去重
      GEO底层本质是ZSet能力扩展
      Stream比List更适合消息队列

持久化

mindmap
  root((Redis 持久化))
    作用
      宕机后恢复数据
      降低内存数据丢失风险
      支撑主从复制与重启恢复

    持久化方案
      RDB
        本质
          某一时刻数据快照
        触发方式
          save
          bgsave
          save规则自动触发
        优点
          文件紧凑
          恢复速度快
          适合备份
        缺点
          有时间点丢数据风险
          fork开销大
        适用场景
          容忍少量数据丢失
          追求恢复速度
      AOF
        本质
          记录写命令日志
        写回策略
          always
          everysec
          no
        重写机制
          bgrewriteaof
          压缩冗余命令
        优点
          数据更完整
          可读性更强
        缺点
          文件更大
          恢复更慢
        适用场景
          更看重数据安全
      混合持久化
        本质
          RDB快照加增量AOF命令
        特点
          兼顾恢复速度
          兼顾数据完整性

    RDB机制
      执行流程
        fork子进程
        子进程生成快照文件
        写入临时文件
        替换旧RDB
      核心点
        主进程继续处理请求
        借助写时复制
      高频问题
        为什么用bgsave
        fork会带来什么开销
        写时复制是什么

    AOF机制
      执行流程
        写命令追加到AOF缓冲区
        按策略刷盘
        重启时重放命令恢复数据
      重写流程
        fork子进程
        根据当前内存数据重写新AOF
        合并重写期间增量命令
        替换旧AOF
      高频问题
        AOF为什么会膨胀
        重写和刷盘区别
        everysec为什么常用

    两者对比
      数据安全
        AOF更强
      恢复速度
        RDB更快
      文件大小
        RDB更小
      可读性
        AOF更好
      性能影响
        RDB适合低频快照
        AOF取决于刷盘策略

    恢复流程
      只有RDB
        加载RDB恢复
      只有AOF
        重放AOF恢复
      同时开启
        优先使用AOF
      混合持久化
        先加载RDB部分
        再执行增量命令

    选型建议
      只要快速备份恢复
        RDB
      更关注数据少丢失
        AOF everysec
      线上常见
        RDB加AOF
        或混合持久化

    高频面试点
      RDB和AOF区别
      bgsave原理
      bgrewriteaof原理
      为什么AOF更安全
      为什么RDB恢复更快
      AOF重写会阻塞吗
      RDB和AOF如何选择

    易错点
      RDB不是实时持久化
      AOF重写不是读取旧AOF简单压缩
      AOF更安全也不是绝对不丢数据
      Redis持久化不能替代数据库主存储

主从复制 & 哨兵

mindmap
  root((Redis 主从复制与哨兵))
    主从复制
      作用
        数据副本
        读写分离
        故障恢复基础
      基本结构
        Master
          负责写
        Slave
          负责同步数据
          可分担读压力
      复制流程
        建立连接
        身份确认
        全量复制
        命令传播
      全量复制
        slave发送psync
        master返回runid和offset
        master执行bgsave
        发送RDB给slave
        再发送缓冲区增量命令
      增量复制
        基于复制偏移量
        继续同步缺失命令
      核心机制
        replication id
        offset偏移量
        复制积压缓冲区
      优点
        提升读性能
        提高可用性
      问题
        主节点压力更大
        复制延迟
        数据不强一致
      高频点
        全量复制过程
        增量复制依赖什么
        复制积压缓冲区作用
        为什么主从有延迟

    哨兵Sentinel
      作用
        监控主从节点
        自动故障转移
        通知客户端新主节点
      核心功能
        监控
        通知
        自动故障转移
        配置中心
      监控对象
        Master
        Slave
        其他Sentinel
      故障判断
        主观下线
          单个Sentinel认为节点异常
        客观下线
          多个Sentinel达成共识
      故障转移
        选出leader Sentinel
        选新Master
        让其他Slave复制新Master
        通知客户端
      新主选择依据
        优先级priority
        复制偏移量
        run id
      优点
        自动切主
        提高可用性
      局限
        不能解决数据分片
        故障切换期间有短暂不可用
        仍可能丢少量数据
      高频点
        主观下线和客观下线区别
        哨兵如何选leader
        新主如何选举
        哨兵和Cluster区别

    主从加哨兵关系
      主从复制
        负责数据同步
      哨兵
        负责监控与切换
      组合意义
        有副本
        能自动恢复

    常见问题
      读写分离
        主写从读
      复制延迟
        读从库可能读到旧数据
      脑裂
        网络分区导致短时双主风险
      数据丢失
        主节点未同步完就宕机
      故障恢复
        依赖哨兵自动切换

    对比Cluster
      主从加哨兵
        解决高可用
        不解决海量分片
      Cluster
        高可用加分片
        更适合大规模集群

    最该记住
      主从复制负责同步数据
      全量复制先传RDB再补增量命令
      增量复制依赖offset和积压缓冲区
      哨兵负责监控和自动故障转移
      主观下线是单点判断
      客观下线是多数派判断
      哨兵适合高可用
      Cluster适合高可用加分片

cluster集群

mindmap
  root((Redis Cluster集群))
    核心定位
      分布式集群方案
      高可用加分片
      解决单机容量瓶颈
      解决单机并发瓶颈
      支持自动故障转移

    核心目标
      数据分片
      横向扩展
      高可用
      去中心化

    集群结构
      Master节点
        负责槽位数据
        负责读写请求
      Slave节点
        复制对应Master
        Master故障时可晋升
      多主多从
        一个集群多个Master
        每个Master可挂多个Slave

    数据分片
      槽位机制
        总共16384个槽
        每个Master负责一部分槽
      路由规则
        key先算CRC16
        再对16384取模
        定位到具体槽
      好处
        分片规则固定
        迁移更方便
        管理比一致性哈希更直接

    请求路由
      客户端访问节点
      节点判断槽是否归自己
      如果不归自己
        返回MOVED
        告知新节点
      槽迁移期间
        可能返回ASK
      客户端
        需要感知集群
        维护槽位与节点映射

    故障转移
      监控方式
        节点间互相通信
        Gossip协议
      故障判断
        主观下线
        客观下线
      切换流程
        某个Master失联
        对应Slave参与选举
        晋升新Master
        接管原槽位
      结果
        提升高可用
        减少人工介入

    集群通信
      Gossip
        传播节点状态
        传播槽位信息
        传播故障信息
      ping pong
        心跳检测
      去中心化
        没有单独中心节点
        节点共同维护集群状态

    扩缩容
      扩容
        新节点加入
        分配槽位
        槽迁移
      缩容
        迁出槽位
        下线节点
      特点
        以槽为单位迁移
        不必整体重分布

    限制与注意点
      多key操作限制
        尽量落同一槽
      事务限制
        跨槽事务受限
      Lua限制
        脚本内涉及key最好同槽
      批量操作限制
        跨槽操作可能失败
      热点问题
        热key仍会压垮单节点

    HashTag
      作用
        让多个key落同一槽
      写法
        大括号内内容参与槽计算
      场景
        多key事务
        多key批量操作
        关联数据放同槽

    优点
      支持分片
      支持高可用
      去中心化
      可横向扩展
      自动故障转移

    局限
      架构更复杂
      客户端要支持集群
      跨槽操作不方便
      仍可能有数据丢失
      热key问题不会自动消失

    对比主从加哨兵
      主从加哨兵
        重点是高可用
        不解决分片
      Cluster
        高可用加分片
        更适合大规模数据

    高频面试点
      为什么是16384个槽
      Cluster如何分片
      MOVED和ASK区别
      集群如何故障转移
      Gossip有什么作用
      Cluster和哨兵区别
      为什么跨槽操作受限
      HashTag有什么用

    最该记住
      Cluster等于分片加高可用
      数据按16384个槽分布
      Master负责槽
      Slave负责副本和故障切换
      节点间靠Gossip通信
      客户端要能处理MOVED和ASK

缓存与分布式锁

mindmap
  root((Redis 缓存问题与分布式锁))
    缓存问题
      缓存穿透
        本质
          请求的数据不存在
          缓存和数据库都查不到
        后果
          请求直打数据库
          数据库压力暴增
        解决
          缓存空值
          布隆过滤器
          参数校验
      缓存击穿
        本质
          热点Key失效瞬间
          大量并发同时查数据库
        后果
          瞬时流量压垮数据库
        解决
          互斥锁
          逻辑过期
          热点Key永不过期
      缓存雪崩
        本质
          大量Key同一时间失效
          或Redis整体故障
        后果
          大量请求回源数据库
          服务雪崩
        解决
          过期时间加随机值
          多级缓存
          Redis高可用
          限流降级
      热Key
        本质
          某个Key访问量极高
        问题
          单节点压力过大
        解决
          本地缓存
          多副本分摊
          热点预热
          拆分Key
      大Key
        本质
          单个Key占用内存过大
          单次操作数据量过大
        问题
          删除阻塞
          网络传输慢
          主从同步压力大
        解决
          拆分存储
          避免一次性取全量
          unlink异步删除
          定期扫描治理
      双写一致性
        本质
          数据库和缓存同时存在
          更新时可能不一致
        常见方案
          先更新数据库再删缓存
          延时双删
          订阅Binlog异步删缓存
        难点
          并发竞争
          删除失败
          短暂不一致

    缓存更新策略
      Cache Aside
        读
          先查缓存
          未命中查数据库
          再写缓存
        写
          先更新数据库
          再删除缓存
        优点
          最常用
          简单实用
      读写穿透
        应用少见
      写回
        适合低一致性场景

    分布式锁
      作用
        控制共享资源并发访问
        保证同一时刻一个线程执行业务
      常见场景
        库存扣减
        定时任务防重
        幂等控制
        缓存重建互斥
      基础实现
        set nx ex
          nx表示不存在才设置
          ex表示加过期时间
        value
          唯一标识线程或请求
      正确解锁
        先比对value
        再删除Key
        保证只能删自己的锁
        推荐Lua脚本原子执行
      为什么要过期时间
        防止持锁线程宕机
        避免死锁

    分布式锁问题
      锁误删
        场景
          锁过期后被别人拿到
          原线程再去删锁
        解决
          value唯一标识
          Lua校验后删除
      锁过期
        场景
          业务执行时间超过TTL
        解决
          合理设置超时时间
          续期机制
          看门狗
      可重入
        问题
          同线程重复加锁会卡住自己
        解决
          记录线程标识和重入次数
          Redisson支持可重入
      主从切换锁丢失
        场景
          主节点刚加锁未同步到从节点就宕机
        后果
          新主不知道旧锁
          可能多线程同时拿锁
        解决
          提升一致性要求
          使用RedLock思路
          接受Redis锁并非绝对强一致
      阻塞等待
        问题
          获取失败后如何等待
        方案
          自旋重试
          sleep后重试
          阻塞队列配合

    Redisson
      优势
        封装完善
        支持可重入
        支持续期
        支持公平锁读写锁联锁
      看门狗
        自动续期
        防止业务未执行完锁先过期
      常见对象
        RLock
        ReadWriteLock
        MultiLock

    面试主线
      什么是缓存穿透
      击穿和雪崩区别
      热Key和大Key问题
      为什么更新数据库后删缓存
      分布式锁为什么用set nx ex
      为什么解锁要校验value
      Lua脚本解决什么问题
      Redis分布式锁有哪些风险
      Redisson看门狗是什么

    最该记住
      穿透查不到
      击穿热点失效
      雪崩大量失效或Redis宕机
      更新策略优先更新数据库再删缓存
      Redis分布式锁核心是set nx ex
      解锁必须校验唯一值
      Lua保证校验加删除原子性
      Redis锁高性能但不是绝对强一致

删除策略与淘汰机制

mindmap
  root((Redis 删除策略与内存淘汰机制))
    过期机制
      作用
        控制缓存生命周期
        释放无效内存
        支撑TTL业务场景
      常用命令
        expire
        pexpire
        expireat
        ttl
        pttl
        persist

    删除策略
      惰性删除
        含义
          访问Key时再检查是否过期
        优点
          CPU开销小
        缺点
          可能长期占内存
      定期删除
        含义
          定时随机抽查部分过期Key
        优点
          平衡CPU与内存
        缺点
          不保证立刻删光
      定时删除
        理论上最及时
        Redis未采用
        原因
          定时器太多
          CPU压力大

    Redis实际做法
      组合策略
        惰性删除
        定期删除
      设计思路
        不追求绝对实时
        追求性能与内存平衡

    过期Key处理流程
      Key被访问
        检查是否过期
        过期则删除并返回不存在
      后台周期任务
        随机抽取设置过期时间的Key
        删除已过期Key
        继续循环或停止

    为什么不用只惰性删除
      问题
        很多过期Key一直不访问
        内存会被白白占用

    为什么不用只定期删除
      问题
        可能删不及时
        访问时仍需兜底检查

    内存淘汰机制
      触发前提
        设置了maxmemory
        当前内存达到上限
      目标
        在内存不足时决定淘汰谁
      注意
        淘汰和过期不是一回事
        过期是时间到了
        淘汰是内存不够了

    淘汰策略分类
      noeviction
        不淘汰
        写请求直接报错
      volatile系列
        只从设置了过期时间的Key里淘汰
        volatile random
        volatile ttl
        volatile lru
        volatile lfu
      allkeys系列
        所有Key都可能被淘汰
        allkeys random
        allkeys lru
        allkeys lfu

    常见策略理解
      LRU
        最近最少使用
        更适合时间局部性场景
      LFU
        最不经常使用
        更适合长期热点场景
      random
        实现简单
        效果一般
      ttl
        优先淘汰更快过期的Key

    高频对比
      LRU对比LFU
        LRU看最近是否访问
        LFU看访问频率高低
      volatile对比allkeys
        volatile只淘汰过期Key集合
        allkeys全体都可能淘汰
      过期删除对比淘汰
        过期是Key到时间自然失效
        淘汰是内存不够被迫清理

    适用场景
      纯缓存
        常用allkeys lru
        常用allkeys lfu
      混合存储
        常用volatile lru
        常用volatile lfu
      严格不允许淘汰
        noeviction

    常见问题
      为什么Redis不保证过期Key立刻删除
        为了控制CPU开销
      为什么会有过期Key没删掉
        定期删除是随机抽查
      内存满了一定先删过期Key吗
        不一定
        要看是否触发访问或后台扫描
      生产环境常用什么策略
        allkeys lru
        allkeys lfu
        视业务而定

    面试主线
      Redis过期Key怎么删除
      惰性删除和定期删除区别
      为什么不用定时删除
      Redis内存满了怎么办
      LRU和LFU区别
      volatile和allkeys区别
      过期删除和内存淘汰区别

    最该记住
      Redis采用惰性删除加定期删除
      过期删除解决无效Key
      内存淘汰解决内存不足
      LRU看最近访问
      LFU看访问频率
      纯缓存场景常考虑allkeys lru或allkeys lfu