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
接口(如BeanNameAware
、BeanClassLoaderAware
、BeanFactoryAware
等)。
Spring
会在设置完属性后调用相应的方法。这些方法允许
Bean
获取一些Spring
的上下文信息。
BeanPostProcessor
前置处理:
如果有实现了
BeanPostProcessor
接口的Bean
。
Spring
会调用它们的postProcessBeforeInitialization
方法。这可以让开发者在
Bean
初始化前进行一些自定义处理。
初始化方法:
初始化方法可以通过以下几种方式定义:
- 实现
InitializingBean
接口的afterPropertiesSet
方法。- 在
Bean
的类中使用@PostConstruct
注解标记一个初始化方法。- 在
XML
配置或 Java 配置中通过init-method
属性指定一个初始化方法。
BeanPostProcessor
的后处理:
调用
BeanPostProcessor
的postProcessAfterInitialization
方法,以允许进行后续处理。
Bean
使用:
经过上述步骤后,
Bean
完全初始化并可以在Spring
容器中使用。
销毁过程:
当容器关闭或
Bean
被销毁时,会调用销毁方法:
- 实现
DisposableBean
接口的destroy
方法。- 使用
@PreDestroy
注解标记的销毁方法。- 在
XML
配置或Java
配置中通过destroy-method
属性指定的销毁方法。