<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>后端 on 洛克里亚的五度 博客</title>
    <link>https://lv-blog.pages.dev/tags/%E5%90%8E%E7%AB%AF/</link>
    <description>Recent content in 后端 on 洛克里亚的五度 博客</description>
    <generator>Hugo</generator>
    <language>zh</language>
    <lastBuildDate>Wed, 15 Jul 2026 00:46:10 +0800</lastBuildDate>
    <atom:link href="https://lv-blog.pages.dev/tags/%E5%90%8E%E7%AB%AF/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>MyBatis 相关面试题整理</title>
      <link>https://lv-blog.pages.dev/posts/programming/for-interview/mybatis-interview-questions/</link>
      <pubDate>Wed, 15 Jul 2026 00:46:10 +0800</pubDate>
      <guid>https://lv-blog.pages.dev/posts/programming/for-interview/mybatis-interview-questions/</guid>
      <description>&lt;h2 id=&#34;mybatis-执行流程&#34;&gt;Mybatis 执行流程&lt;/h2&gt;
&lt;p&gt;mybatis-config.xml (总规)
↓
SqlSessionFactory (总管)
↓
SqlSession (服务员) —— 包含所有执行方法
↓
Executor (大管家) —— 优先查缓存（一级/二级）
↓
MappedStatement (菜谱) —— 持有SQL、参数映射、结果映射
↓
输入参数映射 (备菜) → JDBC执行 → 输出结果映射 (装盘)
↓
返回POJO/集合 (上菜)&lt;/p&gt;
&lt;h2 id=&#34;mybatis-是否支持延迟加载&#34;&gt;Mybatis 是否支持延迟加载&lt;/h2&gt;
&lt;p&gt;支持，默认不开启&lt;/p&gt;
&lt;p&gt;collection fecthType=&amp;ldquo;lazy&amp;rdquo;&lt;/p&gt;
&lt;p&gt;mybatis配置文件延迟加载 lazyLoadingEnabled&lt;/p&gt;
&lt;p&gt;延迟加载的原理&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;CGLIB创建目标对象的代理对象&lt;/li&gt;
&lt;li&gt;调用目标方法 getOrderList&lt;/li&gt;
&lt;li&gt;调用对象 invoke 方法&lt;/li&gt;
&lt;li&gt;判断 orderList 是否为空&lt;/li&gt;
&lt;li&gt;为空，执行SQL&lt;/li&gt;
&lt;li&gt;不为空获取结果&lt;/li&gt;
&lt;li&gt;封装 orderList&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;mybatis-的一级缓存-二级缓存-用过吗&#34;&gt;Mybatis 的一级缓存 二级缓存 用过吗&lt;/h2&gt;
&lt;p&gt;本地缓存 - 基于 PerpetualCache 本质是一个 HashMap
一级缓存 - 作用域是 session 级别
二级缓存 - 作用域是namespace 和 mapper的作用域，不依赖于 session
二级缓存默认关闭
settings name=&amp;ldquo;cacheEnabled&amp;rdquo; value=&amp;ldquo;true&amp;rdquo;
当某个作用域进行了增删改操作，该作用域下的所有select的缓存将被clear&lt;/p&gt;</description>
    </item>
    <item>
      <title>Redis 相关面试题整理</title>
      <link>https://lv-blog.pages.dev/posts/programming/for-interview/redis-interview-questions/</link>
      <pubDate>Wed, 15 Jul 2026 00:46:10 +0800</pubDate>
      <guid>https://lv-blog.pages.dev/posts/programming/for-interview/redis-interview-questions/</guid>
      <description>&lt;h2 id=&#34;你的项目的哪些场景使用了-redis&#34;&gt;你的项目的哪些场景使用了 redis&lt;/h2&gt;
&lt;h2 id=&#34;如果发生了缓存击穿穿透雪崩如何解决&#34;&gt;如果发生了缓存击穿、穿透、雪崩如何解决&lt;/h2&gt;
&lt;h2 id=&#34;redis-作为缓存-mysql的数据如何与redis进行同步&#34;&gt;redis 作为缓存， mysql的数据如何与redis进行同步？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;先介绍业务，看看业务符合什么场景&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;一致性较高场景&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;双写一致
&lt;ul&gt;
&lt;li&gt;读&lt;/li&gt;
&lt;li&gt;写 | 延迟双删&lt;/li&gt;
&lt;li&gt;分布式锁
&lt;ul&gt;
&lt;li&gt;读多写少
&lt;ul&gt;
&lt;li&gt;共享锁&lt;/li&gt;
&lt;li&gt;排它锁&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;允许延迟一致&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;介绍一下你的异步方案&#34;&gt;介绍一下你的异步方案&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;允许延时一致的业务，采用异步通知
&lt;ul&gt;
&lt;li&gt;MQ消息中间件&lt;/li&gt;
&lt;li&gt;Canal中间件&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;强一致性（Redisson读写锁）
&lt;ul&gt;
&lt;li&gt;共享锁
&lt;ul&gt;
&lt;li&gt;阻塞写操作&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;排它锁
&lt;ul&gt;
&lt;li&gt;阻塞读和写操作&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;redis作为缓存数据的持久化是怎么做的&#34;&gt;Redis作为缓存，数据的持久化是怎么做的？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;RDB
&lt;ul&gt;
&lt;li&gt;save&lt;/li&gt;
&lt;li&gt;bgsave&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;AOF&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;rdb-的执行原理&#34;&gt;RDB 的执行原理？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;fork主进程得到子进程&lt;/li&gt;
&lt;li&gt;子进程共享主进程的内存数据（复制页表）&lt;/li&gt;
&lt;li&gt;copy-on-write&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;aof-的执行原理&#34;&gt;AOF 的执行原理&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;配置项&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;always&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;everysec&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;no&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;重写触发&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;bgrewriteaof&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;rdb-和-aof-对比&#34;&gt;RDB 和 AOF 对比&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;持久化方式&lt;/li&gt;
&lt;li&gt;数据完整性&lt;/li&gt;
&lt;li&gt;文件大小&lt;/li&gt;
&lt;li&gt;宕机恢复速度&lt;/li&gt;
&lt;li&gt;数据恢复优先级&lt;/li&gt;
&lt;li&gt;系统资源占用&lt;/li&gt;
&lt;li&gt;使用场景&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;redis-的key过期了会立即删除吗&#34;&gt;redis 的key过期了会立即删除吗&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;惰性删除&lt;/li&gt;
&lt;li&gt;定期删除
&lt;ul&gt;
&lt;li&gt;SLOW（10hz）&lt;/li&gt;
&lt;li&gt;FAST&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Redis的过期策略：惰性删除+定期删除 配合使用&lt;/p&gt;
&lt;h2 id=&#34;redis-数据淘汰策略&#34;&gt;Redis 数据淘汰策略&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;noeviction&lt;/li&gt;
&lt;li&gt;volatile-ttl&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;allkeys-random&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;volatile-random&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;allkeys-lru&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;volatile-lru&lt;/li&gt;
&lt;li&gt;allkeys-lfu&lt;/li&gt;
&lt;li&gt;volatile-lfu&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;数据库有1000万数据redis只能缓存20万如何保证redis中的数据都是热点数据&#34;&gt;数据库有1000万数据，redis只能缓存20万，如何保证redis中的数据都是热点数据？&lt;/h2&gt;
&lt;p&gt;使用 allkeys-lru&lt;/p&gt;</description>
    </item>
    <item>
      <title>消息中间件 面试题整理</title>
      <link>https://lv-blog.pages.dev/posts/programming/for-interview/mq-interview-questions/</link>
      <pubDate>Sun, 23 Mar 2025 13:21:54 +0800</pubDate>
      <guid>https://lv-blog.pages.dev/posts/programming/for-interview/mq-interview-questions/</guid>
      <description>&lt;h1 id=&#34;消息队列通识&#34;&gt;消息队列通识&lt;/h1&gt;
