Redis String
对于Redis数据库保存的键值对来说,键总是一个字符串对象,而值可以是字符串对象,列表对象,哈希对象,集合对象或者有序集合对象中的其中一种。
Redis中有很多地方都使用了字符串,例如所有的key,String类型的value,Redis自己定义了简单动态字符串(simple dynamic string,SDS)的抽象类型,并将SDS用作Redis的默认字符串表示。在 Redis 里面, C 字符串只会作为字符串字面量(string literal), 用在一些无须对字符串值进行修改的地方, 比如打印日志:
redisLog(REDIS_WARNING,"Redis is now ready to exit, bye bye...");
Redis SDS介绍
struct sdshdr{
//记录buf数组中已使用字节的数量
//等于SDS所保存的字符串的长度
int len;
//记录buf数组中未使用字节的数量
int free;
//字节数组,用于保存字符串
char buf[];
}
更加详细的介绍参照Redis设计与实现。
Redis键相关操作
Redis字符串相关操作
Redis对象的类型与编码
Redis使用对象表示数据库中的键和值,每次当我们在Redis的数据库中新创建一个键值对时,我们至少创建两个对象,一个对象用作键值对的键,一个对象用作键值对的值。
以下SET命令在数据库中创建了一个新的键值对,其中键值对的键时包含了字符串值 "msg"
的对象,而键值对的值则是一个包含了字符串的值"hello word"
的对象,Redis中每个对象都由一个redisObject
结构表示,该结构中和保存数据有关的三个属性分别是type
属性、encoding
属性,ptr
属性
typedef struct redisObject{
//类型
unsigned type:4;
//编码
unsigned encoding:4;
//指向底层实现数据结构的指针
void *ptr;
}robj;
type属性记录了对象的类型,这个属性的值可以是下图中列表的某一个
对象的ptr
指针指向对象的底层实现数据结构,而这些数据结构有对象的encoding
属性决定。encoding
属性记录了对象所使用的编码,也即是说这个对象使用了什么数据结构作为对象的底层实现。
每种类型的对象都至少使用了两种不同的编码,
Redis字符串对象的编码可以是int
、raw
、embstr
。
如果一个字符串对象保存的是整数值, 并且这个整数值可以用 long
类型来表示, 那么字符串对象会将整数值保存在字符串对象结构的 ptr
属性里面(将 void*
转换成 long
), 并将字符串对象的编码设置为 int
。
如果字符串对象保存的是一个字符串值, 并且这个字符串值的长度大于 39
字节, 那么字符串对象将使用一个简单动态字符串(SDS)来保存这个字符串值, 并将对象的编码设置为 raw
。
举个例子, 如果我们执行以下命令, 那么服务器将创建一个如图 8-2 所示的 raw
编码的字符串对象作为 story
键的值:
如果字符串对象保存的是一个字符串的值,并且这个字符串的值的长度小于等于39
字节,那么字符串对象将使用empstr
编码方式来保存这个字符串的值。
embstr
编码是专门用于保存短字符串的一种优化编码方式, 这种编码和 raw
编码一样, 都使用 redisObject
结构和 sdshdr
结构来表示字符串对象, 但 raw
编码会调用两次内存分配函数来分别创建 redisObject
结构和 sdshdr
结构, 而 embstr
编码则通过调用一次内存分配函数来分配一块连续的空间, 空间中依次包含 redisObject
和 sdshdr
两个结构。
mbstr
编码的字符串对象在执行命令时, 产生的效果和 raw
编码的字符串对象执行命令时产生的效果是相同的, 但使用 embstr
编码的字符串对象来保存短字符串值有以下好处:
embstr
编码将创建字符串对象所需的内存分配次数从raw
编码的两次降低为一次。- 释放
embstr
编码的字符串对象只需要调用一次内存释放函数, 而释放raw
编码的字符串对象需要调用两次内存释放函数。 - 因为
embstr
编码的字符串对象的所有数据都保存在一块连续的内存里面, 所以这种编码的字符串对象比起raw
编码的字符串对象能够更好地利用缓存带来的优势。
String对象的相关操作针对不同编码的具体实现