每日一题

月伴飞鱼 2025-01-06 23:43:03
工作相关
支付宝打赏 微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者!

MySQL

MySQL叶子节点为啥使用双向链表?不使用单向呢?

MySQL 中的 B+ 树索引采用 双向链表 来连接叶子节点,而不是单向链表。

这种设计主要是为了提高查询效率,尤其是在进行范围查询(例如 BETWEEN)时。

支持双向范围查询:

双向链表使得叶子节点之间的遍历更加灵活,能够支持 顺序查询倒序查询 两种场景。

顺序扫描

  • MySQL 可以从指定的起始叶子节点顺序扫描到下一个叶子节点,执行范围查询或排序时,顺序访问非常高效。

倒序扫描

  • 如果需要倒序查询或倒排索引查询,双向链表提供了方便的支持。
  • 通过指向前一个叶子节点的指针,可以很方便地实现从高值到低值的扫描,而无需再次从头开始遍历 B+ 树。

例如,ORDER BY column DESC 查询时,双向链表能够允许 MySQL 从最大值开始,按逆序快速遍历节点。

减少不必要的回溯:

如果使用单向链表,在倒序查询时,MySQL 必须重新进行回溯(即从根节点重新开始查找)。

双向链表通过每个节点保存指向上一个节点的指针,可以快速找到前一个叶子节点,从而避免了回溯操作。

Redis

什么是Redis的渐进式ReHash?

它是一种哈希表扩容方法,用于在数据增长时逐步将元素迁移到新的哈希表,而不影响系统的正常读写操作。

基本原理:

Redis 的哈希表结构在元素增多时会触发扩容(通常将数组大小扩大一倍)。

为了将元素重新分配到新表位置,Redis 使用了两张哈希表(哈希表1和哈希表2)。

通过分步完成的渐进式 ReHash 来避免一次性迁移带来的性能问题。

渐进式 Rehash 过程:

开始 Rehash

  • Redis 的哈希表达到负载因子限制(元素数量与数组长度的比例)时,触发扩容。
  • 创建一个容量为旧表两倍的新哈希表(哈希表2)。

分步迁移数据

  • Redis 不会一次性将哈希表1中的数据全部迁移到哈希表2中,而是将迁移任务分摊到后续的增删查改操作中。
  • 每次操作触发时,从当前 rehashindex(记录迁移位置)位置开始。
  • 将哈希表1的一个桶中的所有数据迁移到哈希表2,然后将 rehashindex +1。

继续渐进式迁移

  • 随着更多的增删改查操作,每次逐步迁移哈希表1的下一个桶,直到所有元素都被迁移完成。

完成 Rehash

  • 当所有元素都迁移至哈希表2后,哈希表1被清空。
  • 哈希表2成为新的哈希表,rehashindex 被重置,后续操作在新的哈希表1上进行。

渐进式 Rehash 查询过程:

每次查询时,Redis 会先在哈希表1中查找键。

若未找到,再在哈希表2中查找。

随着 ReHash 的进行,更多数据会被迁移到哈希表2中,直到最终所有查询只需访问新表。

渐进式 Rehash 的优势:

Redis 的渐进式 ReHash 避免了一次性扩容带来的 I/O 负担和阻塞现象。

使得在大规模数据扩容时,系统仍能持续响应读写操作,避免了传统哈希表扩容对性能的明显影响。

Spring

SpringBean的初始化过程是怎么样的?

实例化:

Spring 容器创建一个 Bean 时,首先会通过反射机制调用其构造函数进行实例化。

设置属性:

在实例化之后,Spring 会为 Bean 设置属性。

这些属性通常来自于配置文件(如 XML、Java 配置或注解)。

Spring 会调用所有的 Setter 方法来设置 Bean 的属性值。

Aware接口回调:

如果 Bean 实现了某些 Aware 接口(如 BeanNameAwareBeanClassLoaderAwareBeanFactoryAware 等)。

Spring 会在设置完属性后调用相应的方法。

这些方法允许 Bean 获取一些 Spring 的上下文信息。

BeanPostProcessor前置处理:

如果有实现了 BeanPostProcessor 接口的 Bean

Spring 会调用它们的 postProcessBeforeInitialization 方法。

这可以让开发者在 Bean 初始化前进行一些自定义处理。

初始化方法:

初始化方法可以通过以下几种方式定义:

  • 实现 InitializingBean 接口的 afterPropertiesSet 方法。
  • Bean 的类中使用 @PostConstruct 注解标记一个初始化方法。
  • XML 配置或 Java 配置中通过 init-method 属性指定一个初始化方法。

BeanPostProcessor的后处理:

调用 BeanPostProcessorpostProcessAfterInitialization 方法,以允许进行后续处理。

Bean使用:

经过上述步骤后,Bean完全初始化并可以在 Spring容器中使用。

销毁过程:

当容器关闭或 Bean 被销毁时,会调用销毁方法:

  • 实现 DisposableBean 接口的 destroy 方法。
  • 使用 @PreDestroy 注解标记的销毁方法。
  • XML 配置或 Java 配置中通过 destroy-method 属性指定的销毁方法。
支付宝打赏 微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者!