&lt;h2 id=&#34;为什么需要消息队列&#34;&gt;为什么需要消息队列&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;解耦&lt;/li&gt;
&lt;li&gt;削峰填谷&lt;/li&gt;
&lt;li&gt;异步调用&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;消息队列如何保持幂等&#34;&gt;消息队列如何保持幂等&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;重复源泉
&lt;ul&gt;
&lt;li&gt;生产端重发
&lt;ul&gt;
&lt;li&gt;发送ACK没有回复继续发送&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;消费端重复&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;解决方案
&lt;ul&gt;
&lt;li&gt;唯一消息ID，生产者发送时携带messageId&lt;/li&gt;
&lt;li&gt;幂等表&lt;/li&gt;
&lt;li&gt;状态机校验&lt;/li&gt;
&lt;li&gt;乐观锁 / 版本号&lt;/li&gt;
&lt;li&gt;分布式锁&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;核心原则
&lt;ul&gt;
&lt;li&gt;消费逻辑天然幂等&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;为什么需要消息队列-1&#34;&gt;为什么需要消息队列&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;解耦&lt;/li&gt;
&lt;li&gt;异步&lt;/li&gt;
&lt;li&gt;削峰&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;消息队列的模型有哪些&#34;&gt;消息队列的模型有哪些&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;点对点模型&lt;/li&gt;
&lt;li&gt;发布订阅模型&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;如何保证消息不丢失&#34;&gt;如何保证消息不丢失&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;生产端
&lt;ul&gt;
&lt;li&gt;ack&lt;/li&gt;
&lt;li&gt;broker 持久化
&lt;ul&gt;
&lt;li&gt;生产环境副本因子 &amp;gt;= 3&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;消费端
&lt;ul&gt;
&lt;li&gt;手动提交 offset&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;如何保证消息有序&#34;&gt;如何保证消息有序&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;让需要保持有序的消息落到同一个分区&lt;/li&gt;
&lt;li&gt;给唯一的key，且key以后不会重复&lt;/li&gt;
&lt;li&gt;Kafka保证唯一分区内有序，跨分区无序&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;rabbitmq&#34;&gt;RabbitMQ&lt;/h1&gt;
&lt;h2 id=&#34;rabbitmq-如何保证消息不丢失&#34;&gt;RabbitMQ 如何保证消息不丢失&lt;/h2&gt;
&lt;!-- TODO 复习 --&gt;
&lt;ul&gt;
&lt;li&gt;哪些情况会丢失
&lt;ul&gt;
&lt;li&gt;publisher -&amp;gt; exchange
&lt;ul&gt;
&lt;li&gt;生产者确认机制
&lt;ul&gt;
&lt;li&gt;ack publish-confirm&lt;/li&gt;
&lt;li&gt;nack publish-confirm&lt;/li&gt;
&lt;li&gt;ack publish-return&lt;/li&gt;
&lt;li&gt;消息失败之后如何处理
&lt;ul&gt;
&lt;li&gt;回调方法&lt;/li&gt;
&lt;li&gt;记录日志&lt;/li&gt;
&lt;li&gt;保存到数据库中然后定时重发&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;exchange -&amp;gt; queue
&lt;ul&gt;
&lt;li&gt;消息持久化
&lt;ul&gt;
&lt;li&gt;交换机持久化&lt;/li&gt;
&lt;li&gt;队列持久化&lt;/li&gt;
&lt;li&gt;消息持久化&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;queue&lt;/li&gt;
&lt;li&gt;queue -&amp;gt; consumer
&lt;ul&gt;
&lt;li&gt;消费者确认机制&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;rabbitmq-消息的重复消费问题是如何解决的&#34;&gt;RabbitMQ 消息的重复消费问题是如何解决的&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;重复消费的原因&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spring Cloud 面试题整理</title>
      <link>https://lv-blog.pages.dev/posts/programming/for-interview/spring-cloud-interview-questions/</link>
      <pubDate>Sun, 23 Feb 2025 13:20:18 +0800</pubDate>
      <guid>https://lv-blog.pages.dev/posts/programming/for-interview/spring-cloud-interview-questions/</guid>
      <description>&lt;h1 id=&#34;springcloud-问题&#34;&gt;SpringCloud 问题&lt;/h1&gt;
