Redis 使用文档Word文档格式.docx
- 文档编号:16714451
- 上传时间:2022-11-25
- 格式:DOCX
- 页数:45
- 大小:499.37KB
Redis 使用文档Word文档格式.docx
《Redis 使用文档Word文档格式.docx》由会员分享,可在线阅读,更多相关《Redis 使用文档Word文档格式.docx(45页珍藏版)》请在冰豆网上搜索。
redisDb中,dict成员是与实际存储数据相关的.dict的定义如下:
63typedefstructdictEntry
void*key;
void*val;
structdictEntry*next;
}dictEntry;
typedefstructdictType
unsignedint(*hashFunction)(constvoid*key);
void*(*keyDup)(void*privdata,constvoid*key);
void*(*valDup)(void*privdata,constvoid*obj);
int(*keyCompare)(void*privdata,constvoid*key1,constvoid*key2);
void(*keyDestructor)(void*privdata,void*key);
void(*valDestructor)(void*privdata,void*obj);
}dictType;
/*Thisisourhashtablestructure.Everydictionaryhastwoofthisaswe
*implementincrementalrehashing,fortheoldtothenewtable.*/
typedefstructdictht
dictEntry**table;
unsignedlongsize;
unsignedlongsizemask;
unsignedlongused;
}dictht;
typedefstructdict
dictType*type;
void*privdata;
dicththt[2];
intrehashidx;
/*rehashingnotinprogressifrehashidx==-1*/
intiterators;
/*numberofiteratorscurrentlyrunning*/
}dict;
dict是主要是由structdictht的哈唏表构成的,之所以定义成长度为2的(dicththt[2])哈唏表数组,是因为redis采用渐进的rehash,即当需要rehash时,每次像hset,hget等操作前,先执行N步rehash.这样就把原来一次性的rehash过程拆散到进行,防止一次性rehash期间redis服务能力大幅下降.这种渐进的rehash需要一个额外的structdictht结构来保存.
structdictht主要是由一个structdictEntry指针数组组成的,hash表的冲突是通过链表法来解决的.
structdictEntry中的key指针指向用sds类型表示的key字符串,val指针指向一个structredisObject结构体,其定义如下:
typedefstructredisObject
unsignedtype:
4;
unsignedstorage:
2;
/*REDIS_VM_MEMORYorREDIS_VM_SWAPPING*/
unsignedencoding:
unsignedlru:
22;
/*lrutime(relativetoserver.lruclock)*/
intrefcount;
void*ptr;
/*VMfieldsareonlyallocatedifVMisactive,otherwisethe
*objectallocationfunctionwilljustallocate
*sizeof(redisObjct)minussizeof(redisObjectVM),sousing
*RediswithoutVMactivewillnothaveanyoverhead.*/
}robj;
//type占4bit,用来表示key-value中value值的类型,目前redis支持:
string,list,set,zset,hash5种类型的值.
/*Objecttypes*/
#defineREDIS_STRING0
#defineREDIS_LIST1
#defineREDIS_SET2
#defineREDIS_ZSET3
#defineREDIS_HASH4
#defineREDIS_VMPOINTER8
//storage占2bit,表示此值是在内存中,还是swap在硬盘上.
//encoding占4bit,表示值的编码类型,目前有8种类型:
/*Objectsencoding.SomekindofobjectslikeStringsandHashescanbe
*internallyrepresentedinmultipleways.The‘encoding’fieldoftheobject
*issettooneofthisfieldsforthisobject.*/
#defineREDIS_ENCODING_RAW0/*Rawrepresentation*/
#defineREDIS_ENCODING_INT1/*Encodedasinteger*/
#defineREDIS_ENCODING_HT2/*Encodedashashtable*/
#defineREDIS_ENCODING_ZIPMAP3/*Encodedaszipmap*/
#defineREDIS_ENCODING_LINKEDLIST4/*Encodedasregularlinkedlist*/
#defineREDIS_ENCODING_ZIPLIST5/*Encodedasziplist*/
#defineREDIS_ENCODING_INTSET6/*Encodedasintset*/
#defineREDIS_ENCODING_SKIPLIST7/*Encodedasskiplist*/
/*如type是REDIS_STRING类型的,则其值如果是数字,就可以编码成REDIS_ENCODING_INT,以节约内存.
*如type是REDIS_HASH类型的,如果其entry小于配置值:
hash-max-zipmap-entries或value字符串的长度小于hash-max-zipmap-value,则可以编码成REDIS_ENCODING_ZIPMAP类型存储,以节约内存.否则采用Dict来存储.
*如type是REDIS_LIST类型的,如果其entry小于配置值:
list-max-ziplist-entries或value字符串的长度小于list-max-ziplist-value,则可以编码成REDIS_ENCODING_ZIPLIST类型存储,以节约内存;
否则采用REDIS_ENCODING_LINKEDLIST来存储.
*如type是REDIS_SET类型的,如果其值可以表示成数字类型且entry小于配置值set-max-intset-entries,则可以编码成REDIS_ENCODING_INTSET类型存储,以节约内存;
否则采用Dict类型来存储.
*lru:
是时间戳
*refcount:
引用次数
*void*ptr:
指向实际存储的value值内存块,其类型可以是string,set,zset,list,hash,编码方式可以是上述encoding表示的一种.
*至于一个key的value采用哪种类型来保存,完全是由客户端的指令来决定的,如hset,则值是采用REDIS_HASH类型表示的,至于那种编码(encoding),则由redis根据配置自动决定.
*/1.2Dict结构
Dict结构在<
1.1Redis内存存储结构>
;
已经描述过了,这里不再赘述.
1.3zipmap结构
如果redisObject的type成员值是REDIS_HASH类型的,则当该hash的entry小于配置值:
hash-max-zipmap-entries或者value字符串的长度小于hash-max-zipmap-value,则可以编码成REDIS_ENCODING_ZIPMAP类型存储,以节约内存.否则采用Dict来存储.
zipmap其实质是用一个字符串数组来依次保存key和value,查询时是依次遍列每个key-value对,直到查到为止.其结构示意图如下:
为了节约内存,这里使用了一些小技巧来保存key和value的长度.如果key或value的长度小于ZIPMAP_BIGLEN(254),则用一个字节来表示,如果大于ZIPMAP_BIGLEN(254),则用5个字节保存,第一个字节为保存ZIPMAP_BIGLEN(254),后面4个字节保存key或value的长度.
初始化时只有2个字节,第1个字节表示zipmap保存的key-value对的个数(如果key-value对的个数超过254,则一直用254来表示,zipmap中实际保存的key-value对个数可以通过zipmapLen()函数计算得到).
hset(nick,wuzhu)后,
第1个字节保存key-value对(即zipmap的entry数量)的数量1
第2个字节保存key_len值4
第3~6保存key“nick”
第7字节保存value_len值5
第8字节保存空闭的字节数0(当该key的值被重置时,其新值的长度与旧值的长度不一定相等,如果新值长度比旧值的长度大,则realloc扩大内存;
如果新值长度比旧值的长度小,且相差大于4bytes,则realloc缩小内存,如果相差小于4,则将值往前移,并用empty_len保存空闲的byte数)
第9~13字节保存value值“wuzhu”
hset(age,30)
插入key-value对(“age”,30)
hset(nick,tide)
插入key-value对(“nick”,”tide”),后可以看到empty_len为1,
1.4ziplist结构
如果redisObject的type成员值是REDIS_LIST类型的,则当该list的elem数小于配置值:
hash-max-ziplist-entries或者elem_value字符串的长度小于hash-max-ziplist-value,则可以编码成REDIS_ENCODING_ZIPLIST类型存储,以节约内存.否则采用Dict来存储.
ziplist其实质是用一个字符串数组形式的双向链表.其结构示意图如下
ziplistheader由3个字段组成:
ziplist_bytes:
用一个uint32_t来保存,构成ziplist的字符串数组的总长度,包括ziplistheader,
ziplist_tail_offset:
用一个uint32_t来保存,记录ziplist的尾部偏移位置.
ziplist_length:
用一个uint16_t来保存,记录ziplist中elem的个数
ziplistnode也由3部分组成:
prevrawlen:
保存上一个ziplistnode的占用的字节数,包括:
保存prevarwlen,currawlen的字节数和elemvalue的字节数.
currawlen&
encoding:
当前elemvalue的raw形式存款所需的字节数及在ziplist中保存时的编码方式(例如,值可以转换成整数,如示意图中的”1024”,raw_len是4字节,但在ziplist保存时转换成uint16_t来保存,占2个字节).
(编码后的)value
可以通过prevrawlen和currawlen&
encoding来遍列ziplist.
ziplist还能到一些小技巧来节约内存.
len的存储:
如果len小于ZIP_BIGLEN(254),则用一个字节来保存;
否则需要5个字节来保存,第1个字节存ZIP_BIGLEN,作为标识符.
value的存储:
如果value是数字类型的,则根据其值的范围转换成ZIP_INT_16B,ZIP_INT_32B或ZIP_INT_64B来保存,否则用raw形式保存.
1.5adlist结构
38typedefstructlistNode
structlistNode*prev;
structlistNode*next;
void*value;
}listNode;
typedefstructlistIter
listNode*next;
intdirection;
}listIter;
typedefstructlist
listNode*head;
listNode*tail;
void*(*dup)(void*ptr);
void(*free)(void*ptr);
int(*match)(void*ptr,void*key);
unsignedintlen;
}list;
常见的双向链表,不作分析.
1.6intset结构
intset是用一个有序的整数数组来实现集合(set).structintset的定义如下:
11typedefstructintset
uint32_tencoding;
uint32_tlength;
int8_tcontents[];
}intset;
encoding:
来标识数组是int16_t类型,int32_t类型还是int64_t类型的数组.至于怎么先择是那种类型的数组,是根据其保存的值的取值范围来决定的,初始化时是int16_t,根据set中的最大值在[INT16_MIN,INT16_MAX],[INT32_MIN,INT32_MAX],[INT64_MIN,INT64_MAX]的那个取值范围来动态确定整个数组的类型.例如set一开始是int16_t类型,当一个取值范围在[INT32_MIN,INT32_MAX]的值加入到set时,则将保存set的数组升级成int32_t的数组.
length:
表示set中值的个数
contents:
指向整数数组的指针
1.7zset结构
首先,介绍一下skiplist的概念,然后再分析zset的实现.
1.7.1SkipList介绍
1.7.1.1有序链表
1)SearchingakeyinaSortedlinkedlist
7//Searchinganelementx
cell*p=head;
while(p->
next->
key<
x)p=p->
next;
returnp;
Note:
wereturntheelementproceedingeithertheelementcontainingx,orthesmallestelementwithakeylargerthanx(ifxdoesnotexists)
2)insertingakeyintoaSortedlinkedlist
//Toinsert35-
p=find(35);
CELL*p1=(CELL*)malloc(sizeof(CELL));
p1->
key=35;
next=p->
p->
next=p1;
3)deleteingakeyfromasortedlist
//Todelete37-
p=find(37);
CELL*p1=p->
next;
next=p1->
free(p1);
1.7.1.2SkipList(跳跃表)定义
SKIPLIST:
Adatastructureformaintaingasetofkeysinasortedorder.
Consistsofseverallevels.
Allkeysappearinlevel1
Eachlevelisasortedlist.
Ifkeyxappearsinleveli,thenitalsoappearsinalllevelsbelowi
Anelementinlevelipoints(viadownpointer)totheelementwiththesamekeyinthelevelbelow.
Ineachlevelthekeysandappear.(Inourimplementation,INT_MINandINT_MAX
Toppointstothesmallestelementinthehighestlevel.
1.7.1.3SkipList(跳跃表)操作
1)AnemptySkipList
2)Findinganelementwithkeyx
p=top
While
(1)
If(p->
down==NULL)returnp->
next
p=p->
down;
}
Observethatwereturnx,ifexists,orsucc(x)ifxisnotintheSkipList
3)InsertingnewelementX
Determinekthenumberoflevelsinwhichxparticipates(explainedlater)
Dofind(x),andinsertxtotheappropriateplacesinthelowestklevels.(aftertheelementsatwhichthesearchpathturnsdownorterminates)
Example–inserting119.k=2
Ifkislargerthanthecurrentnumberoflevels,addnewlevels(andupdatetop)
Example–inser(119)whenk=4
Determiningk
k–thenumberoflevelsatwhichanelementxparticipate.
UsearandomfunctionOurRnd()—returns1or0(True/False)withequalprobability.
k=1;
While(OurRnd())k++;
Deleteingakeyx
Findxinallthelevelsitparticipates,anddeleteitusingthestanda
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Redis 使用文档 使用 文档