对象
Redis并没有直接使用这些数据结构来实现键值对数据库, 而是基于这些数据结构创建了一个对象系统, 这个系统包含字符串对象、列表对象、哈希对象、集合对象和有序集合对象这五种类型。
typedef struct redisObject {
// 类型
unsigned type:4;
// 编码
unsigned encoding:4;
// 指向底层实现数据结构的指针
void *ptr;
// ...
} robj;
当我们对一个数据库键执行 TYPE 命令时, 命令返回的结果为数据库键对应的值对象的类型, 而不是键对象的类型。
对象类型根据使用场景的不同有多种编码方式,对应不同的底层实现方式。对象的修改可能发生编码转换。
编码对应的底层数据结构:
字符串
字符串对象的编码可以是 int
、 raw
或者 embstr
。
如果一个字符串对象保存的是整数值, 并且这个整数值可以用 long
类型来表示, 那么字符串对象会将整数值保存在字符串对象结构的 ptr
属性里面(将 void*
转换成 long
), 并将字符串对象的编码设置为 int
。
如果字符串对象保存的是一个字符串值, 并且这个字符串值的长度大于 39
字节, 那么字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串值, 并将对象的编码设置为 raw
。
如果字符串对象保存的是一个字符串值, 并且这个字符串值的长度小于等于 39
字节, 那么字符串对象将使用 embstr
编码的方式来保存这个字符串值。
embstr
编码是专门用于保存短字符串的一种优化编码方式, 这种编码和 raw
编码一样, 都使用 redisObject
结构和 sdshdr
结构来表示字符串对象, 但 raw
编码会调用两次内存分配函数来分别创建 redisObject
结构和 sdshdr
结构, 而 embstr
编码则通过调用一次内存分配函数来分配一块连续的空间, 空间中依次包含 redisObject
和 sdshdr
两个结构。
set [key] [value]
新建或更新
get [key]
del [key1] [key2]
mest [key1] [value1] [key2] [value2]
一次添加多个键值对
mget [key1] [key2]
一次查询多个键值对
列表
列表对象的编码可以是 ziplist
或者 linkedlist
。
lpush [key] [value1] [value2]
从列表头插入一个或多个元素
rpush [key] [value1] [value2]
从列表尾插入一个或多个元素
lpop [key] [count]
移除并返回列表头部的若干元素
rpop [key] [count]
移除并返回列表尾部的若干元素
lrange [key] [indexStart] [indexEnd]
返回列表指定区间内的元素,0代表第一个,-1代表倒数第一个
llen [key]
返回列表的长度。如果列表不存在,则key被解释为空列表,返回0
哈希
哈希对象的编码可以是 ziplist
或者 hashtable
。
ziplist
编码的哈希对象使用压缩列表作为底层实现, 每当有新的键值对要加入到哈希对象时, 程序会先将保存了键的压缩列表节点推入到压缩列表表尾, 然后再将保存了值的压缩列表节点推入到压缩列表表尾, 因此:
- 保存了同一键值对的两个节点总是紧挨在一起, 保存键的节点在前, 保存值的节点在后;
- 先添加到哈希对象中的键值对会被放在压缩列表的表头方向, 而后来添加到哈希对象中的键值对会被放在压缩列表的表尾方向。
hashtable
编码的哈希对象使用字典作为底层实现, 哈希对象中的每个键值对都使用一个字典键值对来保存:
- 字典的每个键都是一个字符串对象, 对象中保存了键值对的键;
- 字典的每个值都是一个字符串对象, 对象中保存了键值对的值。
**********************************************************************
hset [key] [field] [value]
hget [key] [field]
hgetall [key]
hdel [key] [field1] [field2]
hmset [key] [field1] [value1] [field2] [value2]
一次设置多个field
hmget [key] [field1] [field2]
一次查询多个field
hlen [key]
查询一个hash有几个field
hexists [key] [field]
查询一个hash是否存在某个字段
集合
集合对象的编码可以是 intset
或者 hashtable
。
intset
编码的集合对象使用整数集合作为底层实现, 集合对象包含的所有元素都被保存在整数集合里面。
hashtable
编码的集合对象使用字典作为底层实现, 字典的每个键都是一个字符串对象, 每个字符串对象包含了一个集合元素, 而字典的值则全部被设置为 NULL
。
set元素不能重复
sadd [key] [member1] [member2]
smembers [key]
sismember [key] [member]
判断是否成员
srem [key] [member1] [member2]
删除指定成员
有序集合
有序集合的编码可以是 ziplist
或者 skiplist
。
ziplist
编码的有序集合对象使用压缩列表作为底层实现, 每个集合元素使用两个紧挨在一起的压缩列表节点来保存, 第一个节点保存元素的成员(member), 而第二个元素则保存元素的分值(score)。压缩列表内的集合元素按分值从小到大进行排序, 分值较小的元素被放置在靠近表头的方向, 而分值较大的元素则被放置在靠近表尾的方向。
skiplist
编码的有序集合对象使用 zset
结构作为底层实现, 一个 zset
结构同时包含一个字典和一个跳跃表:
typedef struct zset {
zskiplist *zsl;
dict *dict;
} zset;
标签:编码,对象,Redis,列表,键值,key,字符串,数据结构 From: https://www.cnblogs.com/gcr277/p/17038261.html