&lt;h2 id=&#34;springcloud-五大组件&#34;&gt;springcloud 五大组件&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Eureka / nacos&lt;/li&gt;
&lt;li&gt;Ribbon&lt;/li&gt;
&lt;li&gt;Feign / dubbo&lt;/li&gt;
&lt;li&gt;Hystrix / sentinel&lt;/li&gt;
&lt;li&gt;Zuul/Gateway&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;服务注册和发现是什么意思springcloud-如何实现服务注册和发现&#34;&gt;服务注册和发现是什么意思，SpringCloud 如何实现服务注册和发现？&lt;/h2&gt;
&lt;h2 id=&#34;nacos-和-eureka-的区别&#34;&gt;nacos 和 eureka 的区别？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;相同点
&lt;ul&gt;
&lt;li&gt;服务提供者 注册 服务信息 到 注册中心&lt;/li&gt;
&lt;li&gt;服务消费者 定时从 注册中心 拉取&lt;/li&gt;
&lt;li&gt;服务消费者 对 服务提供者 进行远程调用&lt;/li&gt;
&lt;li&gt;服务提供者 临时实例 采用心跳检查
&lt;ul&gt;
&lt;li&gt;什么是临时实例？
&lt;ul&gt;
&lt;li&gt;默认实例都是临时实例&lt;/li&gt;
&lt;li&gt;临时实例心跳模式&lt;/li&gt;
&lt;li&gt;非临时主动探测&lt;/li&gt;
&lt;li&gt;临时实例没有心跳会被剔除&lt;/li&gt;
&lt;li&gt;非临时不会被剔除&lt;/li&gt;
&lt;li&gt;ephemeral: false 变成非临时实例
&lt;ul&gt;
&lt;li&gt;非临时实例，nacos会主动询问服务提供者是否存活&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;不同点
&lt;ul&gt;
&lt;li&gt;非临时实例&lt;/li&gt;
&lt;li&gt;nacos集群AP，如果存在非临时实例，采用CP&lt;/li&gt;
&lt;li&gt;eureka采用AP&lt;/li&gt;
&lt;li&gt;nacos还有配置中心&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;你们项目中负载均衡是如何实现的&#34;&gt;你们项目中负载均衡是如何实现的？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Ribbon&lt;/li&gt;
&lt;li&gt;Ribbon 负载均衡流程
&lt;ol&gt;
&lt;li&gt;微服务发起请求&lt;/li&gt;
&lt;li&gt;Ribbon 从注册中心拉取&lt;/li&gt;
&lt;li&gt;根据策略进行转发&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;ribbon-负载均衡策略有哪些&#34;&gt;Ribbon 负载均衡策略有哪些？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;RoundRobinRule&lt;/strong&gt; 简单轮询&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;WeightedResponseTimeRule&lt;/strong&gt; 按照权重来选择服务器，响应时间越长，权重越小&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RandomRule&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;BestAvailableRule 忽略短路的服务器，选择并发数较低的服务器&lt;/li&gt;
&lt;li&gt;RetryRule 重试机制的选择逻辑（基于轮询）&lt;/li&gt;
&lt;li&gt;AvailabilityFilteringRule 可用性敏感策略。先过滤非健康的，再选择连接数比较小的&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ZoneAvoidanceRule&lt;/strong&gt; 以区域可用的服务器为基础对服务器选择。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;如果想自定义负载均衡策略如何实现&#34;&gt;如果想自定义负载均衡策略，如何实现？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;自己创建类实现 IRule 接口， 再通过配置类或配置文件配置&lt;/li&gt;
&lt;li&gt;@Bean IRule 全局生效&lt;/li&gt;
&lt;li&gt;NFLoadBalancerRuleClassName 局部生效&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;什么是服务雪崩如何解决这个问题&#34;&gt;什么是服务雪崩？如何解决这个问题？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;服务雪崩
&lt;ul&gt;
&lt;li&gt;一个服务失败，导致整条链路都失败的情形&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;解决方案
&lt;ul&gt;
&lt;li&gt;降级（接口）
&lt;ul&gt;
&lt;li&gt;Feign 接口走fallback&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;熔断（整个服务）
&lt;ul&gt;
&lt;li&gt;Hystix
&lt;ul&gt;
&lt;li&gt;@EnableCircuitBreaker&lt;/li&gt;
&lt;li&gt;断路器关闭 - 打开 - 半开&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;你们的微服务是怎么监控的&#34;&gt;你们的微服务是怎么监控的？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;skywalking
&lt;ul&gt;
&lt;li&gt;apache顶级项目&lt;/li&gt;
&lt;li&gt;问题定位&lt;/li&gt;
&lt;li&gt;性能分析&lt;/li&gt;
&lt;li&gt;服务关系&lt;/li&gt;
&lt;li&gt;服务告警&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1 id=&#34;业务相关&#34;&gt;业务相关&lt;/h1&gt;
&lt;h2 id=&#34;项目中有没有做过限流怎么做的&#34;&gt;项目中有没有做过限流？怎么做的？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;限流情况&lt;/p&gt;</description>
    </item>
    <item>
      <title>Java 面试题整理</title>
      <link>https://lv-blog.pages.dev/posts/programming/for-interview/java-interview-questions/</link>
      <pubDate>Thu, 23 Jan 2025 08:50:54 +0800</pubDate>
      <guid>https://lv-blog.pages.dev/posts/programming/for-interview/java-interview-questions/</guid>
      <description>&lt;h1 id=&#34;集合&#34;&gt;集合&lt;/h1&gt;
&lt;h2 id=&#34;为什么数组索引要从-0-开始从-1-开始不行吗&#34;&gt;为什么数组索引要从 0 开始？从 1 开始不行吗？&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;回答大纲&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数组在内存中是连续存储的，CPU 通过寻址公式访问元素&lt;/li&gt;
&lt;li&gt;从 0 开始：&lt;code&gt;a[i]_address = base_address + i * typeSize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;从 1 开始：&lt;code&gt;base_address + (i-1) * typeSize&lt;/code&gt;，多一次减法&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;正式回答&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数组在内存中是连续存储的，CPU 通过寻址公式来访问指定下标的元素：&lt;code&gt;a[i] 的地址 = 数组首地址 + i * 元素大小&lt;/code&gt;。当数组下标从 0 开始时，直接套用上述公式即可计算偏移量；如果下标从 1 开始，则需要先执行 &lt;code&gt;i - 1&lt;/code&gt; 再做乘法，多了一次减法运算。虽然单次访问的差异可以忽略不计，但数组通常会出现在循环、遍历等高频访问的场景中，这笔额外开销会被无限放大。这也是 C 语言沿用下来的历史约定，Java 作为一门追求高效的系统级语言，继承了这一设计。&lt;/p&gt;
&lt;h2 id=&#34;时间复杂度如何计算的&#34;&gt;时间复杂度如何计算的？&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;回答大纲&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;口诀：常 对 幂 指 阶&lt;/li&gt;
&lt;li&gt;常见复杂度
&lt;ul&gt;
&lt;li&gt;常数复杂度 O(1)：不随 n 变化&lt;/li&gt;
&lt;li&gt;对数复杂度 O(logN)：二分查找、树操作&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;正式回答&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;时间复杂度用于衡量算法执行时间随数据规模 n 增长的变化趋势，是大 O 表示法下对最坏情况的抽象描述。常见的大小关系可用口诀&amp;quot;常对幂指阶&amp;quot;来记忆，即 O(1) &amp;lt; O(logN) &amp;lt; O(N) &amp;lt; O(N*logN) &amp;lt; O(N²) &amp;lt; O(2ⁿ) &amp;lt; O(n!)，越靠后算法越慢。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spring 面试题整理</title>
      <link>https://lv-blog.pages.dev/posts/programming/for-interview/spring-interview-questions/</link>
      <pubDate>Sat, 19 Oct 2024 23:19:24 +0800</pubDate>
      <guid>https://lv-blog.pages.dev/posts/programming/for-interview/spring-interview-questions/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;面试题从互联网各个角落收集而来&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;谈一谈-spring-ioc-的底层实现&#34;&gt;谈一谈 Spring IOC 的底层实现？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;反射&lt;/li&gt;
