从源码深入理解Redis
创新互联公司专业为企业提供汤原网站建设、汤原做网站、汤原网站设计、汤原网站制作等企业网站建设、网页设计与制作、汤原企业网站模板建站服务,十多年汤原做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。
Redis是一个开源的内存数据结构存储系统,常用于缓存、消息队列、持久化存储等场景。它具有高性能、可扩展、支持丰富的数据类型等特点,被广泛应用于互联网领域。为了更好地理解Redis,我们需要从源码层面去探究Redis的实现。
Redis源码的目录结构
Redis的源码目录结构如下:
![](https://img-blog.csdnimg.cn/20220103232221984.png)
src目录下是Redis的核心代码,包含了Redis的命令实现、数据类型实现以及网络事件处理等核心代码。deps目录下是Redis所依赖的第三方库,如hiredis、Jemalloc等。tests目录下是Redis的测试代码,包含了Redis各个功能点的自动化测试用例。
Redis源码中的数据结构
Redis的内部实现主要依赖于数据结构,下面我们将介绍Redis源码中常见的四种数据结构:字符串、列表、哈希、集合。
1. 字符串
Redis中的字符串类型保存的是二进制安全的字符串。在Redis的源码中,字符串类型的操作可以在src/string.c文件中找到,其中最常用的操作为set、get。
set操作的主要实现如下:
“`c
void setCommand(client *c) {
setGenericCommand(c,SET_NO_FLAGS);
}
void setGenericCommand(client *c, int flags) {
robj *expire = getExpire(c->db,c->argv,flags);
int j;
c->argv[c->argc] = expire ? expire : &shared.nullbulk;
c->argc++;
/* Store the value */
setKey(c->db,c->argv[1],c->argv[2]);
/* Signal modified key */
signalModifiedKey(c,c->db,c->argv[1]);
/* Notify a generic string-key BL pop event */
notifyKeyspaceEvent(NOTIFY_STRING,”set”,c->argv[1],c->db->id);
if (expire) setExpire(c,c->db,c->argv[1],expire);
server.dirty++;
}
get操作的主要实现如下:
```c
void getCommand(client *c) {
getGenericCommand(c);
}
void getGenericCommand(client *c) {
robj *o;
/* Try to get the value from the cache */
if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL ||
o == shared.sentinel)
return;
addReplyBulk(c,o);
}
2. 列表
Redis中的列表类型使用双向链表实现,支持在列表头部和列表尾部插入和删除元素。在Redis的源码中,列表类型的操作可以在src/adlist.c文件中找到,其中最常用的操作为listAddNodeHead、listAddNodeTl、listDelNode。
listAddNodeHead操作的主要实现如下:
“`c
list *listAddNodeHead(list *list, void *value) {
listNode *node;
if ((node = zmalloc(sizeof(*node))) == NULL)
return NULL;
node->value = value;
if (list->len == 0) {
list->head = list->tl = node;
node->prev = node->next = NULL;
} else {
node->prev = NULL;
node->next = list->head;
list->head->prev = node;
list->head = node;
}
list->len++;
return list;
}
listDelNode操作的主要实现如下:
```c
list *listDelNode(list *list, listNode *node) {
/* Fix head pointer if needed. */
if (node->prev == NULL)
list->head = node->next;
else
node->prev->next = node->next;
/* Fix tl pointer if needed. */
if (node->next == NULL)
list->tl = node->prev;
else
node->next->prev = node->prev;
if (list->free) list->free(node->value);
zfree(node);
list->len--;
return list;
}
3. 哈希
Redis中的哈希类型使用字典结构实现,支持在哈希表中添加、删除、查找元素。在Redis的源码中,哈希类型的操作可以在src/dict.c文件中找到,其中最常用的操作为dictAdd、dictFind、dictDelete。
dictAdd操作的主要实现如下:
“`c
int dictAdd(dict *d, void *key, void *val)
{
dictht *ht;
dictEntry *entry;
if (dictIsRehashing(d)) _dictRehashStep(d);
/* Get the index of the new element, or -1 if
* the element already exists. */
if ((entry = dictFind(d,key)) == NULL) {
if (dictIsRehashing(d) && dictAdd(d->ht[1],key,val) == DICT_OK)
incrRefCount(key); /* Prevent ht[0] from freeing the key. */
else {
entry = dictCreateEntry(d,key);
dictSetEntryVal(entry,val);
dictHashTableInsert(d,entry);
}
return 1;
} else {
dictSetEntryVal(entry,val);
return 0;
}
}
dictDelete操作的主要实现如下:
```c
int dictDelete(dict *ht, const void *key) {
unsigned int h, idx;
dictEntry *he, *prevHe;
if (ht->size == 0) return DICT_ERR;
if (dictIsRehashing(ht)) _dictRehashStep(ht);
h = dictHashKey(ht,key);
/* Search in both tables if we are rehashing. */
for (idx = 0; idx
he = ht->table[idx] + (h & ht->sizemask);
prevHe = NULL;
while(he) {
if (key==he->key || dictCompareKeys(ht,key,he->key)) {
/* Unlink the element from the list */
if (prevHe)
prevHe->next = he->next;
else
ht->table[idx] = he->next;
if (ht->keyDestructor) {
ht->keyDestructor(he->key);
}
if (ht->valDestructor) {
ht->valDestructor(he->v.val);
}
zfree(he);
ht->used--;
return DICT_OK;
}
prevHe = he;
he = he->next;
}
if (!dictIsRehashing(ht)) break;
}
return DICT_ERR; /* not found */
}
4. 集合
Redis中的集合类型使用intset或者dict结构实现,使用dict结构实现的集合称为hashset。在Redis的源码中,集合类型的操作可以在src/intset.c文件和src/dict.c文件中找到,其中最常用的操作为setAdd、setIsMember、setRemove。
setAdd操作的主要实现如下:
“`c
int setTypeAdd(robj *subject, robj *value) {
long long llval;
uint8_t success = 0;
if (subject->encoding == OBJ_INTSET) {
if (isObjectRepresentableAsLongLong(value,&llval) != C_OK)
return 0;
subject->ptr = intsetAdd((intset*)subject->ptr,llval,&success);
if (success) signalModifiedObject(subject);
return success;
} else if (subject->encoding == OBJ_HT) {
dict *ht = subject->ptr;
dictEntry *de;
de = dictAddOrFind(ht,value);
if (de == NULL)
return 0;
if (dictFind(ht,value) == NULL) {
incrRefCount(value);
dictSetKey(ht,de,value);
signalModifiedObject(subject);
}
return 1;
} else {
serverPanic(“Unknown set encoding”);
}
}
setRemove操作的主要实现如下:
```c
int setTypeRemove(robj *setobj, robj *value) {
long long llval;
dict *ht;
dictEntry *de;
if (setobj->encoding == OBJ_INTSET) {
if (isObjectRepresentableAsLongLong(value,&llval) != C_OK) return 0;
if (intsetRemove((intset*)setobj->ptr,llval,NULL)) {
if (intsetLen((intset*)setobj->ptr) == 0) {
setobj->ptr = intsetResize(setobj
香港服务器选创新互联,2H2G首月10元开通。
创新互联(www.cdcxhl.com)互联网服务提供商,拥有超过10年的服务器租用、服务器托管、云服务器、虚拟主机、网站系统开发经验。专业提供云主机、虚拟主机、域名注册、VPS主机、云服务器、香港云服务器、免备案服务器等。
文章题目:从源码深入理解Redis(redis源码深入理解)
标题来源:http://www.mswzjz.cn/qtweb/news45/280895.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能