这个面试题主要想了解我们对Redis有没有去深入的了解和理解它底层的原理。
Redis是由C语言编写的。Redis支持5种数据类型,以K-V形式进行存储,K是String类型的,V支持5种不同的数据类型,分别是:string,list,hash,set,sorted set,每一种数据结构都有其特定的应用场景。从内部实现的角度来看是如何更好的实现这些数据类型。Redis底层数据结构有以下数据类型:简单动态字符串(SDS),链表,字典,跳跃表,整数集合,压缩列表,对象。接下来,了解下Redis是怎么通过这些数据结构来实现value的5种类型的。
简单动态字符串(simple dynamic string SDS)
String的数据类型是由SDS实现的。Redis并没有采用C语言的字符串表示,而是自己构建了一种名为SDS的抽象类型,并将SDS作为Redis的默认字符串表示。
redis>SET msg "hello world"OK
上边设置key=msg,value=hello world的键值对,它们的底层存储是:键(key)是字符串类型,其底层实现是一个保存着“msg”的SDS。值(value)是字符串类型,其底层实现是一个保存着“hello world”的SDS。
注意:SDS除了用于实现字符串类型,还被用作AOF持久化时的缓冲区。
为什么要使用SDS:
我们一定会思考,redis为什么不使用C语言的字符串而是费事搞一个SDS呢,这是因为C语言用N+1的字符数组来表示长度为N的字符串,这样做在获取字符串长度,字符串扩展等操作方面效率较低,并且无法满足redis对字符串在安全性、效率以及功能方面的要求。
1.获取字符串长度(SDS O(1))
在C语言字符串中,为了获取一个字符串的长度,必须遍历整个字符串,时间复杂度为O(1),而SDS中,有专门用于保存字符串长度的变量,所以可以在O(1)时间内获得。
2.防止缓冲区溢出
C字符串,容易导致缓冲区溢出,假设在程序中存在内存紧邻的字符串s1和s2,s1保存redis,s2保存MongoDB
如果我们现在将s1 的内容修改为redis cluster,但是又忘了重新为s1 分配足够的空间,这时候就会出现以下问题:
因为s1和s2是紧邻的,所以原本s2 中的内容已经被S1的内容给占领了,s