ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

知识总结 - 问题大纲

知识总结 - 问题大纲 文章目录网络系统项目基础知识数据结构与算法线程与并发JVMGC类加载SpringSpringBoot设计模式实践MybatisMySQL分布式RedisNettyNginxFeignNacosxxl-job消息中间件DubboZookeeperSpringCloud网络系统项目Linux常用命令 TCP三次握手四次挥手(SYN、ACK、FIN3种标志位 序号 确认号) TCP和UDP区别(有连接/无连接 可靠/不可靠 传输效率低/高) TCP可靠性机制(数据分片/收到确认/超时重发/流量控制/乱序重排/数据校验) 滑动窗口(提高效率/流量控制) TCP、IP通俗理解(传输层网络层)(物理链路网络传输会表应) select、poll和epoll区别(FD存储结构:数组/动态数组/红黑树就绪链表 FD数量:有限制/无限制/无限制 操作方式:遍历O(n)/遍历O(n)/回调O(1) epoll内存零拷贝技术) BIO、NIO、AIO(阻塞性:同步阻塞/同步非阻塞/异步非阻塞 方式:单连接单线程/多连接单线程/系统回调 Centos7JDK1.8 NIO使用epoll) NIO中三大组件及其作用(Channel数据双向传输/Buffer数据存储读写/Selector监听连接) 零拷贝是什么(减少数据在内存中拷贝次数提高效率) (read/write 4次用户态内核态切换 4次拷贝) (mmap/write 4次用户态内核态切换 3次拷贝) (sendfile 2次用户态内核态切换 3|2次拷贝) 成就感、挑战性、亮点项目 项目及负责的模块 线上问题处理方式 Maven中Package与Install HTTPS如何保证安全传输(请求证书/交互秘钥/加密数据) 浏览器发出请求到收到响应经历哪些过程(域名解析/TCP建链/发送HTTP请求/服务器响应/收到返回/页面渲染/TCP断链/) 跨域请求是什么(访问不同源的服务 协议/域名/端口) 如何解决(修改请求头/nginx代理/后端转发) DelayQueue、RocketMQ、ScheduledThreadPoolExecutor实现延时任务优劣(系统重启任务丢失 大量任务占内存) 延时任务调度器(RocketMQ5.0延时消息 消息定义/工具类/读线程/执行线程池) 分布式高并发设计方案(整体结构 单体结构 接口层面) (整体结构:DNS/四层负载均衡/七层负载均衡) (单体结构:服务拆分/动静分离/数据应用分离/读写分离/分库分表/缓存) (接口层面:sql/异步/线程池) 好代码个人体会(可读性可维护性:定义见意义/方法拆分/类拆分/) 单点登录解决方案(1次身份认证多个系统共用 共享Session/共享加密有效期token)基础知识对Java的理解(语言特性:面向对象/3特性/平台无关性/GC 生态特性:类库/框架/中间件) 面向对象与三特性(封装/继承/多态) 重载与重写(单个类中方法名相同参数列表不同/父子类方法重写实现多态) JDK JRE JVM 抽象类/接口类(单继承/多实现 行为定义/提取共性提高复用) 反射(原理与常用方法) (原理:对于任意类虚拟机中都维护1个对应的Class对象在程序运行过程中可以通过Class对象获取实例的任意方法和变量并执行其方法) (常用方法:getField/getFields/getDeclaredField/getDeclaredFields/getMethod/getMethods/getDeclaredMethod/getDeclaredMethods) 复制(深拷贝和浅拷贝) Java异常体系(分类) final(修饰类则类不可继承/修饰方法则方法不可重写/修饰变量则变量不可修改) 和equals区别(:基本类型比值/引用类型比地址 equals:默认为/可重写) hashCode和equals(hashCode:基于内存地址生成 equals为true则hashCode相等 反之不一定) String、StringBuffer、StringBuilder区别(可变性:不可变/可变/可变 安全性:安全/安全/非安全) List和Set区别(元素唯一性:否/是 ) LinkedList、ArrayList、Vector区别(底层结构:链表/数组/数组 安全性:不安全/不安全/安全 队列//) HashMap和HashTable区别(非安全/安全 禁止Null键Null值/允许1个Null键多个Null值 数组链表/数组链表红黑树) HashMap扩容过程/扩容原理(1.7新数组移动元素/1.8新数组链表直接移动元素红黑树需要统计并按条件转链表) HashMap的put方法过程(根据key计算下标-1.7条件扩容头插法入链表-1.8尾插法入链表转红黑树条件扩容) HashMap的容量和扩容为什么是2的次幂(高效运算:数组下标计算取模-按位与hash(capacity-1)-位运算效率高 减小hash碰撞:capacity-1111 扩容时索引计算高效:新索引旧索引0/旧容量) Java1.7/1.8中HashMap区别(数组链表/数组链表红黑树 头插法\尾插法 先扩容后插入\先插入后扩容) 泛型中extends和super区别(extends/包括T和T的子类/上界安全读 super/T和T的父类/下界安全写) String对象如何修改值但不修改地址(反射方式) String.intern方法(将字符串对象添加到字符串常量池并返回池中对应的引用) IntegerCache的数据范围(-128~127) List有哪些实现类(ArrayList/LinkedList/Vector/Stack/CopyOnWriteArrayList) Object中方法(equals:判等 hashCode:哈希码 toString:类名hash clone:拷贝对象 wait:线程等待 notify:线程唤醒 notifyAll: getClass:Class对象) Object.clone(浅拷贝 深拷贝需实现Cloneable接口并重写clone方法) Object.toString(类型名称hash值) String为什么不可改变(private final char value[]) 接口类多继承 普通类单继承 接口类多实现 基础数据类型(byte short int long float double char boolean) 为什么使用包装类(面向对象/提供操作方法和常用对象/适配泛型集合/适配序列化) HashMap为什么不使用二叉树(二叉树极端情况退化为链表/平衡二叉树插入删除效率低) HashMap、ConcurrentHashMap的k/v是否允许null值(单Null键多Null值/不允许) (如果vnull则无法判断键是否存在多线程环境中存在很大的不稳定性) Java1.7/1.8中ConcurrentHashMap区别 (1.7:基于分段锁实现每个锁对应1个HashMap/操作时先获取锁) (1.8:基于SynchronizedCAS实现/操作头结点使用CAS操作后继节点则获取头结点锁) ConcurrentHashMap原理及其扩容原理 (1.7:每个分段锁内部扩容-扩容过程与该版本HashMap类似) (1.8:put完成后判断条件是否扩容-支持多线程扩容-生成新数组-将原数组分组每组分给不同的线程扩容) ConcurrentHashMap如何保证线程安全(分段锁Segment/CASsynchronized) CopyOnWriteArrayList底层原理(底层是数组写操作会加锁并复制新数组读操作基于原始数组-完成更新array变量-适合读多写少场景-可能读不到最新数据) ThreadLocal原理与使用场景(线程内部缓存/Thread中ThreadLocalMap变量key为ThreadLocal对象value为缓存值/使用后需手动remove否则造成内存泄漏) ThreadLocal内存泄漏原因(使用后需手动remove) 内存泄漏和内存溢出区别(该回收而未回收/申请内存超过系统可用资源)数据结构与算法图的深度遍历与广度遍历 二叉搜索树和平衡二叉树区别 强平衡二叉树与弱平衡二叉树区别 快排算法线程与并发进程和线程的区别(定义:进程是程序的执行过程是系统进行资源调度的基本单位/线程是进程的执行单元是CPU调度的基本单位 资源:进程间资源互相隔离/进程内线程共享通信资源) 线程生命周期与状态(创建/就绪/运行/阻塞/死亡) 线程安全如何理解(对于内存中对象任何时候调用对象的方法都能获取正确的结果则线程安全) 守护线程如何理解(保姆线程服务非守护线程例GC线程) 如何开启线程(继承Thread/实现Runnable/实现Callable/线程池) 如何保证线程安全(synchronized/ReentrantLock/线程安全工具类) 并发、串行和并行区别(同一多个任务互相影响只有1个任务运行/同1时刻只有1个任务运行/同1时刻多个任务运行) 并发三特性(有序性:程序执行顺序与代码顺序一致/可见性:线程修改共享变量后其他线程可立即感知/原子性:一组操作必须全部成功或全部失败不存在中间态) volatile特性及其原理(有序性:禁止指令重排序内存屏障指令/可见性:强制操作主内存内存屏障指令) Synchronized特性及其原理(有序性:禁止指令重排序内存屏障指令/可见性:强制操作主内存内存屏障指令/原子性:锁Monitor) volatile和Synchronized区别(两性/三性) volatile能否保证线程安全(否) Synchronized锁机制(膨胀方向实现方式适合场景) (膨胀方向:偏向锁/轻量级锁/重量级锁) (实现方式:偏向锁线程ID/锁记录指针/Monitor) (适用场景:单一线程重复加锁/少量线程交替加锁/多线程并发) 自旋锁:加锁未成功-自旋等待-加锁(无线程阻塞和唤醒过程效率高) Synchronized放在静态方法和普通方法上的区别(锁对象:Class对象/当前实例 作用范围:所有调用/实例内调用) Thread和Runable区别(类/接口 提供方法sleepjoininterruptyield/{}) sleep和wait区别(休眠/阻塞入等待队列 自动唤醒/被唤醒 {}/结合Synchronized使用 释放CPU不释放锁/释放CPU和锁) join和yield区别(阻塞等待其他线程/表示可释放CPU) LockSupport.park、LockSupport.unpark和wait、notify的区别(JUC类/Object方法 无顺序限制/先wait后notifySynchronized) notify和notifyAll区别(随机唤醒1个等待线程/唤醒所有等待线程) interrupt机制(协作式线程终止机制) start和run区别(启动线程/线程内容) 如何给run方法传参(构造方法传参/成员变量传参) 如何实现处理线程返回值(CallableFutureTask) CompletableFuture使用场景(任务并行处理/链式异步编排/任务结果合并) CAS简述(3参数:内存位置/预期原值/新值 应用场景:原子类/线程安全集合 优点:效率高/无死锁 缺点:ABA问题/带版本号原子类) AQS简述(锁公共功能抽象:锁资源定义/加锁失败入等待队列/解锁唤醒等待线程/线程唤醒重新加锁) AQS哪些是共享锁/排它锁(读锁/Semphore/countDownLatch 重入锁/写锁) Synchronized和ReentrantLock区别(关键字/类 自动加解锁/手动加解锁 JVM层面的锁/API层面的锁 非公平锁/非公平锁公平锁 基于对象头实现/基于int变量实现 锁升级/{}) 如何实现可重入(锁变量1) ReentrantLock公平锁和非公平锁底层实现(默认非公平锁参数为true则为公平锁) ReentrantLock中lock和trylock区别(行为:加锁失败阻塞等待/加锁失败立即返回或超时返回) ReentrantLock公平锁加解锁过程 (获取当前线程 - 若state变量为0且无等待线程 - 则使用CAS获取锁并设置锁持有者 - 若锁为本线程持有 - 则state加1重入 - 其他情况则加锁失败入等待队列) (若锁为本线程持有 - state减1释放锁 - 若state为0返回true反之返回false) ReentrantLock非公平锁加锁过程 (首先使用CAS获取锁 - 失败继续 - 获取当前线程 - 若state变量为0 - 则使用CAS获取锁并设置锁持有者 - 若锁为本线程持有 - 则state加1重入 - 其他情况则加锁失败入等待队列) 加锁失败(addWaiter插入等待队列 - acquireQueued队列中实现阻塞) addWaiter(封装新Node - 获取tail - tail不为空则添加Node到尾部 - CAS操作更新tail - tail为空或更新tail失败则以死循环方式添加到等待队列 注:头结点为虚拟节点) acquireQueued(死循环{ [a]若为次节点则加锁-加锁成功则删除当前节点-加锁失败则重复加锁 [b]若为第3至n节点则查找有效前驱节点并修改其waitStatus-1 - 然后park }) ReentrantLock等待队列为什么使用双向队列(方便查找前驱节点:向前查找删除无效节点/唤醒次节点加锁 ) countDownLatch使用场景(多任务完成后汇总) CountDownLatch和Semphore区别及底层原理(计数器/信号量 new时创建n个锁-await挂起-countDown1次去掉1个锁-去掉n个锁则唤醒线程/new时创建n个许可证-加锁成功获取许可证-失败阻塞-解锁释放许可证 任务拆分汇总/限流思想) 3个线程 如何实现同时执行/顺序执行/交替执行 (同时执行:CountDownLatch) (顺序执行:Thread.join()/CompletableFuture/单一线程池顺序提交任务) (交替执行:ReentrantLockCondition共享变量/synchronizedwait/notify共享变量/Semaphore) 用多线程模拟死锁(不能使用Thread.sleep)(重入锁 信号量 Timer TimeUnit 使用空循环代替延时) 简述线程池原理(组成提交任务逻辑) (组成:核心线程/非核心线程/工作队列) (提交任务时逻辑:线程数小于核心线程数则创建核心线程-线程数等于核心线程数则提交到等待队列线程数等于核心线程数且等待队列满载则创建非核心线程-线程数等于最大线程数则执行拒绝策略-非核心线程空闲指定时间销毁) (拒绝策略:抛异常/调用线程执行任务/抛弃新任务/抛弃旧任务) 线程池7大参数(核心线程数/最大线程数/线程空闲时间/时间单位/工作队列/线程工厂/拒绝策略) 为什么使用线程池(3优点:提高线程利用率/提高任务响应速度/提高线程的可管理性) FixedThreadPool阻塞队列是什么(定长线程池/LinkedBlockingQueue/无界队列) 线程池中阻塞队列作用(缓存任务/无任务阻塞线程/有任务唤醒线程) 线程池中线程复用原理(线程和任务解耦/Worker中死循环-从工作队列中获取Runable-执行Runable的run方法) 为什么先入队列后创建非核心线程(创建线程耗费性能) FutureTask如何同时支持Runnable和Callable(RunnableAdapter类-实现Callable-包含Runnable变量) 不建议使用Executor建立线程池(存在无界参数易造成内存溢出) (newFixedThreadPool:定长线程池/无界队列) (newSingleThreadExecutor:单一线程池/无界队列) (newCachedThreadPool:缓存线程池/最大线程数无限) 如何查看线程死锁(服务死锁:jstack查看栈 数据库死锁:查询是否锁表/查看所有进程/查看等待锁的事务/查看获取锁的事务) show OPEN TABLES where In_use 0; show processlist; SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; 线程通讯4方式(voliteSynchronized/AQS同步器/RedisMQNetty等组件/Socket) Java死锁如何避免 (死锁原因:线程A获取锁1等待锁2-线程B获取锁2等待锁1-形成死锁) (死锁避免:统一加锁顺序/加锁超时退出/死锁检查) 线程池队列已满提交任务时会发生什么(线程数小于最大线程数:创建非核心线程 线程数等于最大线程数:执行拒绝策略) 线程池提交任务加入工作队列还是创建线程(线程数小于核心线程数:创建核心线程 线程数小于核心线程数:加入工作队列) 线程池配置(IO密集型:线程数 核心数(1线程等待时间/线程计算时间) CPU密集型:线程数CPU核心数) (即时响应:调高线程数 避免缓冲 动态调整) (非即时响应:线程数可小一点 利用缓冲达到最大效率) 如何排查接口慢(内存层面线程层面外部接口数据库) 如何排查系统卡(内存层面线程层面外部接口数据库) (大量对象导致频繁GC/死循环线程或者线程死锁/外部接口响应慢/sql操作耗时或死锁) JVM类型问题排查(内存层面线程层面 挂死非挂死) OMM问题如何处理(重启修复-生成内存文件-分析内存快照文件) java程序cpu高的原因(频繁GC/死循环线程/大量IO操作) 系统发生full GC的原因(高并发导致瞬时数据量大 一致性加载过多数据 内存泄漏 System.gc) 项目QPS(10~50) 主要业务接口单机约130 集群3 QPS优化(集群 单体) (单体: 内存层面线程层面外部接口数据库) (避免反复GC 避免死循环和死锁 异步调用/队列解耦 缓存/sql走索引/分库分表/读写分离) QPS优化实例(慢接口异步 基础信息入缓存 优化sql走索引) SpringBoot项目中接口默认QPS是多少(Tomcat线程和队列) Tomcat参数默认值(10/minSpareThreads 200/maxThreads 100/acceptCount) Tomcat中为什么使用自定义类加载器(支持部署多个web并相互隔离/实现类动态加载/自定义加载规则增强灵活) Tomcat如何优化(线程数配置:minSpareThreads/maxThreads/acceptCount 连接数配置:maxConnections/connectionTimeout 启用压缩:compression/compressionMinSize/compressableMimeType) 阻塞队列的类型(LinkedBlockingQueue ArrayBlockingQueue PriorityBlockingQueue DelayQueue SynchronousQueue LinkedTransferQueue LinkedBlockingDeque) 阻塞队列的工作原理 (插入-竞争插入锁-条件插入-成功则唤醒获取线程-失败进入等待队列 put) (获取-竞争获取锁-条件获取-成功则唤醒插入线程-失败进入等待队列 take) (LBQueue NodeE 2个ReentrantLock 2个Condition) (ABQueue Object[] 1个ReentrantLock 2个Condition) (PBQueue Object[] 1个ReentrantLock 1个Condition 插入排序) (DQueue 基于PBQueue实现) (SyncQueue 不存数据线程交换) 线程池类型 (ThreadPoolExecutor: newFixedThreadPool/x/x/LQ newSingleThreadExecutor/1/1/LQ newCachedThreadPool/0/MAX_VALUE/SQ) (ScheduledThreadPoolExecutor: newSingleThreadScheduledExecutor newScheduledThreadPool) ScheduledThreadPoolExecutor排序原理(DelayedWorkQueue/小顶堆) submit和execute区别(RunnableCallable/Runnable 有返回/无返回)JVMGC类加载平台无关性(编码为Java文件-编译后生成class文件-JVM将class文件翻译成二进制文件并执行-JVM适配不同的系统) 使用字节码的好处 JVM内存分区(共享私有 堆/栈/方法区/程序计数器 方法区-永久代/元数据区 栈-本地方法栈/虚拟机栈) 堆内存分区及比例(新生代:老年代1:2 Eden:SurvivorFrom:SurvivorTo8:1:1) JVM三大性能调优参数(Xms/初始堆内存、Xmx/最大堆内存、Xss/栈大小) JVM堆区性能调优参数(XX:NewRatio、XX:SurvivorRatio) JVM中堆栈的区别(共享内存/私有内存 存储对象实例数组/存储局部变量基本数据类型 手动动态分配/系统自动分配 有自动回收机制/{}) 永久代和元数据区(老版本/Java1.8 基于堆内存/基于本地缓存 依赖FullGC/独立回收 存储元数据静态变量/存储元数据) Java1.7/1.8中内存分区变化(永久代[堆内存依赖FullGC]/元数据区[本地内存独立回收]) 对象内存布局(对象头/实例数据/对齐填充 字节对齐) 对象存活判定(反向判断-对象死亡 引用计数法/可达性分析法) GCRoot(虚拟机栈中引用的对象/方法区中静态变量/本地方法栈中JNI引用) 垃圾回收算法(标记清除/半区复制/标记整理/分代收集) 新生代-老年代 GC年龄(15) Minor GC、Major GC和Full GC(清理年轻代/清理老年代/清理年轻代和老年代) 触发FullGc的情况(老年代空间不足/System.GC/新生代晋升到老年代对象大小老年代大于剩余空间) 垃圾回收器(Serial、Serial Old、Parallel Scavenge、Parallel Old、G1、ParNew、CMS) Java8默认垃圾回收器(Parallel Scavenge/半区复制、Parallel Old/标记整理) G1虚拟机使用什么垃圾回收算法(复制) CMS和G1区别(老年代/全部 标记清除有内存碎片/标记整理无碎片 并发回收浮动垃圾/筛选回收控制STW) 类加载过程(加载-连接[验证/准备/解析]-初始化-使用-卸载) 双亲委派模型(类加载器收到加载请求-优先将请求委派给父类加载器加载-父类加载器无法加载则子类加载器加载) 4种类加载器(User Class Loader/Application Class Loader/Extention Class Loader/Bootstrap Class Loader) 双亲委派模型优点(确保类唯一性/保证核心类库的安全性/提升代码复用性​) 类唯一性确定参数(​​类加载器/​​类的全限定名)SpringSpringBootSpring框架简述(快速开发框架/IOC/AOP) IOC理解(容器/提供bean的创建、初始化、使用、销毁全生命周期管理解决方案) IOC的实现方式(set注入、构造注入、自动装配) 如何实现一个IOC容器(定义扫描路径-扫描获取.class文件-确定需要管理对象-对象实例化) AOP理解(封装公共功能[权限日志事务]形成切面以无侵入的方式切入到方法中对方法进行增强) 如何实现AOP(接口真实实现类代理类增强) 如何实现AOP(动态代理-对类生成代理类-再调用原方法前后做部分公共操作) AOP使用场景(统一日志、权限校验、事务、返回值统一处理) Bean生命周期(Bean配置-实例化-属性填充-初始化-使用-销毁) Bean是否线程安全(若带有可变状态量则非线程安全) Bean作用域(singleton/prototype/request/session/websocket等) Bean自动装配的方式(配置文件注解) Bean循环依赖解决方式(三级缓存/一级为完成实例化和初始化的Bean/二级为完成实例化的Bean/三级为单例工厂) Bean常用扩展点(Aware接口/InitializingBean接口/DisposableBean接口/BeanPostProcessor) ApplicationContext和BeanFactory区别(ApplicationContext继承BeanFactory) (ResourceLoaderr/资源访问 MessageSource/实现国际化 ApplicationEventPublisher/事件功能) Spring源码及其Spring容器启动过程(初始化Spring容器:3小点 将配置类以BeanDefinition形式注册到容器 调用refresh刷新容器:13小点) (初始化Spring容器:创建BeanFactory/BeanDefinitionReader/ClassPathBeanDefinitionScanner) (调用refresh刷新容器:预处理/BeanFactory初始化和处理[比如扫描和解析配置类执行BeanFactory后置处理器]/初始化ResourceLoaderrMessageSourceApplicationEventPublisher/实例化Bean/发布容器启动完成时间) Spring事务实现方式(数据库事务AOP-Transactional的bean生成代理对象-调用代理对象方法时判断是否有Transactional-若加Transactional-使用事务管理器创建事务设置事务禁止自动提交-执行sql-正常提交异常回滚) Transactional注解失效原因(非Spring管理的bean/内部调用/非public方法/异常处理不当/数据库不支持事务事务管理器配置错误) Spring中事务类型(声明式事务 编程式事务) Spring中事务传播(propagation REQUIRED/REQUIRES_NEW/NESTED/SUPPORTS/NOT_SUPPORTED/MANDATORY/NEVER) REQUIRED/NESTED区别(合并/嵌套)(父--子 子-/-父) Spring中后置处理器作用(BeanFactory后置处理器/Bean后置处理器) (BeanFactory后置处理器:BeanFactoryPostProcessor/BeanDefinition后置处理/bean条件化处理) (Bean后置处理器:BeanPostProcessor/bean实例化后处理/增强代理类/公共属性注入) Spring中事件发布器使用场景(解耦) SpringBoot启动过程(新建SpringApplication对象:3个小点 执行SpringApplication.run方法:4个小点) (新建SpringApplication对象:确定应用类型/加载spring.factories中定义的类/设置带有mian方法的运行主类) (执行SpringApplication.run方法:创建SpringApplicationRunListeners/准备应用程序参数和环境变量/创建、准备、刷新应用上下文环境/发布启动完成事件) SpringBoot自动配置原理(SpringBootApplication组合注解-EnableAutoConfiguration[SpringBootConfigurationComponentScan]-扫描和加载所有spring.factories中定义的类-实例化---) SpringBoot常用注解及其底层实现(3n) SpringBoot配置文件加载顺序(内部通用配置文件-内部专用配置文件-外部配置文件-环境变量-命令行系统参数-命令行应用参数) SpringBoot如何启动Tomcat(run方法中刷新上下文) Starter如何理解(独立的组件/封装了启动配置内部依赖/直接引入即可) SpringMVC、SpringBoot、Spring区别 SpringMVC工作流程(所有请求到前端控制器-前端控制器请求处理器映射器获取1个具体的处理器-使用处理器适配器执行处理器获取ModelAndView-使用视图解析器将ModelAndView解析成View-将View渲染到页面) SpringMVC中组件(前端控制器/处理器映射器/处理器适配器/处理器/视图解析器) SPI(接口定义和接口实现分开 Dubbo JDBC) 注入依赖是代理对象还是普通对象(注入AOP增强类时为代理对象) 注解实现原理(反射) 元注解(Target Rention Documented Inherited) Autowired和Resource区别(提供方-Spring/Java 装配方式-按type/按name)设计模式实践设计模式分类及常见设计模式(分类:创建型/结构型/行为型) (创建:单例 结构:代理 行为:策略/模板/责任链) 单例模式最健壮实现方案(双重检测静态内部类枚举) Spring中常见的设计模式(工厂模式:BeanFactory 代理模式:AOP 模板方法模式:JDBCTemplate 责任链模式:BeanPostProcessor) 设计模式6大原则(单一职责原则/开闭原则/里氏替换原则/依赖倒置原则/接口隔离原则/迪米特法则) 策略模式范例 SmartApplicationListener ResponseBodyAdvice/RequestBodyAdvice HandlerMapping 状态机MybatisMybatis优缺点(SQL和代码解耦比较灵活/匹配JDBC类型连接的所有数据库/易于Spring继承 复杂业务场景中SQL工作量大) #{}和${}区别(占位符预编译处理/拼接符字符串替换 无风险/SQL注入风险) Mybatis一级缓存与二级缓存定义(SqlSession、SqlSessionFactory) Mybatis一级缓存与二级缓存区别 范围会话周期/应用程序周期 事务提交会话结束 共享会话内共享/多会话共享 实现HashMap/Cache接口 规则默认开启 不能关闭/手动开启 可关闭MySQL自定义数据库(容灾管理/存储管理/缓存管理/权限管理/日志管理/sql解析/索引/锁) 索引基本原理(一种对数据排序的数据结构使用索引可快速访问数据库中的指定数据) 索引设计原则(建立索引的字段尽可能表示数据的唯一性例如主键/使用频率高的字段建索引/索引数量合适) 索引数据结构种类及其优劣(Hash:等值查询速度快/不适合范围查询哈希冲突是效率低不适合排序 B树:{}/查询速度不稳定 B树:查询速度稳定天然支持排序/内存冗余开销 平衡二叉树:查询速度稳定/插入删除效率差) B树和B树区别(B树:左子节点值本节点值右子节点值/节点内多个值排序 B树:B数特点/非叶子节点存指针叶子节点存数据/叶子节点形成双向链表) MySQL为什么使用B树(非叶子节点存指针叶子节点存数据容量大/双向链表利于全表扫描) 聚簇索引和非聚簇索引区别(叶子节点存数据/叶子节点存数据指针) 密集索引和稀疏索引(每个数据均有索引/部分数据有索引 注:InnoDB中主键索引为密集索引其他索引为稀疏索引) 索引类型(主键索引/唯一索引/普通索引/联合索引) 最左匹配原则 覆盖索引/索引覆盖(索引中的字段满足查询需求无需回表操作) 回表(根据非主键索引查找主键-根据主键索引查找到数据) 3层B树可存储多少数据(非叶子节点存主键指针/2层-叶子节点存主键数据/1层-页大小为a主键指针大小为b主键数据大小为c-整体数量为a*a*a/b/b/c-a16kb86bytec大约1K结果为2190W) 事务定义(一组sql操作只能全部成功或全部失败) 事务4特性(原子性/一致性/隔离性/持久性) 事务隔离级别及3并发问题(未提交读RU/已提交读RC/可重复读RR/串行化S 脏读/不可重复读/幻读) 事务ACID如何保证(原子性:undo log 一致性:其他3性保证一致性 隔离性:锁MVCC 持久性:redo log持久化到磁盘) 锁分类((粒度:页锁/表锁/行锁[记录锁间隙锁临键锁] 模式:共享锁/排他锁 属性:悲观锁/乐观锁)) InnoDB锁算法(记录锁:锁定数据行 间隙锁:锁定左开右开的区间 临键锁:锁定左开右闭的区间) 临键锁(记录锁间隙锁锁定左开右闭区间) MVCC简述(唯一行号事务id回滚指针-回滚指针指向undo log中上一版本-开启事务后形成新数据行-未提交事务前新数据行其他事务不可见-事务提交后事务id递增) InnoDB如何实现事务(机制: Buffer Pool/Redo Log/Undo Log 注:LogBuffer) InnoDB中RR级别如何避免幻读(快照读:MVCC机制 当前读:临键锁) InnoDB中RC、RR如何实现非阻塞读(MVCC) MySQL RR级别解决了脏读、不可重复读、幻读3个问题 MyISAM和InnoDB区别(不支持事务/支持事务 不支持行锁/支持行锁 索引和数据分离/索引和数据不分离) MySQL执行计划怎么看(explain重要字段包含id、type、key、rows) explain语法中各字段含义 (id表操作顺序:id越大优先执行/id相同自上而下执行 type访问类型:constrefrangeindexALL key:实际走的索引) explain中type中system含义(只有一行数据) MySQL主从同步原理(主库数据变更后更新bin log-从库IO线程发起dump请求-主库IO线程推送bin log到从库-从库IO线程加载到relay log-从库SQL线程加载relay log并执行sql) MySQL主从搭建(配置文件) SQL不走索引的原因(like查询使用前导模糊/范围查询使用负向条件/索引列存在函数或隐式转换/联合索引未遵从最左匹配原则) 慢查询优化方法(服务层-引擎层-数据表-硬件与网络 每层有对应的方法) MySQL深度分页(业务规避 走索引且只查id 避免回表) MySQL快照可见性算法(本事务提交永远可见/其他事务版本未提交不可见 版本提交晚于创建快照则不可见 反之则可见) 如何规避数据库死锁(读写分离 降低隔离级别 事务细粒度化 事务简单化 统一加锁顺序 尽量走主键索引) 子查询的类型(from where exists in) JOIN和子查询的区别(JOIN可使用索引 子查询为临时表) 主键为什么采用long类型(8字节存储范围足够大/存储效率合适/索引效率比uuid高很多/插入效率比自增id高) 为什么使用数据库连接池(///) 数据库存储冗余字段优劣(减少联表提高效率/数据实时性差) 数据库主键类型选择(自增/uuid/雪花long) (自增: 单机递增 竞争自增锁 非分布式唯一不利于迁移) (uuid: 非递增/维护主键索引需频繁移动节点 存储空间大 占用索引空间大/查询效率低 分布式唯一) (雪花long: 单机递增 分布式唯一)分布式基础 集群与分布式区别 集群 分布式 微服务 分布式系统设计目标(可扩展 高可用 高可靠) CAP理论(一致性:所有节点同一时刻数据需一致 可用性:系统在合理的时间内响应请求 容错性:系统发生节点间通信中断时时需保持可用 CP/AP) BASE理论(基本可用/中间状态/最终一致) 负载均衡算法/负载均衡策略(随机 加权随机 轮询 加权轮询 源地址hash) 数据一致性模型(强弱) 分布式id解决方案(uuid 雪花算法) 分布式锁解决方案(数据库:对指定key进行插入和删除 Redis:SETNX带超时参数Watchdog延时 redlock:获取redis锁数量过半即为获取分布式锁) 接口幂等性如何实现(定义:请求单次响应或多次响应后系统数据需合理 实现:请求唯一性id预存并校验/请求带版本号并校验版本号) 事务 分布式事务解决方案(两阶段提交 三阶段提交 TCC saga 本地消息表 事务消息 最大努力通知) 分布式事务两阶段提交和三阶段提交区别(两阶段/三阶段 无超时机制/有超时机制 强一致性/最终一致性 阻塞概率大/阻塞概率小) 两阶段提交(准备/提交 小事务同步阻塞 协调者故障阻塞 网络分区数据不一致) 三阶段提交(询问/准备/提交 小事务超时提交 询问阶段尽早发现问题) 服务 RPC如何理解(远程过程调用 快捷式调用系统外方法) Zeekeeper Dubbo 存储 分库分表实现方式(垂直拆分/水平拆分) 存储拆分后唯一主键(分布式唯一性id方案: 雪花id/自增id/uuid) 雪花算法原理(结构:符号位41位毫秒级时间戳10位机器id12位自增序列号) (优点:分布式唯一/有序递增 缺点:依赖时钟时钟回拨则不唯一) 不分区键查询问题(高频使用字段做分片键/建立分区键与不分区键映射/核心字段冗余存储/长尾查询设计ES) session分布式方案(Redis存储) 缓存 缓存雪崩、缓存击穿和缓存穿透(原因解决方案) (缓存雪崩:大量缓存数据失效导致数据瞬间承受大量请求而挂死/缓存过期设置为随机值缓存预热MQ) (缓存击穿:某一缓存数据失效导致数据瞬间承受大量请求而挂死/热点数据永远不过期分布式互斥锁) (缓存穿透:数据库和缓存均没有数据导致数据瞬间承受大量请求而挂死/布隆过滤器空值缓存参数校验) 常用缓存方案(客户端 cdn nginx 内部缓存 外部缓存 DAO层缓存 mysql缓存) 如何保证数据库和缓存的一致性(缓存可更新可删除数据库可更新按先后顺序组成4种方案/延迟双删/强一致性则封装原子操作) 先更新数据库后删除缓存的优缺点(数据丢失风险低/短期不一致) 缓存过期策略(定时过期:设置缓存有效期 被动过期:使用时判断有效期 定期清理:周期性扫描检查有效期) 缓存淘汰算法(143)(不淘汰 有效期键随机淘汰/有效期键剩余有效期较短则淘汰/有效期键LRU淘汰/有效期键LFU淘汰 所有键先进先出/所有键LRU/所有键LFU) 布隆过滤器优缺点(优点:空间效率高/查询速度快/支持海量去重 缺点:哈希冲突时存在误判/不支持删除操作) 分布式缓存寻址(哈希、一致性哈希、槽位) 高可用 服务降级服务熔断 服务雪崩服务限流 复杂服务拆分方案(SpringCloudAlibaba/Nacos/feign/Seata/RocketMQ/Redis/网关...) 分布式日志解决方案(Elasticsearch/Logstash/Kibana fillbeat)RedisRedis数据结构及其使用场景(String:缓存计数器分布式锁 List:栈队列最新消息 Hash:key-value形式存储对象 Set:集合可做交集并集差集操作 SortSet:有序集合排行榜延迟队列 Bitmap:位图用户活跃度统计 HyperLogLog:UV统计 Geo:经纬度数据) Redis数据结构对应的底层数据结构(简单动态字符串 压缩列表/双向链表 压缩列表/字典 字典/整数集合 跳跃表/压缩列表) 海量数据查询固定前缀key(SCAN命令迭代查询/RediSearch) Redis分布式锁实现(SETNX带超时参数Watchdog延时/redlock) 异步队列实现(List可做队列) RDB和AOF持久化机制及其优缺点(RDB/AOF) (RDB 机制:形成内存快照存入磁盘/savebgsave命令手动触发或配置自动触发 优点:单独进程复刻内存效率高/文件小恢复快 缺点:若系统挂死数据丢失概率大) (AOF 机制:记录所有写、删命令到AOF缓冲区然后同步到磁盘 优点:数据安全丢失概率小 缺点:文件体积大恢复慢效率低) Redis过期键删除策略/Redis缓存过期策略(见分布式缓存过期策略) Redis快的原因(IO多路复用 单线程 内存操作) Redis事务实现 Redis缓存淘汰策略/Redis缓存淘汰算法(见分布式缓存淘汰算法) LRU数据结构实现方案(哈希数组双向链表/哈希数组存储key和链表Node位置/双向链表存储数据/淘汰则删除尾部) LFU数据结构实现方案(哈希数组频率HashMap最小频率变量/哈希数组存储key和频率Map中Node位置/频率HashMap键存储频率和数据/淘汰则按最小频率变量淘汰) Redis高可用方案(主从/哨兵/集群) (主从:1主多从/主负责写从负责读/主从之间数据同步/不可扩容) (哨兵:主从特点/增加哨兵节点/哨兵监控所有节点状态并发通知给管理员/主节点挂死则选取新主节点) (集群:多主多从/每个主节点拥有从节点/主节点挂死则选取新主节点/数据按key进行槽位分配/可扩容) Redis主从复制原理(主从建立连接-从节点发起同步请求-主节点生成RDB文件-从节点加载RDB文件-主节点保存写删命令到缓存并发送到从节点-从节点加载命令) Redis雪崩如何处理(预热随机过期使用锁降低并发使用队列串行化限流和降级) Redis和Mysql数据一致性(见分布式缓存如何保证数据库和缓存的一致性) 为什么使用缓存(提高响应速度/降低数据库负载) 海量数据如何找到一条记录(利用Redis建立key-value) 单个redis服务挂死的原因(缓存无淘汰到账内存不足/持久化进程阻塞/连接资源耗尽) Redis混合持久化模式数据备份逻辑(rdb正常/AOF文件rdb增量命令/使用混合AOF文件恢复数据) 普通SET和分布式锁的区别(SET覆盖/SETNX为key不存在时赋值) 一致性哈希和普通哈希对比(服务器数量变化导致缓存迁移) 一致性哈希和哈希槽对比(可手动分布/节点变化时高可用方案不同/引起雪崩) (一致性哈希:2^32个点形成环/数据节点和服务器节点映射到环上/数据顺时针旋转遇到第一个服务器节点即为存储位置) (哈希槽:2^14个槽点进行分组/每组映射特定的hash范围并对应1个服务器节点/根据数据的键和槽位的对应关系即可确认服务器节点//) Raft选举算法NettyNetty是什么(基于NIO的异步网络应用框架用于快速开发高性能、高可靠性的网络服务) Netty线程模型(Reactor单线程模型多线程模型主从多线程模型) Netty高性能原因(NIO模型管理连接/零拷贝技术实现高效数据传输/内存池化技术减少内存管理开销/支持高性能protobuf序列化协议/采用事件驱动线程模型支持任务运行) Netty为什么不使用AIO(Linux上AIO使用epoll Reactor和Proactor Linux上AIO不成熟)NginxNginx有哪些作用(反向代理/负载均衡/动静分离)FeignFeign底层原理(启动注解 扫描接口类生成实例 扫描方法到容器 动态代理调用方法 组装参数) Feign调用接口异常解决方案(熔断/超时/补偿机制)NacosNacos中服务调用过程(生产端注册并健康检测,消费端定时更新路由,注册中心推送更新,根据路由调用) Nacos支持CPAP(注册配置ephemeraltrue/false AP/CP 默认AP) Nacos挂死服务间是否能访问(可使用不可更新) Nacos动态配置原理(动态配置实时刷新bean客户端定时拉取注册中心推送更新) 注册中心选型(一致性协议/健康检测方式/负载均衡策略/雪崩保护) (Nacos/CPAP Zeekeeper/CP Eureka/AP)xxl-jobxxl-job解决重复调度(任务分片查询/id取模) xxl-job海量任务调度(分片广播 执行器分片查询) xxl-job负载均衡策略(随机/轮询/一致性哈希/LRU/LFU...) elastic-job和xxl-job(依赖-多/少 适合-数据量和服务器数量大/数据量和服务器数量相对不大)消息中间件消息队列优缺点(解耦/异步/削峰 复杂度/多发少发/重复消费/一致性) 死信队列简述(存储未被成功消费的消息的队列) 延时队列简述(一种延时消费消息的队列) 如何保证消息不被重复消费(幂等性 幂等性实现方案见分布式 基础 接口幂等性如何实现) 4大消息队列中间件对比(吞吐量 Topic 可靠性 丢失率) RocketMQ架构/底层实现原理(注册中心/broker/生产者/消费者) RocketMQ事务消息(发送half消息到Broker-执行事务操作-向Broker发送提交/回滚-Broker超时检测生产者事务操作是否成功 消费端MQ保证消费成功) RocketMQ顺序消息(版本号 单队列) (版本号: 生产者发送消息/消费者消费消息判断版本号/消费成功版本号入缓存) (单队列: 生产者发送时确定queue/MQ队列存储/消费者加锁队列单线程消费) RocketMQ持久化机制(Broker收到消息更新commitLogConsumeQueueIndexFile-根据配置持久化到磁盘/同步/异步) RocketMQ与零拷贝(存储:mmapwrite实现4次切换2次内存拷贝 发送:sendfile实现2次切换2次内存拷贝) RocketMQ如何保证不丢消息/如何保证消息可靠传输 (生产者 - broker - 消费者) 生产者不多发不少发(多发属于异常 发送失败需重试) broker存储(单体持久化 集群容灾与备份) 消费者不重复消费(消费失败需重试 重复消费需幂等) 事务消息一致性(生产者不少发 消费者幂等 broker不丢消息) RocketMQ(n主n从 同步复制) RocketMQ 消息积压原因(生产者瞬时生成大量消息 网络问题 消费者bug/消费者速度慢) RocketMQ 消息积压如何处理(生产者业务降级 mq扩容与熔断 消费者逻辑优化/消费者实例增加/灰度发布) RocketMQ 消息积压条件(ProcessQueue 数量大于1000/大小大于100M/消息偏移量差大于2000/顺序消息加锁失败) 消费者速度慢(业务逻辑复杂/外部接口响应慢/数据库操作慢) 消费者逻辑优化(异步重试/熔断/消息本地存储) RocketMQ rebalance(平均负载 环形分配 一致性hash 自定义分配 机房就近分配 机房绑定分配) 生产者海量消息如何确保 kafka高性能原因(磁盘顺序读写 零拷贝 消息批量压缩处理/异步) kafka处理消息顺序、重复发送、重复消费和消息丢失 kafka为什么比RocketMQ吞吐量高(压缩/异步) kafka消息丢失解决方案 kafka的pull和push优缺点 kafka架构设计 kafka副本同步机制 kafka消息高可靠解决方案 kafka的rebalance机制 kafka中zk的作用 自定义MQ(单体队列-分布式集群-Topic与路由-可靠连接-日志与备份-其他如事务消息延时队列) RocketMq和kafka对比(业务/日志 持久化-同步异步/异步 队列多时性能-低/高 队列数-5W/64W 消费失败-可重试/不可 延时消息事务消息-支持/不支持)DubboDubbo简述(作用) Dubbo工作流程 Dubbo架构及其分层设计 (代理 注册 调用 传输 序列化) Dubbo如何做系统交互 (引入调用 Reference接口解析生成bean 封装Invocation 获取路由 请求并获取结果) (暴露 Service接口解析 封装ServiceBean 注册路由 心跳检测) Dubbo负载均衡策略(5) (加权随机 加权轮询 一致性hash) Dubbo如何完成服务导出/服务暴露 Dubbo如何完成服务引入 Dubbo服务调用过程 Dubbo架构设计(注册中心 提供者 消费者 监控 容器) Dubbo支持的哪些注册中心 Dubbo集群容错策略有哪些 Dubbo的SPI机制 Dubbo为什么不使用JDKSPI而自实现SPI Dubbo中ZK集群挂死 发布者和订阅者还能通信吗 Dubbo支持的协议ZookeeperZAB协议 为啥Zookeeper可做注册中心 Zookeeper领导者选举流程 Zookeeper集群之间数据如何同步 Zookeeper数据同步原理 Zookeeper初始化选举和崩溃选举过程 Zookeeper数据模型和节点类型 Zookeeper命名服务、配置管理和集群管理 Zookeeper的watch机制实现原理 Zookeeper分布式锁实现原理 Zookeeper典型应用场景 Zookeeper某个客户端修改节点数据 其他客户端能获取最新数据吗 Zookeeper对事物的支持 Zookeeper观察者机制 Zookeeper会话管理机制 Zookeeper和Eureka对比 Zookeeper如何存储生产者和消费者信息SpringCloudSpringCloudAlibaba各组件功能(Nacos/Ribbon/OpenFeign/Gateway) SpringCloud与Dubbo区别 Seata(XA AT TCC Seaga 前3者均有参与者/协调者) XA(完全隔离/强一致性/性能低 一阶段:开启全局事务/注册分支事务/执行sql 二阶段:检测分支事务/全部成功则全局事务成功) AT(全局锁隔离/弱一致性/性能高 一阶段:开启全局事务/注册分支事务/执行sql并提交事务/记录undo.log 二阶段:检测分支事务/全部成功则删除记录undo.log/反之利用undo.log回滚) TCC(Try/Confirm/Cancel/资源预留隔离/弱一致性/性能高/侵入式 一阶段:开启全局事务/注册分支事务/占据资源 二阶段:成功则Confirm提交 失败则执行Cancel释放资源)参考文献
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进