关于Redis中的数据类型

一、 Redis常用数据类型

Redis最为常用的数据类型主要有以下:

  • String

  • Hash

  • List

  • Set

  • Sorted set

一张图表达问题的本色

图一:

图片 1

图二:

图片 2

代码:

/* Object types */
#define REDIS_STRING 0
#define REDIS_LIST 1
#define REDIS_SET 2
#define REDIS_ZSET 3
#define REDIS_HASH 4

/* Objects encoding. Some kind of objects like Strings and Hashes can be
 * internally represented in multiple ways. The 'encoding' field of the object
 * is set to one of this fields for this object. */
#define REDIS_ENCODING_RAW 0     /* Raw representation */
#define REDIS_ENCODING_INT 1     /* Encoded as integer */
#define REDIS_ENCODING_HT 2      /* Encoded as hash table */
#define REDIS_ENCODING_ZIPMAP 3  /* Encoded as zipmap */
#define REDIS_ENCODING_LINKEDLIST 4 /* Encoded as regular linked list */
#define REDIS_ENCODING_ZIPLIST 5 /* Encoded as ziplist */
#define REDIS_ENCODING_INTSET 6  /* Encoded as intset */
#define REDIS_ENCODING_SKIPLIST 7  /* Encoded as skiplist */
#define REDIS_ENCODING_EMBSTR 8  /* Embedded sds string encoding */

redisobject

/* The actual Redis Object */
#define REDIS_LRU_BITS 24
#define REDIS_LRU_CLOCK_MAX ((1<<REDIS_LRU_BITS)-1) /* Max value of obj->lru */
#define REDIS_LRU_CLOCK_RESOLUTION 1000 /* LRU clock resolution in ms */
typedef struct redisObject {
    unsigned type:4;
    unsigned encoding:4;
    unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */
    int refcount;
    void *ptr;
} robj;

struct sdshdr {
    unsigned int len;
    unsigned int free;
    char buf[];
};

二、各类数据类型应用和达成情势

robj *createObject(int type, void *ptr) {
    robj *o = zmalloc(sizeof(*o));
    o->type = type;    
    o->encoding = REDIS_ENCODING_RAW;
    o->ptr = ptr;
    o->refcount = 1;   

    /* Set the LRU to the current lruclock (minutes resolution). */
    o->lru = LRU_CLOCK();
    return o;    
}

1、String

  • 比方一个字符串保存的是整数值,并且这么些整数值可以用long类型表示,那么字符串对象会把整数值保存到ptr所指的空间里,编码设为int

  • 如借使平凡字符串,并且长度当先39字节,使用redis自己完成的SDS类型

  • 借使是普普通通字符串,并且长度小于等于39字节,选拔embstr存储

    #define REDIS_ENCODING_EMBSTR_SIZE_LIMIT 39
    robj createStringObject(char ptr, size_t len) {

    if (len <= REDIS_ENCODING_EMBSTR_SIZE_LIMIT)
        return createEmbeddedStringObject(ptr,len);
    else                   
        return createRawStringObject(ptr,len);
    

    }

embstr 编码是尤其用于保存短字符串的一种优化编码格局,
那种编码和 raw 编码一样,
都使用 redisObject 结构和 sdshdr 结构来代表字符串对象,
但 raw 编码会调用一次内存分配函数来分别创设 redisObject 结构和 sdshdr 结构,
而 embstr 编码则通过调用一回内存分配函数来分配一块两次三番的长空,
空间中逐一包蕴 redisObject 和 sdshdr 多个结构

使用场景:String是最常用的一种数据类型,普通的key/ value
存储都可以归为此类.即可以完全得以达成如今 Memcached
的效能,并且效用更高。还足以大快朵颐Redis的定时持久化,操作日志及
Replication等功效。

除却提供与 Memcached 一样的get、set、incr、decr
等操作外,Redis还提供了下边一些操作:

  • 取得字符串长度

  • 往字符串append内容

  • 设置和获取字符串的某一段内容

  • 设置及得到字符串的某一位(bit)

  • 批量设置一多样字符串的始末

    127.0.0.1:6379> set name “This is a test”
    OK
    127.0.0.1:6379> get name
    “This is a test”

2、Hash