&lt;li&gt;工厂的价值&lt;/li&gt;
&lt;li&gt;设计模式&lt;/li&gt;
&lt;li&gt;关键的几个方法
&lt;ul&gt;
&lt;li&gt;createBeanFactory&lt;/li&gt;
&lt;li&gt;getBean&lt;/li&gt;
&lt;li&gt;doGetBean&lt;/li&gt;
&lt;li&gt;createBean&lt;/li&gt;
&lt;li&gt;doCreateBean&lt;/li&gt;
&lt;li&gt;createBeanInstance(getDeclaredConstructor, newInstance)「方案选单」&lt;/li&gt;
&lt;li&gt;populateBean&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&#34;mermaid&#34;&gt;flowchart TD
    A[开始] --&gt; B[&#34;createBeanFactory()&lt;br/&gt;创建 DefaultListableBeanFactory&#34;]
    B --&gt; C[加载 BeanDefinition&lt;br/&gt;解析 XML/注解]
    C --&gt; D[&#34;getBean(beanName)&lt;br/&gt;外部调用入口&#34;]

    D --&gt; E[&#34;doGetBean(beanName)&#34;]
    E --&gt; F{从缓存获取单例?}
    F --&gt;|是| G[返回缓存的 Bean]
    F --&gt;|否| H[&#34;createBean(beanName, mbd)&#34;]

    H --&gt; I[&#34;doCreateBean(beanName, mbd)&#34;]
    I --&gt; J[&#34;createBeanInstance()&lt;br/&gt;getDeclaredConstructor + newInstance&#34;]
    J --&gt; K[&#34;populateBean()&lt;br/&gt;属性填充/依赖注入&#34;]
    K --&gt; L[&#34;initializeBean()&lt;br/&gt;初始化回调&#34;]
    L --&gt; M[注册销毁方法]
    M --&gt; N[返回完整 Bean 实例]
&lt;/pre&gt;
&lt;h2 id=&#34;谈谈-springioc-的理解原理和实现&#34;&gt;谈谈 SpringIOC 的理解，原理和实现？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;IOC 思想&lt;/li&gt;
&lt;li&gt;DI 实现手段&lt;/li&gt;
&lt;li&gt;什么是容器 什么是Bean&lt;/li&gt;
&lt;li&gt;BeanDefination
&lt;ul&gt;
&lt;li&gt;从哪里读
&lt;ul&gt;
&lt;li&gt;XML&lt;/li&gt;
&lt;li&gt;注解&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;存哪里
&lt;ul&gt;
&lt;li&gt;所有 BeanDefinition 都存在 DefaultListableBeanFactory 里的一个 Map 中&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;容器的生命周期&#34;&gt;容器的生命周期&lt;/h2&gt;
&lt;pre class=&#34;mermaid&#34;&gt;flowchart TD
    START([🚀 程序启动]) --&gt; REFRESH[&#34;AbstractApplicationContext.refresh()&#34;]

    REFRESH --&gt; PHASE1

    subgraph PHASE1[&#34;🔵 第一阶段：准备工作&#34;]
        direction TB
        A1[&#34;prepareRefresh()\n记录启动时间\n设置容器状态为「活跃」\n初始化环境变量&#34;] --&gt; A2
        A2[&#34;obtainFreshBeanFactory()\n创建 DefaultListableBeanFactory\n这是容器的核心仓库&#34;] --&gt; A3
        A3[&#34;prepareBeanFactory()\n注册基础 BeanPostProcessor\n注册 Aware 相关处理器\n注册默认环境 Bean（environment）&#34;]
    end

    PHASE1 --&gt; PHASE2

    subgraph PHASE2[&#34;🟢 第二阶段：加载 BeanDefinition（读图纸）&#34;]
        direction TB
        B1[&#34;扫描 @ComponentScan 指定的包\n或读取 XML 配置文件&#34;] --&gt; B2
        B2[&#34;解析注解 / XML\n识别 @Component @Service\n@Repository @Controller @Bean&#34;] --&gt; B3
        B3[&#34;为每个 Bean 生成 BeanDefinition\n记录：类名、作用域、是否懒加载\n初始化方法、销毁方法、依赖关系&#34;] --&gt; B4
        B4[(&#34;存入 beanDefinitionMap\nkey = beanName\nvalue = BeanDefinition&#34;)]
    end

    PHASE2 --&gt; PHASE3

    subgraph PHASE3[&#34;🟡 第三阶段：修改 BeanDefinition（修图纸）&#34;]
        direction TB
        C1[&#34;invokeBeanFactoryPostProcessors()\n执行所有 BeanFactoryPostProcessor&#34;] --&gt; C2
        C2[&#34;ConfigurationClassPostProcessor\n处理 @Configuration @Import\n@PropertySource @ComponentScan\n👉 SpringBoot 自动装配在此触发&#34;] --&gt; C3
        C3[&#34;PropertySourcesPlaceholderConfigurer\n替换 BeanDefinition 中\n所有 ${xxx} 占位符为真实值&#34;] --&gt; C4
        C4[/&#34;所有 BeanDefinition 最终确定\n图纸不再变动&#34;/]
    end

    PHASE3 --&gt; PHASE4

    subgraph PHASE4[&#34;🌸 第四阶段：注册 BeanPostProcessor（工人就位）&#34;]
        direction TB
        D1[&#34;registerBeanPostProcessors()\n按优先级顺序注册\nPriorityOrdered → Ordered → 普通&#34;] --&gt; D2
        D2[&#34;AutowiredAnnotationBeanPostProcessor\n负责处理 @Autowired @Value&#34;] --&gt; D3
        D3[&#34;CommonAnnotationBeanPostProcessor\n负责处理 @PostConstruct @PreDestroy @Resource&#34;] --&gt; D4
        D4[&#34;AnnotationAwareAspectJAutoProxyCreator\n负责检测切面、生成 AOP 代理对象&#34;] --&gt; D5
        D5[/&#34;所有工人就位\n等待 Bean 创建时介入\n此时不开工&#34;/]
    end

    PHASE4 --&gt; PHASE5

    subgraph PHASE5[&#34;🟣 第五阶段：容器基础设施初始化&#34;]
        direction TB
        E1[&#34;initMessageSource()\n初始化国际化资源 i18n&#34;] --&gt; E2
        E2[&#34;initApplicationEventMulticaster()\n初始化事件广播器&#34;] --&gt; E3
        E3[&#34;onRefresh()\n⭐ SpringBoot 在此启动\nTomcat / Jetty / Undertow\nWeb 容器开始监听端口&#34;] --&gt; E4
        E4[&#34;registerListeners()\n注册所有 ApplicationListener\n监听容器事件&#34;]
    end

    PHASE5 --&gt; PHASE6

    subgraph PHASE6[&#34;🟠 第六阶段：实例化所有单例 Bean&#34;]
        direction TB
        F1[&#34;finishBeanFactoryInitialization()\npreInstantiateSingletons()\n遍历所有非懒加载单例 BeanDefinition&#34;] --&gt; F2
        F2[&#34;逐个执行 getBean()\n触发每个 Bean 的生命周期\n实例化 → 属性填充 → Aware回调\n→ 前置处理 → init方法 → 后置处理&#34;] --&gt; F3
        F3[(&#34;所有单例 Bean 存入\nsingletonObjects 一级缓存\n✅ 全部就绪&#34;)]
    end

    PHASE6 --&gt; PHASE7

    subgraph PHASE7[&#34;✅ 第七阶段：容器就绪&#34;]
        direction TB
        G1[&#34;finishRefresh()\n清理启动时占用的资源\n初始化生命周期处理器&#34;] --&gt; G2
        G2[&#34;发布 ContextRefreshedEvent\n通知所有监听者：容器启动完成&#34;] --&gt; G3
        G3[/&#34;容器进入运行状态\n可以处理业务请求&#34;/]
    end

    G3 --&gt; RUNNING([🎉 容器正常运行中])

    RUNNING -.-&gt;|&#34;收到关闭信号\nCtrl+C / kill / close()&#34;| PHASE8

    subgraph PHASE8[&#34;🔴 第八阶段：容器销毁&#34;]
        direction TB
        H1[&#34;发布 ContextClosedEvent\n通知所有监听者：容器即将关闭&#34;] --&gt; H2
        H2[&#34;停止 Web 容器\nTomcat 停止接受新请求&#34;] --&gt; H3
        H3[&#34;执行所有 Bean 的销毁逻辑\n@PreDestroy → destroy() → destroy-method\n按注册顺序逆序销毁&#34;] --&gt; H4
        H4[&#34;清空所有缓存\nsingletonObjects 清空\nbeanDefinitionMap 清空&#34;] --&gt; H5
        H5[&#34;容器状态设置为「关闭」\nactive = false / closed = true&#34;]
    end

    H5 --&gt; END([💀 容器销毁完成])

    style START fill:#43A047,color:#fff
    style RUNNING fill:#43A047,color:#fff
    style END fill:#e53935,color:#fff
    style REFRESH fill:#1E88E5,color:#fff
&lt;/pre&gt;
&lt;h2 id=&#34;bean-的生命周期&#34;&gt;bean 的生命周期&lt;/h2&gt;
&lt;pre class=&#34;mermaid&#34;&gt;flowchart TD
    START([🌱 开始创建 Bean]) --&gt; A

    A[&#34;① 实例化\nInstantiation\n反射调用构造方法\nnew 出空壳对象\n此时所有字段都是 null&#34;] --&gt; B

    B[&#34;② 放入三级缓存\nsingletonFactories\n提前暴露半成品\n为循环依赖做准备&#34;] --&gt; C

    C[&#34;③ 属性填充\npopulateBean()\n处理 @Autowired @Value\n把依赖的 Bean 注入进来&#34;] --&gt; D

    subgraph AWARE[&#34;④ Aware 回调&#34;]
        direction TB
        D[&#34;BeanNameAware\n告诉 Bean 自己叫什么名字&#34;] --&gt; E
        E[&#34;BeanFactoryAware\n把 BeanFactory 塞给 Bean&#34;] --&gt; F
        F[&#34;ApplicationContextAware\n把 ApplicationContext 塞给 Bean&#34;]
    end

    subgraph INIT[&#34;⑤ 初始化 initializeBean()&#34;]
        direction TB
        G[&#34;前置处理\npostProcessBeforeInitialization()\n所有 BeanPostProcessor 挨个执行\n📌 @PostConstruct 在这里被调用&#34;] --&gt; INITMETHOD

        subgraph INITMETHOD[&#34;init 方法（按顺序执行）&#34;]
            direction TB
            H1[&#34;第1个：@PostConstruct\n（已在前置处理中执行）&#34;] --&gt; H2
            H2[&#34;第2个：afterPropertiesSet()\n实现 InitializingBean 接口&#34;] --&gt; H3
            H3[&#34;第3个：init-method\n@Bean(initMethod=&#39;xxx&#39;) 或 XML 配置&#34;]
        end

        INITMETHOD --&gt; I

        I[&#34;后置处理\npostProcessAfterInitialization()\n所有 BeanPostProcessor 挨个执行\n⭐ AOP 代理在这里生成&#34;]
    end

    AWARE --&gt; INIT

    I --&gt; J

    subgraph CACHE[&#34;⑥ 存入缓存&#34;]
        direction TB
        J[&#34;从三级缓存 singletonFactories 移除\n从二级缓存 earlySingletonObjects 移除&#34;] --&gt; K
        K[&#34;存入一级缓存 singletonObjects\n✅ 完整 Bean 就绪&#34;]
    end

    K --&gt; READY([🎉 Bean 可以正常使用了])

    READY -.-&gt;|&#34;容器关闭&#34;| DESTROY

    subgraph DESTROY[&#34;⑦ 销毁阶段（容器关闭时）&#34;]
        direction TB
        D1[&#34;第1个：@PreDestroy\n方法被调用&#34;] --&gt; D2
        D2[&#34;第2个：destroy()\n实现 DisposableBean 接口&#34;] --&gt; D3
        D3[&#34;第3个：destroy-method\n@Bean(destroyMethod=&#39;xxx&#39;) 或 XML 配置&#34;]
    end

    D3 --&gt; END([💀 Bean 销毁完成])
&lt;/pre&gt;
&lt;h2 id=&#34;spring-三级缓存依赖流程&#34;&gt;spring 三级缓存依赖流程&lt;/h2&gt;
&lt;pre class=&#34;mermaid&#34;&gt;sequenceDiagram
    participant Spring as Spring容器
    participant L3 as 三级缓存&lt;br/&gt;singletonFactories
    participant L2 as 二级缓存&lt;br/&gt;earlySingletonObjects
    participant L1 as 一级缓存&lt;br/&gt;singletonObjects

    Note over Spring: 开始创建 A

    Spring-&gt;&gt;Spring: ① new A 空壳对象
    Spring-&gt;&gt;L3: ② 存入 A 的 ObjectFactory lambda

    Note over Spring: 给 A 注入属性，发现需要 B

    Spring-&gt;&gt;Spring: ③ new B 空壳对象
    Spring-&gt;&gt;L3: ④ 存入 B 的 ObjectFactory lambda

    Note over Spring: 给 B 注入属性，发现需要 A

    Spring-&gt;&gt;L1: ⑤ getBean(A)，查一级缓存
    L1--&gt;&gt;Spring: ❌ 没有

    Spring-&gt;&gt;L2: 查二级缓存
    L2--&gt;&gt;Spring: ❌ 没有

    Spring-&gt;&gt;L3: 查三级缓存
    L3--&gt;&gt;Spring: ✅ 找到 A 的 lambda！

    Spring-&gt;&gt;Spring: ⑥ 执行 lambda&lt;br/&gt;（需要代理则生成代理 A）
    Spring-&gt;&gt;L2: ⑦ 早期引用放入二级缓存
    Spring-&gt;&gt;L3: 删除三级缓存中的 A

    Note over Spring: B 拿到 A 的早期引用，B 完成初始化

    Spring-&gt;&gt;L1: ⑧ B 放入一级缓存 ✅
    Spring-&gt;&gt;L3: 删除三级缓存中的 B

    Note over Spring: 回到 A 的流程，B 已就绪，A 完成初始化

    Spring-&gt;&gt;L1: ⑨ A 放入一级缓存 ✅
    Spring-&gt;&gt;L2: 删除二级缓存中的 A

    Note over L1: 最终：一级缓存中有完整的 A 和 B ✅
&lt;/pre&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;情况&lt;/th&gt;
					&lt;th&gt;三级缓存&lt;/th&gt;
					&lt;th&gt;lambda 执行&lt;/th&gt;
					&lt;th&gt;二级缓存&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;无循环依赖，无 AOP&lt;/td&gt;
					&lt;td&gt;存了 lambda&lt;/td&gt;
					&lt;td&gt;❌ 不执行&lt;/td&gt;
					&lt;td&gt;不经过&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;无循环依赖，有 AOP&lt;/td&gt;
					&lt;td&gt;存了 lambda&lt;/td&gt;
					&lt;td&gt;❌ 不执行&lt;/td&gt;
					&lt;td&gt;不经过&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;有循环依赖，无 AOP&lt;/td&gt;
					&lt;td&gt;存了 lambda&lt;/td&gt;
					&lt;td&gt;✅ 执行&lt;/td&gt;
					&lt;td&gt;存原始对象&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;有循环依赖，有 AOP&lt;/td&gt;
					&lt;td&gt;存了 lambda&lt;/td&gt;
					&lt;td&gt;✅ 执行&lt;/td&gt;
					&lt;td&gt;存代理对象&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;spring-bean-缓存的放置时间和删除时间&#34;&gt;spring bean 缓存的放置时间和删除时间&lt;/h2&gt;
&lt;h2 id=&#34;spring-bean-三级缓存的放置与删除时间&#34;&gt;Spring Bean 三级缓存的放置与删除时间&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;缓存&lt;/th&gt;
					&lt;th&gt;存的是什么&lt;/th&gt;
					&lt;th&gt;放入时机&lt;/th&gt;
					&lt;th&gt;删除时机&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;三级 &lt;code&gt;singletonFactories&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Bean 的工厂 lambda&lt;/td&gt;
					&lt;td&gt;实例化完成后立刻放入&lt;/td&gt;
					&lt;td&gt;工厂被调用时（升级到二级）或 Bean 完成时&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;二级 &lt;code&gt;earlySingletonObjects&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;早期暴露的半成品 Bean&lt;/td&gt;
					&lt;td&gt;三级工厂被调用的瞬间&lt;/td&gt;
					&lt;td&gt;Bean 完全初始化完成放入一级时&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;一级 &lt;code&gt;singletonObjects&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;完整可用的 Bean&lt;/td&gt;
					&lt;td&gt;初始化全部完成后&lt;/td&gt;
					&lt;td&gt;容器关闭销毁时&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;beanfactory-和-factorybean-的区别&#34;&gt;BeanFactory 和 FactoryBean 的区别？&lt;/h2&gt;
&lt;h3 id=&#34;factorybean-是什么&#34;&gt;FactoryBean 是什么&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;FactoryBean&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;T&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 返回 Bean 的实例（可以是复杂创建逻辑）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    T &lt;span style=&#34;color:#a6e22e&#34;&gt;getObject&lt;/span&gt;() &lt;span style=&#34;color:#66d9ef&#34;&gt;throws&lt;/span&gt; Exception;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 返回 Bean 的类型&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Class&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;?&amp;gt;&lt;/span&gt; getObjectType();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 是否单例&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;boolean&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;isSingleton&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;相同点
&lt;ul&gt;
&lt;li&gt;都是用来创建Bean对象的&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;不同点
&lt;ul&gt;
&lt;li&gt;使用 BeanFactory 创建对象的适合必须遵循严格的生命周期流程，太复杂了。如果想简单自定义某个对象的创建，同时想交给spring管理，那么必须实现 FactoryBean 接口
&lt;ul&gt;
&lt;li&gt;isSingleton 是否是单例对象&lt;/li&gt;
&lt;li&gt;getObjectType 获取返回对象的类型&lt;/li&gt;
&lt;li&gt;getObject 自定义创建对象的过程&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;对比维度&lt;/th&gt;
					&lt;th&gt;BeanFactory&lt;/th&gt;
					&lt;th&gt;FactoryBean&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;角色&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;容器/工厂接口&lt;/td&gt;
					&lt;td&gt;特殊的 Bean&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;功能&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;管理所有 Bean 的生命周期&lt;/td&gt;
					&lt;td&gt;自定义某个 Bean 的创建逻辑&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;定位&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;基础设施（IOC 容器）&lt;/td&gt;
					&lt;td&gt;业务扩展（创建复杂对象）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;使用方式&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;由 Spring 框架实现和使用&lt;/td&gt;
					&lt;td&gt;由开发者实现，注册到容器中&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;常见实现&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;DefaultListableBeanFactory&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;SqlSessionFactoryBean&lt;/code&gt;、&lt;code&gt;ProxyFactoryBean&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;谁创建谁&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;BeanFactory&lt;/code&gt; 创建并管理 &lt;code&gt;FactoryBean&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;FactoryBean&lt;/code&gt; 创建业务对象&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;pre class=&#34;mermaid&#34;&gt;flowchart LR
    subgraph BeanFactory[BeanFactory - IOC容器]
        direction LR
        Bean1[普通 Bean]
        Bean2[普通 Bean]
        FB[FactoryBean&lt;br/&gt;特殊 Bean]
    end

    FB --&gt;|调用 getObject| Result[业务对象]

    User[开发者] --&gt;|getBean| BF[BeanFactory]
    BF --&gt;|返回| Bean1
    BF --&gt;|返回| Bean2
    BF --&gt;|返回 getObject 结果| Result
    BF --&gt;|加 &amp; 前缀| FB
&lt;/pre&gt;
&lt;h2 id=&#34;spring中用到的设计模式&#34;&gt;Spring中用到的设计模式&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;单例模式&lt;/li&gt;
&lt;li&gt;原型模式（指定作用域为prototype）&lt;/li&gt;
&lt;li&gt;工厂模式
&lt;ul&gt;
&lt;li&gt;BeanFactory&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;模板方法
&lt;ul&gt;
&lt;li&gt;JdbcTemplate&lt;/li&gt;
&lt;li&gt;TransactionTemplate&lt;/li&gt;
&lt;li&gt;RestTemplate&lt;/li&gt;
&lt;li&gt;RedisTemplate&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;策略模式
&lt;ul&gt;
&lt;li&gt;XmlBeanDefinitionReader&lt;/li&gt;
&lt;li&gt;PropertiesBeanDefinitionReader&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;观察者模式
&lt;ul&gt;
&lt;li&gt;listener&lt;/li&gt;
&lt;li&gt;event&lt;/li&gt;
&lt;li&gt;multicast&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;适配器模式
&lt;ul&gt;
&lt;li&gt;HandlerAdapter&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;装饰者模式
&lt;ul&gt;
&lt;li&gt;BeanWrapper&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;责任链模式
&lt;ul&gt;
&lt;li&gt;使用aop的时候会先生成一个拦截器链&lt;/li&gt;
&lt;li&gt;SpringMVC 的filter责任链&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;代理模式
&lt;ul&gt;
&lt;li&gt;动态代理&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;委托者模式
&lt;ul&gt;
&lt;li&gt;delegate&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;spring-aop-底层实现原理&#34;&gt;Spring AOP 底层实现原理&lt;/h2&gt;
&lt;h3 id=&#34;-第一层一句话定性开场&#34;&gt;🥇 第一层：一句话定性（开场）&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;Spring AOP 的底层本质是&lt;strong&gt;动态代理&lt;/strong&gt;。Spring 在容器初始化 Bean 的时候，通过 &lt;code&gt;BeanPostProcessor&lt;/code&gt; 机制拦截，判断这个 Bean 是否需要被增强，如果需要，就用动态代理生成一个代理对象，替换掉原始 Bean 注册进容器。后续所有对这个 Bean 的调用，实际上都是在走代理对象。&amp;rdquo;&lt;/p&gt;</description>
    </item>
    <item>
      <title>MySQL 面试题整理</title>
      <link>https://lv-blog.pages.dev/posts/programming/for-interview/mysql-interview-questions/</link>
      <pubDate>Thu, 19 Sep 2024 23:19:24 +0800</pubDate>
      <guid>https://lv-blog.pages.dev/posts/programming/for-interview/mysql-interview-questions/</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;面试题从互联网各个角落收集而来&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;如何定位慢查询&#34;&gt;如何定位慢查询？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;方案1
&lt;ul&gt;
&lt;li&gt;开源工具
&lt;ul&gt;
&lt;li&gt;Arthas&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;运维工具
&lt;ul&gt;
&lt;li&gt;Prometheus&lt;/li&gt;
&lt;li&gt;Skywalking&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;方案2
&lt;ul&gt;
&lt;li&gt;MySQL自带慢日志(mysql性能损耗)
&lt;ul&gt;
&lt;li&gt;开启慢日志方法
&lt;ul&gt;
&lt;li&gt;/etc/my.conf
&lt;ul&gt;
&lt;li&gt;slow_query_log&lt;/li&gt;
&lt;li&gt;long_query_time&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;sql语句执行很慢如何分析&#34;&gt;SQL语句执行很慢，如何分析&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;慢的原因
&lt;ul&gt;
&lt;li&gt;聚合查询&lt;/li&gt;
&lt;li&gt;多表查询&lt;/li&gt;
&lt;li&gt;表数据量过大查询&lt;/li&gt;
&lt;li&gt;深度分页查询&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;如何分析慢
&lt;ul&gt;
&lt;li&gt;explain， desc 命令
&lt;ul&gt;
&lt;li&gt;如何分析执行结果？
&lt;ul&gt;
&lt;li&gt;extra 的额外优化建议
&lt;ul&gt;
&lt;li&gt;using where; using index 查找使用了索引，需要的数据在索引列都能找到，不需要回表查询数据&lt;/li&gt;
&lt;li&gt;using index condition 查找使用了索引&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;type
&lt;ul&gt;
&lt;li&gt;index，all 需要优化&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;了解过索引吗什么是索引&#34;&gt;了解过索引吗？什么是索引？&lt;/h2&gt;
&lt;p&gt;索引（index）是帮助 MySQL 高效获取数据的数据结构（有序）。在数据之外，数据库系统还维护着满足特定查找算法的数据结构（如 B+ 树），这些数据结构以某种方式引用（指向）数据，这样就可以在这些数据结构上实现高级查找算法，这种数据结构就是索引。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;帮助MySQL高效获取数据的数据结构&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;索引的底层数据结构了解过吗&#34;&gt;索引的底层数据结构了解过吗？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;二叉搜索树&lt;/li&gt;
&lt;li&gt;红黑树&lt;/li&gt;
&lt;li&gt;B树&lt;/li&gt;
&lt;li&gt;B+树
&lt;ul&gt;
&lt;li&gt;阶数更多，路径更短&lt;/li&gt;
&lt;li&gt;磁盘读写代价B+树更低，叶子节点才能真正存储数据&lt;/li&gt;
&lt;li&gt;便于扫库和区间查询，叶子节点是双向链表&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;什么是聚簇索引什么是非聚簇索引&#34;&gt;什么是聚簇索引？什么是非聚簇索引？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;聚簇索引&lt;/li&gt;
&lt;li&gt;二级索引&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;什么是回表查询&#34;&gt;什么是回表查询？&lt;/h2&gt;
&lt;h2 id=&#34;知道什么是覆盖索引吗&#34;&gt;知道什么是覆盖索引吗？&lt;/h2&gt;
&lt;p&gt;通过该索引查询能够一次找到所有数据，且无需回表的，就是覆盖索引&lt;/p&gt;
&lt;h2 id=&#34;mysql超大分页怎么处理&#34;&gt;MySQL超大分页怎么处理？&lt;/h2&gt;
&lt;p&gt;使用覆盖索引加上子查询&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-mysql&#34; data-lang=&#34;mysql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; tb_sku t,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#66d9ef&#34;&gt;select&lt;/span&gt; id &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; tb_sku &lt;span style=&#34;color:#66d9ef&#34;&gt;order&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;by&lt;/span&gt; id &lt;span style=&#34;color:#66d9ef&#34;&gt;limit&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;9000000&lt;/span&gt;,&lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt;) a 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;where&lt;/span&gt; t.id &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; a.id
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;索引创建的原则有哪些&#34;&gt;索引创建的原则有哪些？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;单表超过10万条数据且查询比较频繁的表建立索引&lt;/li&gt;
&lt;li&gt;常常作为查询条件的字段要建立索引&lt;/li&gt;
&lt;li&gt;使用区分度高的列作为索引，尽量建立唯一索引&lt;/li&gt;
&lt;li&gt;字符串类型的字段长度较长可以建立前缀索引&lt;/li&gt;
&lt;li&gt;尽量使用联合索引，减少单列索引&lt;/li&gt;
&lt;li&gt;索引列使用NOT NULL方便优化器确定哪个索引更好用于查询&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;什么情况下索引会失效&#34;&gt;什么情况下索引会失效？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;违反了最左前缀法则&lt;/li&gt;
&lt;li&gt;查询范围右边的列，不能使用索引&lt;/li&gt;
&lt;li&gt;索引列上进行运算操作，索引列失效&lt;/li&gt;
&lt;li&gt;字符串不加单引号，索引失效（索引类型转换导致的失效）&lt;/li&gt;
&lt;li&gt;字符串非尾部匹配，索引失效&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;谈一谈对sql优化的经验&#34;&gt;谈一谈对SQL优化的经验&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;表设计优化
&lt;ul&gt;
&lt;li&gt;我们参考了 阿里开发手册《嵩山版》&lt;/li&gt;
&lt;li&gt;根据实际存储数值长短设计数据类型&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;索引的优化&lt;/li&gt;
&lt;li&gt;SQL语句的优化
&lt;ul&gt;
&lt;li&gt;select 语句务必指明字段名称
&lt;ul&gt;
&lt;li&gt;为了覆盖索引&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;尽量用 union all 代替 union&lt;/li&gt;
&lt;li&gt;避免对 where 子句中对字段进行表达式操作&lt;/li&gt;
&lt;li&gt;能用 innerjoin 就不用 left join , right join。如必须，要以小表为驱动&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;主从复制，读写分离&lt;/li&gt;
&lt;li&gt;分库分表&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;事务的特性详细说一说&#34;&gt;事务的特性详细说一说&lt;/h2&gt;
&lt;h2 id=&#34;并发事务带来哪些问题如何解决这些问题mysql的默认隔离级别是&#34;&gt;并发事务带来哪些问题，如何解决这些问题？MySQL的默认隔离级别是？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;并发事务的问题
&lt;ul&gt;
&lt;li&gt;脏读
&lt;ul&gt;
&lt;li&gt;读已提交&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;不可重复读
&lt;ul&gt;
&lt;li&gt;值问题&lt;/li&gt;
&lt;li&gt;可重复读&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;幻读
&lt;ul&gt;
&lt;li&gt;数量问题&lt;/li&gt;
&lt;li&gt;串行化&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;隔离级别
&lt;ul&gt;
&lt;li&gt;未提交读&lt;/li&gt;
&lt;li&gt;读已提交&lt;/li&gt;
&lt;li&gt;可重复读*&lt;/li&gt;
&lt;li&gt;串行化&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;undo-log-和-redo-log-的区别&#34;&gt;undo log 和 redo log 的区别&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;缓冲池&lt;/li&gt;
&lt;li&gt;数据页&lt;/li&gt;
&lt;li&gt;redo log
&lt;ul&gt;
&lt;li&gt;物理&lt;/li&gt;
&lt;li&gt;持久&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;undo log
&lt;ul&gt;
&lt;li&gt;逻辑&lt;/li&gt;
&lt;li&gt;原子 一致&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;事务的隔离性底层是如何保证的&#34;&gt;事务的隔离性底层是如何保证的？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;锁：排他锁&lt;/li&gt;
&lt;li&gt;MVCC
&lt;ul&gt;
&lt;li&gt;多版本并发控制&lt;/li&gt;
&lt;li&gt;依赖于
&lt;ul&gt;
&lt;li&gt;隐式字段
&lt;ul&gt;
&lt;li&gt;DB_TRX_ID&lt;/li&gt;
&lt;li&gt;DB_ROLL_PTR&lt;/li&gt;
&lt;li&gt;DB_ROW_ID&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;undo log
&lt;ul&gt;
&lt;li&gt;版本链
&lt;ul&gt;
&lt;li&gt;版本链数据访问规则&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;readview
&lt;ul&gt;
&lt;li&gt;快照读
&lt;ul&gt;
&lt;li&gt;Read Committed 每次 select都生成一个快照读&lt;/li&gt;
&lt;li&gt;Repeatable Read 开启事务后第一个 select 语句才是快照读的地方&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;核心字段
&lt;ul&gt;
&lt;li&gt;m_ids&lt;/li&gt;
&lt;li&gt;min_trx_id&lt;/li&gt;
&lt;li&gt;max_trx_id&lt;/li&gt;
&lt;li&gt;creator_trx_id&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RC隔离级别下，在事务中每次执行快照读时生成 ReadView&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;img style=&#34;background:wheat&#34; src=&#34;https://img.wathan.cn/images/2026/06/cd548aef09e32fd1e14c29fa8745e0e1b60269f31af92b320c83320d44bdedf1.svg&#34;&gt;
&lt;h2 id=&#34;mysql-的主从同步原理&#34;&gt;MySQL 的主从同步原理&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;核心：二进制日志
&lt;ul&gt;
&lt;li&gt;BINLOG
&lt;ul&gt;
&lt;li&gt;DDL&lt;/li&gt;
&lt;li&gt;DML
主数据库在事务提交时，变更记录写入 Binlog
从库 binlog -&amp;gt; 中继日志
从库 中继日志读取事件 -&amp;gt; 从库数据库&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;你们项目用过分库分表吗&#34;&gt;你们项目用过分库分表吗？&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;什么时候分库分表
&lt;ul&gt;
&lt;li&gt;单表数据量达到1000W 或者 20GB&lt;/li&gt;
&lt;li&gt;优化解决不了性能问题&lt;/li&gt;
&lt;li&gt;IO、CPU瓶颈&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;如何拆分
&lt;ul&gt;
&lt;li&gt;垂直拆分
&lt;ul&gt;
&lt;li&gt;垂直分库
&lt;ul&gt;
&lt;li&gt;不同表拆分到不同库&lt;/li&gt;
&lt;li&gt;适用于微服务&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;垂直分表
&lt;ul&gt;
&lt;li&gt;不常用字段单独放在一张表&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;水平拆分
&lt;ul&gt;
&lt;li&gt;水平分库
&lt;ul&gt;
&lt;li&gt;一个库的数据拆分到多个库中&lt;/li&gt;
&lt;li&gt;路由规则
&lt;ul&gt;
&lt;li&gt;根据id节点取模&lt;/li&gt;
&lt;li&gt;按id范围路由&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;水平分表
&lt;ul&gt;
&lt;li&gt;一个表的数据拆分到多个表中&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;新的问题
&lt;ul&gt;
&lt;li&gt;分布式事务一致性问题&lt;/li&gt;
&lt;li&gt;跨节点关联查询&lt;/li&gt;
&lt;li&gt;跨节点分页、排序函数&lt;/li&gt;
&lt;li&gt;主键去重&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;解决方案
&lt;ul&gt;
&lt;li&gt;分库分表中间件
&lt;ul&gt;
&lt;li&gt;mycat&lt;/li&gt;
&lt;li&gt;sharding-sphere&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;深入问题&#34;&gt;深入问题&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;为什么 InnoDB 主键建议自增？&lt;/li&gt;
&lt;li&gt;为什么非自增主键会导致页分裂？&lt;/li&gt;
&lt;li&gt;为什么 MyISAM 和 InnoDB 索引结构不同？&lt;/li&gt;
&lt;li&gt;为什么 B+树适合磁盘而红黑树不适合？&lt;/li&gt;
&lt;/ol&gt;</description>
    </item>
  </channel>
</rss>
