2021开工第一天,就有小伙伴私信我,还给我分享了一道他面阿里的 redis 题( 这家伙绝比已经拿到年终奖了 ),我看了以后觉得挺有意思,题目很简单,是那种典型的似懂非懂,常常容易被大家忽略的问题。这里整理出来分享一下,顺便自己巩固一下基础,希望对正在面试和想要面试的兄弟有点帮助。
redis
题目大致是这样的
面试官:了解 redis 的 String 数据结构底层实现嘛?
String
铁子:当然知道,是基于 SDS 实现的
SDS
面试官: redis 是用 C 语言开发的,那为啥不直接用 C 的字符串,还单独设计 SDS 这样的结构呢?
C
铁子:·····
“其实看得出面试官是想看看,铁子是只停留在redis的使用层面,还是对底层数据结构有过更深入的研究,面试嘛都爱这样问大家都懂得。
我们知道 redis 是用 C 写的,但它却没有完全直接使用 C 的字符串,而是自己又重新构建了一个叫简单动态字符串 SDS (simple dynamic string)的抽象类型。
redis 也支持使用 C 语言的传统字符串,只不过会用在一些不需要对字符串修改的地方,比如静态的字符输出。
而我们开发中使用 redis ,往往会经常性的修改字符串的值,这个时候就会用 SDS 来表示字符串的值了。有一点值得 注意 :在redis数据库中, key-value 键值对含有字符串值的,都是由 SDS 来实现的。
key-value
比如:在 redis 执行一个最简单的 set 命令,这时 redis 会新建一个键值对。
set
127.0.0.1:6379> set xiaofu "程序员内点事"
此时键值对的 key 和 value 都是一个字符串对象,而对象的底层实现分别是两个保存着字符串 xiaofu 和 程序员内点事 的 SDS 结构。
key
value
xiaofu
程序员内点事
再比如:我向一个列表中压入数据,redis 又会新建一个键值对。
127.0.0.1:6379> lpush xiaofu "程序员内点事" "程序员小富"
这时候键值对的键和上边一样,还是一个由SDS实现的字符串对象,键值对的值是一个包含两个字符串对象的列表对象了,而这两个对象的底层也是由SDS实现。
一个SDS值的数据结构,主要由 len 、 free 、 buf[] 这三个属性组成。
len
free
buf[]
struct sdshdr{ int free; // buf[]数组未使用字节的数量