默许使用 REDIS_ENCODING_ZIPLIST 编码, 当以下任何一个尺度被满意时,
程序将编码从 REDIS_ENCODING_ZIPLIST 切换为 REDIS_ENCODING_HT

  • 哈希表中某个键或某个值的长度领先 server.hash_max_ziplist_value (默许值为 64 )

  • 减掉列表中的节点数量超过 server.hash_max_ziplist_entries (默许值为 512 )

选取场景:在Memcached中,我们平常将一部分结构化的新闻打包成HashMap,在客户端系列化后存储为一个字符串的值,比如用户的昵称、年龄、性别、积分等,那时候在须求修改其中某一项时,平日须要将所有值取出反系列化后,修改某一项的值,再连串化存储回去。那样不但增大了支付,也不适用于有些或者出现操作的场馆(比如三个冒出的操作都需要修改积分)。而Redis的Hash结构得以使您像在数据库中Update一个属性一样只修改某一项属性值。

俺们简要举个实例来叙述下Hash的采纳场景

比如我们要存储一个用户音信目标数据,包含以下音讯:用户ID为寻找的key,存储的value用户对象涵盖姓名,年龄,生日等音信,如若用平时的key/value结构来存储,主要有以下2种存储形式:

率先种艺术将用户ID作为查找key,把其余信息封装成一个目的以系列化的点子存储,那种办法的通病是,扩张了种类化/反系列化的付出,并且在急需修改其中一项音信时,须要把方方面面对象取回,并且修改操作须求对现身举办爱惜,引入CAS等复杂问题。

其次种艺术是那些用户音信目的有多少成员就存成多少个key-value对儿,用用户ID+对应属性的名号作为唯一标识来取得对应属性的值,尽管省去了种类化费用和出现问题,可是用户ID为重新存储,假设存在大气如此的数码,内存浪费仍旧卓殊惊人的。

那么Redis提供的Hash很好的缓解了那个题材,Redis的Hash实际是里面存储的Value为一个HashMap,并提供了直接存取那些Map成员的接口

Key依旧是用户ID,
value是一个Map,这几个Map的key是成员的属性名,value是属性值,那样对数据的修改和存取都得以直接通过其内部Map的Key(Redis里称其中Map的key为field),
也就是透过 key(用户ID) + field(属性标签)
就足以操作对应属性数据了,既不须求再行存储数据,也不会带来种类化和产出修改决定的题目,很好的化解了问题。

这里还要需求注意,Redis提供了接口(hgetall)可以平昔取到全部的属性数据,可是一旦中间Map的成员很多,那么涉及到遍历整个内部Map的操作,由于Redis单线程模型的由来,那一个遍历操作可能会比较耗时,而另其余客户端的哀求完全不响应,那点要求万分小心。

 

127.0.0.1:6379> HMSET user:1 username root password 123456 score 100
OK
127.0.0.1:6379> hgetall user:1
1) "username"
2) "root"
3) "password"
4) "123456"
5) "score"
6) "100"

3、List

默认使用 REDIS_ENCODING_ZIPLIST 编码, 当以下任意一个规范被满意时,
列表会被更换成 REDIS_ENCODING_LINKEDLIST 编码

  • 往列表新添加一个字符串值且那一个字符串的长度超过 server.list_max_ziplist_value (默认值为 64 )

  • ziplist 包括的节点当先 server.list_max_ziplist_entries (默认值为 512 )

运用场景:Redis
list的使用场景非凡多,也是Redis最要紧的数据结构之一,比如twitter的关切列表,粉丝列表等都能够用Redis的list结构来得以完毕。Lists
就是链表,相信略有数据结构知识的人都应有能明了其结构。使用Lists结构,我们得以轻松地落到实处最新信息名次等功能。Lists的另一个用到就是音信队列,

可以运用Lists的PUSH操作,将任务存在Lists中,然后工作线程再用POP操作将任务取出举行实施。Redis还提供了操作Lists中某一段的api,你可以一贯询问,删除Lists中某一段的元素。

127.0.0.1:6379> lpush list mysql
(integer) 1
127.0.0.1:6379> lpush list mssql
(integer) 2
127.0.0.1:6379> lpush list oracle
(integer) 3
127.0.0.1:6379> lrange list 0 3
1) "oracle"
2) "mssql"
3) "mysql"

4、Set

  • 一经第二个元素得以代表为 long long 类型值(也即是,它是一个整数),
    那么聚集的早先编码为 REDIS_ENCODING_INTSET

  • 不然集合的伊始编码为 REDIS_ENCODING_HT

