面试题答案
一键面试1. Redis字典底层数据结构简介
- dictEntry:Redis字典中的每个键值对是一个
dictEntry
结构体,包含键、值指针,以及指向下一个dictEntry
的指针(用于解决哈希冲突,采用链地址法)。 - 哈希表:Redis使用
dict
结构体来表示字典,其中包含两个哈希表ht[0]
和ht[1]
。哈希表是一个数组,数组元素是指向dictEntry
的指针。
2. 高并发读写场景下优化字典相关操作提升内存使用效率策略
- 减少哈希冲突:
- 优化哈希函数:选择更均匀分布的哈希函数,使键在哈希表中更均匀地分布,减少链表长度,降低内存浪费。例如,Redis默认使用的哈希函数在分配内存时已经考虑了一定的均匀性,但在特定场景下可根据键的特征进一步优化。
- 动态调整哈希表大小:当哈希表的负载因子(已使用的桶数与总桶数的比例)超过一定阈值(如Redis默认1.0),进行扩展操作,将哈希表大小翻倍。当负载因子小于一定阈值(如0.1),进行收缩操作,减少哈希表大小,释放内存。
- 内存回收与重用:
- 及时释放删除的键值对内存:当删除一个键值对时,不仅要从哈希表中移除对应的
dictEntry
,还要释放该dictEntry
占用的内存以及键和值占用的内存(如果是动态分配的)。 - 对象共享:对于一些常用的小对象(如短字符串、整数),可以采用对象共享机制。例如,Redis中对于范围在
-5
到10000
之间的整数对象,会进行共享,减少内存占用。
- 及时释放删除的键值对内存:当删除一个键值对时,不仅要从哈希表中移除对应的
3. 对系统性能和稳定性的影响
- 性能影响:
- 优化哈希函数:更优的哈希函数虽然可以减少哈希冲突,但可能增加计算哈希值的时间开销。不过总体上,减少链表长度带来的查找时间优化通常能弥补这部分开销,提升整体读写性能。
- 动态调整哈希表大小:扩展和收缩操作需要重新计算键的哈希值并重新分配内存,这是一个相对耗时的操作,可能会导致短时间内性能下降。但合理设置阈值可以在性能和内存使用之间找到平衡,从长期看有助于提升性能。
- 内存回收与重用:及时释放内存和对象共享,减少了内存碎片和重复分配,有助于提升内存分配效率,进而提升读写性能。
- 稳定性影响:
- 优化哈希函数:稳定的哈希函数能保证数据分布均匀,避免因哈希冲突导致的链表过长,影响系统稳定性。
- 动态调整哈希表大小:如果阈值设置不合理,频繁的扩展和收缩操作可能导致系统抖动,影响稳定性。因此,需要根据实际应用场景进行调优。
- 内存回收与重用:及时释放内存可避免内存泄漏,对象共享机制增强了系统对内存的管理能力,有助于提升系统稳定性。