概要
首先,redis是一种"键值对"(key-value)数据库,也就是说,redis中存储的用户数据都是以key-value的方式存在的,而这些键值对存储于哈希表,这也解释了为什么redis提供的set、lpush、hset、sadd、zadd等添加数据的命令的格式都基于key-value格式
其次,为什么redis选择键值对呢?或者说redis为什么选择哈希表呢?
哈希表的插入、查找时间复杂度是O(1),因为哈希表就是一个数组,这种高效的数据结构满足了redis对于高性能的需求
redis存储结构
图中涉及到的数据结构的名字和⽤途:
- redisDb 结构,表示 Redis 数据库的结构,结构体⾥存放了指向了 dict 结构的指针;
- dict 结构,结构体⾥存放了 2 个哈希表,正常情况下都是⽤「哈希表1」,「哈希表2」只有在 rehash 的时候才⽤,具体什么是 rehash,后面本⽂的哈希表数据结构会讲;
- ditctht 结构,表示哈希表的结构,结构⾥存放了哈希表数组,数组中的每个元素都是指向⼀个哈希表 节点结构(dictEntry)的指针;
- dictEntry 结构,表示哈希表节点的结构,结构⾥存放了 void * key 和 void * value 指针, *key 指向 的是 String 对象,⽽ *value 则可以指向 String 对象,也可以指向集合类型的对象,⽐如 List 对 象、Hash 对象、Set 对象和 Zset 对象
特别说明下,void * key 和 void * value 指针指向的是 Redis 对象,Redis 中的每个对象都由 redisObject 结构表示,如下图:
重点说说其中的哈希表结构 ditctht和dictEntry
ditctht表示哈希表,也就是一个存放哈希节点(dictEntry)的数组
dictEntry表示哈希节点,一个节点存放着void* key和void* value两个成员,redis规定其中的key指向string字符串,而value可以指向多种类型的对象(string、list、hash、set…)
1.为什么key只能指向string对象?
键的唯一性和简单性
键(key)必须是字符串:
- 在 Redis 中,所有的键都是字符串。这是设计上的选择,旨在简化和统一键的管理。字符串键使得哈希计算、比较和查找等操作变得简单而高效。
- 统一使用字符串作为键,可以避免不同数据类型之间的兼容性问题。字符串键可以被唯一地标识和比较,确保哈希表中的键是唯一的。
2.value指向不同类型的对象时有什么区别?
a.string
当value指向string对象时,通过key查找到的value就是一个value指针,value指向一个string对象
b.list
当value指向list对象时,由于list可以存储多个节点值,value指向的就是一条链表的头节点,通过key查找到的value就是一个链表的头节点
c.hash
当value指向hash对象时,情况变得复杂,由于value本身作为一个key-value中的value,此时value指向另一个哈希表,这个哈希表中存储着若干键值对
所以查找一个hash对象时,命令也变得不同:hget key field ,通过key可以找到对应的value,这个value指向一个哈希表,因此不能找到具体的数据,所以需要第二个参数field作为key,在value所指向的哈希表中找到对应的value
也就是说当value是一个hash对象时,该对象的value存储在一个二级嵌套的hash表中