面试题答案
一键面试Redis的SDS结构特点
- 灵活的动态内存分配:SDS结构可以根据存储的字符串长度动态调整内存空间,避免了C语言传统字符串(以
\0
结尾的字符数组)在长度变化时频繁手动管理内存的麻烦。它通过记录自身长度,在需要扩展或收缩时能够高效地进行内存重分配。 - 减少内存碎片:SDS在内存分配时采用预分配策略。当对SDS进行扩展操作时,不仅会分配当前所需的空间,还会额外分配一定量的未使用空间(小于1MB时,额外分配与现有长度相同的空间;大于等于1MB时,额外分配1MB空间)。这样在后续追加内容时,如果所需空间小于预分配空间,则无需再次进行内存分配,从而减少了内存碎片的产生。
- 获取长度时间复杂度为O(1):C语言字符串获取长度需要遍历整个字符串直到遇到
\0
,时间复杂度为O(n)。而SDS结构中直接记录了字符串的长度,获取长度操作时间复杂度为O(1),这对于一些需要频繁获取字符串长度的操作(如计算哈希值等)效率更高。 - 二进制安全:SDS可以存储任意二进制数据,不像C语言字符串以
\0
作为结束标志,这使得SDS可以存储包含\0
的数据,在处理一些非文本数据(如图片、音频等)时更为适用。
SDS对常用缓存淘汰策略的影响或作用
- LRU(最近最少使用)策略
- 内存占用影响淘汰决策:由于SDS结构有预分配空间,可能导致单个缓存对象(以SDS存储的字符串)占用的内存比实际存储内容略大。在LRU策略下,内存占用是一个重要考量因素。如果系统内存紧张,占用内存较大的SDS对象即使最近使用过,也可能因为其相对较高的内存消耗而更容易被淘汰,以便为其他更“轻量级”的缓存对象腾出空间。
- 长度获取高效性与淘汰评估:SDS获取长度时间复杂度为O(1)。在评估缓存对象的重要性时,可能会结合对象的大小(通过获取长度可得知)等因素。高效的长度获取操作使得LRU策略在评估SDS对象时能够快速得到大小信息,从而更准确地做出淘汰决策。
- LFU(最不经常使用)策略
- 频率统计与内存占用:LFU策略需要统计每个缓存对象的访问频率。SDS结构由于其预分配空间,不同的SDS对象可能因为存储内容长度不同以及预分配空间不同,导致占用内存差异较大。在内存资源有限的情况下,即使两个SDS对象访问频率相同,占用内存大的SDS对象可能会被优先淘汰,因为它相对占用了更多的宝贵内存资源。
- 数据结构特性与频率记录:SDS的二进制安全特性使得它可以存储各种复杂的数据结构用于记录访问频率。例如,可以在SDS中存储自定义的频率统计数据,并且由于其灵活的内存管理和二进制安全特性,能够方便地对这些统计数据进行更新和维护,为LFU策略提供准确的频率信息。