设为首页 收藏本站
查看: 523|回复: 0

[经验分享] Redis代码阅读2--Redis数据结构之链表

[复制链接]

尚未签到

发表于 2016-12-18 11:17:31 | 显示全部楼层 |阅读模式
   Redis

是一个开源的高性能key-value数据库,其很大程度上弥补了memeched这类key-value存储的不足(除了支持String外,还支持Hash,Set,sorted set, List),在部分场合对关系型数据库也起到了很好的补充作用。因为Redis的代码量并不多,因为我逐步阅读了其源代码,以期能对其有深入的理解。首先介绍Redis支持的各种数据结构。
  Redis中的链表是双向链表,这一点可以由 adlist.h 中代码得出:

typedef struct listNode {
struct listNode *prev;
struct listNode *next;
void *value;
} listNode;
typedef struct listIter {
listNode *next;
int direction;
} listIter;
typedef struct list {
listNode *head;
listNode *tail;
void *(*dup)(void *ptr);
void (*free)(void *ptr);
int (*match)(void *ptr, void *key);
unsigned int len;
} list;

  struct list通过head 和tail这两个指针维护了链表的头、尾节点。ListNode通过prev和next使得链表成为一个双向链表。Struct List里面的dup、free和match这三个函数指针用于配置复制、释放和匹配三个功能。比如listSetMatchMethod就是用来设置match方法的。
  Redis里的List这一数据结构和我们常说的数据结构里面的链表很相似,同样有在头、尾节点增加Node,删除Node,查找Node及Index等功能。
  Redis里面操作list的命令有RPUSH,LPUSH,LSET,LLEN等。Redis中负责实现这些命令的API就在t_list.c。下面就以RPUSH为例,来说明当客户端执行RPUSH命令时,Redis是如何通过list 的API去执行list的listAddNodeTail方法的。
  在Redis.c里面,有一个Struct里面叫readonlyCommandTable。这个struct将Redis的各种命令和Redis里面各种命令对应的函数关联起来。比如:{"rpush",rpushCommand,-3,REDIS_CMD_DENYOOM,NULL,1,1,1}。
  Redis Server接收各个Client传过来的各种命令是通过networking.c里面的代码来完成的。具体如何解析和执行各种Command以后会单独拎出来讲。这里主要简单介绍下其流程。
  processInputBuffer-->processCommand-->lookupCommand.这里的lookupCommand就是根据Command的名字从readonlyCommandTable找出该Command对应的方法。比如,Client执行RPUSH命令,则这里的lookupCommand找到的是rpushCommand。

void rpushCommand(redisClient *c) {
pushGenericCommand(c,REDIS_TAIL);
}
void pushGenericCommand(redisClient *c, int where) {
int j, addlen = 0, pushed = 0;
robj *lobj = lookupKeyWrite(c->db,c->argv[1]);
int may_have_waiting_clients = (lobj == NULL);
if (lobj && lobj->type != REDIS_LIST) {
addReply(c,shared.wrongtypeerr);
return;
}
for (j = 2; j < c->argc; j++) {
c->argv[j] = tryObjectEncoding(c->argv[j]);
if (may_have_waiting_clients) {
if (handleClientsWaitingListPush(c,c->argv[1],c->argv[j])) {
addlen++;
continue;
} else {
may_have_waiting_clients = 0;
}
}
if (!lobj) {
lobj = createZiplistObject();
dbAdd(c->db,c->argv[1],lobj);
}
listTypePush(lobj,c->argv[j],where);
pushed++;
}
addReplyLongLong(c,addlen + (lobj ? listTypeLength(lobj) : 0));
if (pushed) signalModifiedKey(c->db,c->argv[1]);
server.dirty += pushed;
}
void listTypePush(robj *subject, robj *value, int where) {
/* Check if we need to convert the ziplist */
listTypeTryConversion(subject,value);
if (subject->encoding == REDIS_ENCODING_ZIPLIST &&
ziplistLen(subject->ptr) >= server.list_max_ziplist_entries)
listTypeConvert(subject,REDIS_ENCODING_LINKEDLIST);
if (subject->encoding == REDIS_ENCODING_ZIPLIST) {
int pos = (where == REDIS_HEAD) ? ZIPLIST_HEAD : ZIPLIST_TAIL;
value = getDecodedObject(value);
subject->ptr = ziplistPush(subject->ptr,value->ptr,sdslen(value->ptr),pos);
decrRefCount(value);
} else if (subject->encoding == REDIS_ENCODING_LINKEDLIST) {
if (where == REDIS_HEAD) {
listAddNodeHead(subject->ptr,value);
} else {
listAddNodeTail(subject->ptr,value);
}
incrRefCount(value);
} else {
redisPanic("Unknown list encoding");
}
}
  在t_list.c里面,rpushCommand-->pushGenericCommand-->listTypePush。listTypePush里面通过方向变量where来判断是在head还是在tail插入新的Node。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-315970-1-1.html 上篇帖子: redis的操作 下篇帖子: redis on window 安装
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表