Q1LIKE模糊查询是否会导致索引失效具体规则与解决方案是什么LIKE查询是否走索引完全取决于通配符%的位置其本质是由B树的有序性决定的。右模糊如LIKE abc%索引有效因为B树叶子节点按键值有序排列前缀匹配可以利用索引进行范围扫描。左模糊如LIKE %abc或全模糊如LIKE %abc%会导致索引失效并触发全表扫描由于无法确定起始键值引擎必须遍历所有记录逐一比对。此外即使写成右模糊形式若字段为VARCHAR而传入数字也可能因隐式类型转换导致索引失效。生产环境中若业务仅需前缀匹配应确保使用右模糊并通过EXPLAIN验证执行计划。若必须支持左模糊或全文检索禁止使用LIKE应引入Elasticsearch或MySQL 5.7的FULLTEXT INDEX。对于短文本左模糊场景可考虑“反转字符串存储右模糊查询”的变通方案但需评估数据写入与维护成本。 延伸追问与关联知识点如何分析SQL是否真正走了索引EXPLAIN是诊断索引使用情况的核心工具。重点关注type字段ALL表示全表扫描index表示全索引扫描range及以上才表示有效利用了索引。同时检查key字段确认实际使用的索引名称rows估算扫描行数Extra中出现Using index表示覆盖索引命中Using filesort或Using temporary则提示存在额外排序或临时表开销。仅凭key非空不能断定查询高效必须结合type与rows综合判断。覆盖索引在模糊查询中的作用当SELECT列表中的所有字段都包含在某个联合索引中时即使WHERE条件中的LIKE导致索引无法用于过滤MySQL仍可能选择该索引进行全索引扫描而非回表查聚簇索引。这是因为索引体积远小于数据行IO代价更低。例如索引(name, age)查询SELECT name, age FROM t WHERE name LIKE %abc虽无法用索引定位但避免了回表性能仍优于全表扫描。ES与MySQL数据同步方案有哪些主流方案有三种一是Canal监听MySQL Binlog实时捕获变更并写入ES延迟低、对业务无侵入但需维护Canal服务二是双写模式业务代码同时写MySQL和ES实现简单但一致性难保障易因异常导致数据不一致三是定时任务批量同步适合对实时性要求不高的场景但存在时间窗口内的数据滞后。生产环境推荐Canal消息队列缓冲的方案兼顾实时性与可靠性。字符集与排序规则对LIKE性能的影响排序规则决定了字符串比较方式。_bin后缀的二进制排序规则严格按字节值比较区分大小写且可利用索引_ci后缀的不区分大小写排序规则需逐字符转换后再比较可能导致索引失效或效率下降。例如utf8mb4_general_ci下LIKE ABC%可能无法走索引而utf8mb4_bin下可以。建表时应根据业务需求选择合适的排序规则避免运行时隐式转换带来的性能损耗。Q2MySQL InnoDB在什么情况下会将行锁升级为表锁InnoDB的行锁是加在索引记录上的而非物理数据行。当UPDATE/DELETE语句的WHERE条件列无索引时InnoDB无法定位具体索引项会对聚簇索引的所有记录加锁等同于锁住整张表这是最常见的“伪行锁”陷阱。在可重复读隔离级别下若查询范围覆盖大量间隙间隙锁与临键锁可能锁定整个区间阻塞其他事务的INSERT操作。DDL操作如ALTER TABLE、CREATE INDEX及显式LOCK TABLES命令会直接获取表级元数据锁或显式表锁。外键约束检查时对子表写入可能对父表相关记录加共享锁反之亦然。始终确保UPDATE/DELETE语句的WHERE条件包含索引列并通过执行计划验证避免无意中锁表引发线上故障。 延伸追问与关联知识点如何诊断线上锁等待与死锁问题通过SHOW ENGINE INNODB STATUS查看最近的死锁日志与当前锁等待信息查询performance_schema.data_locks和data_lock_waits表可精确到每个事务持有的锁类型、模式及等待关系结合慢查询日志定位长事务与未提交事务。生产环境建议开启innodb_print_all_deadlocks参数并将锁监控接入告警系统实现主动发现而非被动响应。MVCC与锁机制如何协同工作MVCC通过版本链实现快照读读取历史版本无需加锁只有当前读SELECT … FOR UPDATE、UPDATE、DELETE等才会加锁。在RC隔离级别下每次当前读都重新生成ReadView只看到已提交数据间隙锁不存在在RR隔离级别下ReadView在首次当前读时生成并保持配合Next-Key Lock防止幻读。理解二者协作是掌握InnoDB并发控制的关键。自增主键与锁的关系InnoDB为自增列维护一个内存计数器插入时需获取自增锁。早期版本采用表级自增锁高并发插入时成为瓶颈5.1.22后引入连续模式批量插入预分配ID段减少锁竞争交错模式下每次插入单独申请ID适用于分布式多源写入但牺牲连续性。自增锁持有时间极短但在超高并发写入场景仍需关注其影响。乐观锁与悲观锁在InnoDB中的实现差异悲观锁通过SELECT … FOR UPDATE显式加排他锁适合写多读少、冲突频繁的场景但并发度低乐观锁通常通过版本号字段实现更新时检查版本号是否变化适合读多写少、冲突罕见的场景避免加锁开销但失败重试成本高。InnoDB本身不提供乐观锁语法需在应用层实现CAS逻辑并注意ABA问题与重试策略。Q3为什么MySQL选择B树作为索引结构树高一般是多少B树是磁盘存储型数据库的最优解。相比红黑树B树是多路平衡搜索树极度矮胖千万级数据高度仅3~4层磁盘IO次数极少。相比B树B树非叶子节点仅存键值不存数据单页可容纳更多索引项进一步降低树高且叶子节点通过双向链表连接天然支持高效范围查询与排序。每个节点大小等于页大小默认16KB一次IO读取一个完整节点最大化利用磁盘预读机制。假设主键为BIGINT8字节页大小16KB每个非叶子节点约存1000个key则3层B树可存储约10亿条数据。因此千万级至亿级数据B树高度稳定在34层意味着仅需34次磁盘IO即可定位目标数据。 延伸追问与关联知识点聚簇索引与非聚簇索引的回表代价如何量化非聚簇索引叶子节点存储主键值查到主键后需再访问聚簇索引获取完整行数据即回表。回表是随机IO代价远高于顺序IO。若回表次数超过阈值通常为扫描行数的20%~30%优化器可能放弃索引转而全表扫描。减少回表的手段包括构建覆盖索引、使用索引合并、限制SELECT字段、分页优化延迟关联。页分裂与页合并对性能的影响当页满时插入新记录触发页分裂原页一半数据移至新页产生碎片并增加树高删除过多记录触发页合并相邻页合并以释放空间。频繁分裂导致写入放大与空间浪费可通过预留填充因子FILLFACTOR、顺序插入、定期OPTIMIZE TABLE缓解。但OPTIMIZE TABLE会重建表并锁表生产环境需在低峰期执行或使用pt-online-schema-change等在线工具。为什么MongoDB用B树而MySQL用B树MongoDB是文档数据库单条文档可能很大且访问模式多样常需直接通过索引获取完整文档内容B树非叶子节点存数据可减少一次IO而MySQL是关系型数据库数据行固定存储在聚簇索引中二级索引只需键值用于定位B树非叶子节点不存数据可容纳更多分支降低树高更适合高并发点查与范围扫描。二者选型源于数据模型与访问模式的根本差异。LSM-Tree与B树的取舍LSM-Tree将随机写转化为顺序写写入吞吐极高适合写密集型场景如日志、时序数据但读需合并多层SSTable存在读放大B树读写均衡适合OLTP事务处理。TiDB底层TiKV采用RocksDBLSM-Tree支撑海量写入上层通过Raft缓存补偿读性能HBase同样基于LSM-Tree。选型核心在于业务是写优先还是读写均衡。Q4如何保证三个线程T1、T2、T3严格按顺序执行除基础的Future.get()阻塞等待外还有多种严谨方案。Thread.join()最直观T2启动后调用T1.join()T3启动后调用T2.join()适用于固定顺序简单场景。CountDownLatch适合复杂依赖T2持有count1的latch1T3持有latch2T1完成后countDown(latch1)T2 await通过后执行并countDown(latch2)。CompletableFuture链式编排代码优雅支持异步回调与异常处理推荐现代Java项目使用。BlockingQueue信号传递解耦性强适合生产者-消费者模式下的顺序控制。若任务无需并行直接用SingleThreadExecutor按序提交天然保序且无同步开销。 延伸追问与关联知识点AQS底层原理是什么AQS是JUC包的核心抽象内部维护一个volatile int state表示同步状态以及一个FIFO双向等待队列。独占模式如ReentrantLock通过CAS修改state获取锁失败则封装为Node加入队列并park阻塞共享模式如CountDownLatchstate表示剩余计数await时检查state是否为0不为0则入队等待。AQS将同步语义与线程排队机制解耦使各类同步器只需关注state的含义与转换规则。虚拟线程对并发编程模型的影响JDK21引入的虚拟线程是轻量级用户态线程由JVM调度而非操作系统创建销毁成本极低可轻松创建百万级实例。传统线程池在虚拟线程下失去意义应改用Executors.newVirtualThreadPerTaskExecutor()。但需注意synchronized块与native方法会导致虚拟线程pin住载体线程应替换为ReentrantLockThreadLocal滥用会造成内存爆炸建议使用ScopedValue。虚拟线程使“每请求一线程”模型重回高并发场景。ForkJoinPool的工作窃取算法ForkJoinPool为每个工作线程维护独立双端队列线程从自己队列头部取任务执行当队列为空时从其他线程队列尾部窃取任务实现负载均衡。这种设计减少了线程间竞争特别适合递归分治类任务。与SingleThreadExecutor的串行队列完全不同ForkJoinPool强调并行分解与动态调度适用于CPU密集型计算而非顺序控制。响应式编程如何实现顺序控制Reactor中flatMap不保证内部订阅顺序适合并行处理concatMap严格保持上游元素顺序逐个订阅下游Publisher适用于需保序的场景zip将多个流按位置配对天然对齐顺序。背压机制通过request(n)控制上游发射速率防止下游过载。响应式顺序控制本质是将命令式的线程同步转化为声明式的操作符组合避免显式锁与阻塞。Q5不同垃圾回收器GC的区别及选型依据回收器算法核心特点适用场景JDK版本Serial复制/标记整理单线程STW时间长无并发开销客户端模式 / 小内存嵌入式应用全版本Parallel Scavenge复制吞吐量优先自适应调节策略后台计算密集型、批处理服务JDK5CMS标记清除低延迟但有内存碎片和浮动垃圾旧版Web应用已废弃JDK5~8G1Region化 标记整理可预测停顿时间大堆友好无碎片中大堆服务端应用JDK9默认JDK7ZGC染色指针 读屏障亚毫秒级暂停支持TB级堆全程并发超低延迟金融/实时交易系统JDK11Shenandoah转发指针 读屏障亚毫秒级暂停与ZGC类似但实现不同超低延迟场景RedHat主导JDK12选型原则关注延迟选ZGC或G1关注吞吐选Parallel Scavenge小内存/嵌入式选Serial生产环境JDK11首选G1JDK17可评估ZGC。 延伸追问与关联知识点G1的Mixed GC触发条件与Region分配策略Mixed GC在老年代占用达到堆的45%默认时触发回收部分老年代Region与所有年轻代Region。G1将堆划分为大小相等的Region新生代与老年代Region动态调整Humongous Region用于存放大对象超过Region容量50%。频繁分配Humongous Region会导致内存碎片与Full GC应调大Region尺寸或拆分大对象。ZGC的着色指针与读屏障如何实现并发标记ZGC将64位指针的高几位用作标记位Marked、Remapped、Finalizable对象引用本身携带GC状态。读屏障在加载引用时检查标记位若对象被移动则自动修正引用指向新地址。整个过程无需STW标记与转移全程并发。相比Shenandoah的转发指针表ZGC无需额外内存查找但受限于指针位数目前仅支持64位平台。GC调优的核心指标与工具链核心指标包括GC频率、单次暂停时间、总暂停占比、堆使用率趋势。工具链方面GC日志-Xlog:gc*是基础配合GCEasy/GCViewer可视化分析JFR提供低开销运行时事件采集Async Profiler可采样分析GC热点与内存分配路径。调优目标是满足SLA前提下最小化GC开销而非追求零GC。内存泄漏与GC的关系GC只能回收不可达对象若对象被意外强引用如静态集合、未关闭资源、ThreadLocal未清理则永远可达导致泄漏。软引用在内存不足时被回收适合缓存弱引用下次GC即回收适合WeakHashMap虚引用仅用于跟踪回收时机。排查泄漏需结合堆转储jmap/MAT分析GC Roots引用链定位异常持有者。Q6Spring Cloud Gateway与Nginx的核心区别是什么各自适用场景如何划分维度NginxSpring Cloud Gateway架构层级基础设施层 / 入口网关L4/L7应用层 / 微服务网关L7技术栈C语言事件驱动异步非阻塞Java/Spring WebFlux Netty响应式核心能力高性能反向代理、静态资源、SSL卸载、基础限流动态路由、熔断降级、鉴权、灰度、协议转换、注册发现集成配置方式nginx.conf热重载需reload配置中心动态推送实时生效扩展性Lua脚本门槛高Java Filter与业务无缝集成性能极高单机10万QPS较高单机数千~数万QPS二者并非同一层级的替代品而是互补协作的关系。生产架构最佳实践Nginx作为最外层入口负责域名解析、SSL终止、静态资源及基础限流并将请求转发至Gateway集群Spring Cloud Gateway部署在Nginx之后处理业务相关治理。简单代理用Nginx微服务深度集成用Gateway双层架构兼顾极致性能与业务灵活性。 延伸追问与关联知识点Netty的零拷贝与Reactor线程模型Netty通过DirectMemory、FileRegion.transferTo、CompositeByteBuf实现用户态零拷贝减少内核态与用户态数据复制。Reactor模型采用少量IO线程处理大量连接BossGroup接收连接WorkerGroup处理IO读写业务逻辑交由独立线程池执行避免IO线程阻塞。Spring Cloud Gateway继承此模型使其在高并发下仍能保持低延迟。Gateway过滤器链的执行顺序与自定义扩展过滤器分为GlobalFilter与GatewayFilter执行顺序由getOrder()返回值决定数值越小优先级越高。Pre Filter在路由前执行如鉴权、限流Post Filter在响应返回后执行如日志、指标。自定义过滤器需实现相应接口并注册为Bean注意避免在过滤器中执行阻塞操作否则破坏响应式链路。Nginx的upstream健康检查与负载均衡算法开源版Nginx仅支持被动健康检查max_fails/fail_timeout请求失败后才标记节点不可用商业版Nginx Plus支持主动TCP/HTTP探针。负载均衡算法包括round-robin默认、ip_hash会话保持、least_conn最少连接、generic hash自定义key。微服务场景下通常由Gateway或服务网格承担智能路由Nginx仅作基础负载。API网关的安全防护体系网关应集成WAF防御SQL注入/XSS等攻击JWT校验在网关统一完成避免各服务重复验证OAuth2对接时网关作为Resource Server或BFF层处理Token防重放通过NonceTimestamp签名机制实现敏感数据脱敏在Post Filter中处理。安全策略应分层设计网关负责通用防护业务服务专注领域安全。Q7RabbitMQ消息堆积除了增加消费者还有哪些系统性解决方案消息堆积需分阶段多层次治理。紧急扩容时可临时增加消费者实例或将消息转发到新队列用更多消费者消费注意顺序性要求。生产者侧实施背压机制当队列长度超阈值时拒绝新消息或降级写入DB/日志防止雪崩。消费者侧优化包括批量消费减少ACK开销、异步处理耗时逻辑、合理设置prefetch count避免单消费者过载。死信队列用于承接超时或失败消息后续补偿处理避免阻塞主队列。建立队列深度监控告警堆积前预警而非堆积后救火。同时反思架构设计评估是否真需要MQ高频/低频消息是否应拆分到不同队列消费者逻辑是否可异步化。 延伸追问与关联知识点Confirm机制与Return机制如何保证可靠投递Confirm机制确保消息到达Broker开启publisher confirm后Broker收到消息返回ack/nack生产者据此重试或记录。Return机制处理路由失败当mandatorytrue且消息无法路由到队列时Broker返回return回调。二者结合可实现“发送端→Broker→队列”全链路可靠但需注意confirm仅保证入队不保证被消费消费端仍需手动ACK。手动ACK与批量ACK的性能权衡逐条ACK安全性高但网络开销大批量ACK提升吞吐但失败时整批重投。prefetch count限制消费者在途未ACK消息数防止内存溢出。调优公式batch_size ≈ prefetch_count / 并发消费者数确保ACK频率与处理能力匹配。关键业务建议逐条ACK日志类等容忍少量丢失的场景可批量ACK。延迟消息的实现方案TTLDLX方案消息设置TTL过期后进入DLX再路由到目标队列但TTL相同的消息才能保证顺序不同TTL消息会阻塞后续短TTL消息。rabbitmq-delayed-message-exchange插件基于Erlang定时器实现任意延迟无顺序问题但高延迟量下性能下降。生产环境推荐插件方案或对延迟精度要求不高时使用多级TTL队列规避阻塞。Kafka与RabbitMQ在消息堆积场景下的差异Kafka以分区为单位并行消费堆积时可通过增加分区与消费者组实例线性扩容且消息持久化在磁盘堆积不影响性能RabbitMQ是竞争消费者模型堆积时消息驻留内存或换出磁盘换出后消费性能骤降扩容受限于队列绑定关系。Kafka适合大数据量流式处理RabbitMQ适合低延迟事务消息选型需匹配业务特征。Q8TCP与WebSocket的关系如何保证心跳与断线重连WebSocket是应用层协议底层基于TCP。通过HTTP Upgrade握手建立连接后转为全双工二进制帧通信不再遵循HTTP请求-响应模型。TCP自身keepalive间隔过长默认2小时不可靠必须在应用层自定义Ping/Pong帧客户端定时发送Ping服务端回Pong超时未收到则判定断开。前端监听onclose/onerror事件采用指数退避算法如1s→2s→4s→…→max重试避免服务端瞬时压力重连后需同步业务状态校验数据一致性。WebSocket本身不保证消息必达关键业务需在应用层实现消息确认重试幂等机制不能依赖传输层可靠性。 延伸追问与关联知识点WebSocket的帧格式与控制帧类型WebSocket帧由FIN、RSV、Opcode、Mask、Payload Length等组成。Opcode标识帧类型0x1文本、0x2二进制、0x8关闭、0x9 Ping、0xA Pong。客户端发送帧必须掩码服务端不得掩码。控制帧Ping/Pong/ClosePayload不得超过125字节且不可分片。理解帧结构有助于调试与自定义协议扩展。长连接场景下的粘包与拆包处理WebSocket协议自带帧边界不存在TCP粘包问题。但若在WebSocket之上封装自定义二进制协议如Protobuf over WS仍需处理应用层粘包通过长度前缀、分隔符或固定头解析消息边界。纯文本JSON消息通常以完整帧传输无需额外处理但超大消息可能被分片接收端需缓冲直至FIN1。SSE与WebSocket的选型对比SSE基于HTTP单向服务器推送自动重连文本格式兼容性好但无法客户端主动发送WebSocket全双工二进制支持需自行实现重连与心跳代理穿透可能受限。仅需服务端通知如进度、公告选SSE需双向交互如聊天、游戏选WebSocket。SSE在Nginx/CDN环境下更友好WebSocket需注意中间件配置。分布式WebSocket会话管理单机WebSocket会话绑定特定服务器集群环境下用户可能连接到不同节点。解决方案一是Redis Pub/Sub发送方将消息发布到频道所有节点订阅后推送给本地会话二是消息队列广播各节点消费同一Topic三是会话亲和性通过Nginx ip_hash或Cookie将用户固定到某节点但节点故障时会话丢失。推荐Pub/Sub方案兼顾可靠性与扩展性。