redis代码结构之三类型库-list
来源:互联网 发布:淘宝工具软件 编辑:程序博客网 时间:2024/06/05 05:47
redis代码结构之三类型库-list
1. 类型库概述
下面介绍redis核心的内容以及所支持的数据类型及操作。首先看一下相应的数据结构:
- typedef char *sds; //该文件返回的基本上都是sds,即char *,也是实际存储内容的地址。
- struct sdshdr {
- int len; //内容拥有的空间,不包括该结构的本身的大小,也不包括buf最后的结束符’\0’
- int free; //剩下的可用内存空间,buf中可能有一些没有使用,这些的长度就是free的值
- char buf[]; //实际的存储内容=strlen(buf)+free=len
- };
该类型是redis使用最多的类型,它类似c++的string类型。相应的函数包括sds sdsnewlen(const void *init, size_t initlen) ,它首先申请sh = zmalloc(sizeof(struct sdshdr)+initlen+1);内存(注:sizeof(struct sdshdr)=8),initlen就是sdshdr->len,而init则会被memcpy到sdshdr->buf里,并且此时sdshdr->free为0。最后返回(char*)sh->buf,即实际内容的地址。其它的就类似于string的方法。
- typedef struct redisObject {
- unsigned type:4;
- unsigned storage:2; /* REDIS_VM_MEMORY or REDIS_VM_SWAPPING */
- unsigned encoding:4;
- unsigned lru:22; /* lru time (relative to server.lruclock) */
- int refcount;
- void *ptr;
- } robj;
该结构定义了redis的操作对象的抽象数据类型。
Type:定义该数据的类型,当前的redis支持5种数据类型:REDIS_STRING、REDIS_LIST、REDIS_SET、REDIS_ZSET、REDIS_HASH。
Storage:定义数据当前的位置内存还是硬盘的swap。
Encoding:定义数据类型使用的编码方式或者叫内存的存储方式,当前redis支持8种encoding。各种类型及所支持的编码见下表:
类型
REDIS_STRING(t_string.c)
REDIS_LIST(t_list.c,ziplist.c)
REDIS_SET(t_set.c)
REDIS_ZSET(t_zset.c)
REDIS_HASH(t_hash.c)
命令
set,mset
lpush,rpush,lpop,rpop
sadd
zadd
Hset,hmset
编码
REDIS_ENCODING_RAW, REDIS_ENCODING_INT
REDIS_ENCODING_ZIPLIST, REDIS_ENCODING_LINKEDLIST
REDIS_ENCODING_HT, REDIS_ENCODING_INTSET
REDIS_ENCODING_ZIPLIST, REDIS_ENCODING_SKIPLIST
REDIS_ENCODING_HT, REDIS_ENCODING_ZIPMAP
数据的类型是由用户的命令决定的,另外所有的key都使用REDIS_STRING类型(在dbAdd的时候再提取出实际的内容sds copy = sdsdup(key->ptr);,这个就是真正保存到dict里的key值),并且它的encoding只为REDIS_ENCODING_RAW;而编码则是由server根据配置及当前的系统情况进行选择的(这个条件我们在后面的每种类型中分别介绍)。
Lru:
Refcount:该对象的引用个数
Ptr:指向实际存储的内容
Server在接收到client请求的时候总是先把命令的所有成员转换成type=REDIS_STRING,encoding = REDIS_ENCODING_RAW为的robj类型保存到client->argv[]里(0是命令,1是key,2,3..是value【2可能是expire值】,这个过程在processInlineBuffer或者processMultibulkBuffer函数里完成)。同时在调用每个命令相应的处理函数的时候,大多数命令都会对value先进行一个tryObjectEncoding,即判断该value是否可表示为long类型string2l(s,sdslen(s),&value),如果可以的话就使用shared.integers[value],或者encoding = REDIS_ENCODING_INT,代码如下:
- if (!string2l(s,sdslen(s),&value)) return o;
- …
- if (server.maxmemory == 0 && value >= 0 && value < REDIS_SHARED_INTEGERS &&
- pthread_equal(pthread_self(),server.mainthread)) {
- decrRefCount(o);
- incrRefCount(shared.integers[value]);
- return shared.integers[value];
- } else {
- o->encoding = REDIS_ENCODING_INT;
- sdsfree(o->ptr);
- o->ptr = (void*) value;
- return o;
- }
- 下面我们分别介绍五种数据类型的相应结构及操作。(每种类型的操作指令及含义可参考<a href="http://www.w3ccollege.org/redis/redis-command-manual.html">http://www.w3ccollege.org/redis/redis-command-manual.html</a>)
- 2. REDIS_STRING(t_string.c)该类型的命令包括:set,setnx,setex,mset,incr,append等等。这里我们只介绍set命令,它相应的命令回调函数为
- <pre class="cpp" name="code">setCommand(redisClient *c) {
- c->argv[2] = tryObjectEncoding(c->argv[2]);
- setGenericCommand(c,0,c->argv[1],c->argv[2],NULL);
- }</pre>该类型的大多数命令都是通过调用setGenericCommand函数为内部接口:<br>
- <pre class="cpp" name="code">void setGenericCommand(redisClient *c, int nx, robj *key, robj *val, robj *expire) {
- long seconds = 0; /* initialized to avoid an harmness warning */
- if (expire) {//设置过期时间的操作
- if (getLongFromObjectOrReply(c, expire, &seconds, NULL) != REDIS_OK)
- return;
- if (seconds <= 0) {
- addReplyError(c,"invalid expire time in SETEX");
- return;
- }
- }
- //如果该key存在,并且命令要求在key不存在时才set,此时则返回
- if (lookupKeyWrite(c->db,key) != NULL && nx) {
- addReply(c,shared.czero);
- return;
- }
- setKey(c->db,key,val); //向字典中追加key,val
- server.dirty++;//设置dirty持久化时使用
- if (expire) setExpire(c->db,key,time(NULL)+seconds);//向expire dict中添加该事件
- addReply(c, nx ? shared.cone : shared.ok);
- }</pre>这就是set操作的过程,很简单。其内部的setKey就是调用db.c,dict.c的函数。
- <pre></pre>
- <pre></pre>
- redis代码结构之三类型库-list
- redis代码结构之三类型库-list
- redis代码结构之三类型库-list
- redis代码结构之三类型库-string
- redis之list类型
- NoSQL数据库之Redis数据库管理三(list类型)
- Redis数据类型之LIST类型
- Redis之List 列表类型
- Redis 数据类型之List类型
- Redis之List类型操作
- 三:redis的List类型相关操作
- 3.Redis数据类型之List类型
- redis学习笔记之list类型
- 详解Redis之list类型及操作
- 缓存技术Redis之list类型
- 03Redis数据类型之List类型
- golang-redis之list类型简单操作
- Redis学习之list类型及操作
- POJ 2531 Network Saboteur
- redis代码结构之二net,main,event
- HP QC IE11不支持( win7 64位 无法安装)解决方法
- tyvj P1001 第k极值
- IOS 开发中判断字符串是否为空字符的方法
- redis代码结构之三类型库-list
- 第17周项目6-学生成绩统计(1)
- STM32中GPIO的8种工作模式!(转)
- ceph存储 centos7搭建samba服务
- 深入理解C++的动态绑定和静态绑定
- redis代码结构之三类型库-list
- PendingIntent getActivity
- Oracle XE Installation in Linux CentOS
- cocos2dx3.2 往模板build_native.py加入java库脚本