借使一个汇集使用 REDIS_ENCODING_INTSET 编码,
那么当以下任何一个标准化被知足时,
那几个集合会被转换成 REDIS_ENCODING_HT 编码

  • intset 保存的整数值个数超越 server.set_max_intset_entries (默许值为 512 )

  • 意欲往集合里添加一个新因素,并且这么些元素不可能被代表为 long long 类型(也即是,它不是一个整数)

选取场景:Redis
set对外提供的效益与list类似是一个列表的效益,特殊之处在于set是足以活动排重的,当你需求仓储一个列表数据,又不指望出现重复数据时,set是一个很好的选用,并且set提供了判断某个成员是还是不是在一个set集合内的紧要性接口,那几个也是list所不能提供的。

Sets
集合的定义就是一堆不重复值的整合。利用Redis提供的Sets数据结构,可以储存一些集合性的数额,比如在新浪应用中,可以将一个用户所有的爱惜人存在一个会面中,将其具有粉丝存在一个见面。Redis还为集合提供了求交集、并集、差集等操作,可以丰盛有利的兑现如一道关切、共同喜好、二度好友等成效,对上面的装有集合操作,你还足以选择不相同的通令接纳将结果再次来到给客户端或者存集到一个新的成团中。

127.0.0.1:6379> sadd sets  redis 
(integer) 1
127.0.0.1:6379> sadd sets mongodb
(integer) 1
127.0.0.1:6379> sadd sets hbase
(integer) 1
127.0.0.1:6379> smembers sets
1) "hbase"
2) "redis"
3) "mongodb"

5、Sorted Set

即使第三个元素符合以下规则的话,
就创办一个 REDIS_ENCODING_ZIPLIST 编码的静止集

  • 服务器属性 server.zset_max_ziplist_entries 的值超出 0 (默认为 128 ),元素的 member 长度小于服务器属性 server.zset_max_ziplist_value 的值(默认为 64 )

  • 要不,程序就创制一个 REDIS_ENCODING_SKIPLIST 编码的雷打不动集

对于一个 REDIS_ENCODING_ZIPLIST 编码的有序集, 只要满意以下任一条件,
就将它转换为 REDIS_ENCODING_SKIPLIST 编码

  • ziplist 所保存的因素数量超越服务器属性 server.zset_max_ziplist_entries 的值(默许值为 128 )

  • 新添美元素的 member 的尺寸领先服务器属性 server.zset_max_ziplist_value 的值(默许值为 64 )

使用情状:Redis sorted
set的行使意况与set类似,不一致是set不是全自动有序的,而sorted
set可以由此用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即活动排序。当你要求一个依样画葫芦的还要不另行的汇集列表,那么可以选取sorted
set数据结构,比如twitter 的public
timeline可以以发布时间作为score来存储,那样获取时就是自行按时间排好序的。

除此以外还足以用Sorted
Sets来做带权重的行列,比如一般信息的score为1,首要新闻的score为2,然后工作线程能够选择按score的倒序来收获工作职责。让首要的天职优先执行。

127.0.0.1:6379> zadd ssets 0 redis 
(integer) 1
127.0.0.1:6379> zadd ssets 0 mongodb
(integer) 1
127.0.0.1:6379> zadd ssets 0 hbase
(integer) 1
127.0.0.1:6379> zrangebyscore ssets 0 10
1) "hbase"
2) "mongodb"
3) "redis"

三、其他

1、Pub/Sub

Pub/Sub
从字面上领会就是公布(Publish)与订阅(Subscribe),在Redis中,你可以设定对某一个key值进行音信发表及新闻订阅,当一个key值上拓展了音信公布后,所有订阅它的客户端都会吸纳相应的音讯。这一功力最强烈的用法就是作为实时音信系统,比如平时的当即聊天,群聊等成效

2、Transactions

什么人说NoSQL都不协助工作,即使Redis的Transactions提供的并不是从严的ACID的事务(比如一串用EXEC提交实施的授命,在实践中服务器宕机,那么会有局地命令执行了,剩下的没执行),不过这一个Transactions仍然提供了主导的一声令下打包举办的职能(在服务器不出问题的意况下,可以确保接二连三串的命令是各种在共同实施的,中间有会有任何客户端命令插进来执行)。Redis还提供了一个沃·特(W·at)ch功用,你可以对一个key进行沃特ch,然后再履行Transactions,在那进程中,假如那几个沃特ched的值进行了改动,那么那么些Transactions会发现并拒绝执行

网站地图xml地图