hget命令实现代码:
void hgetCommand(client *c) { robj *o; // key不存在,返回空 if ((o = lookupKeyReadOrReply(c,c->argv[1],shared.nullbulk)) == NULL || checkType(c,o,OBJ_HASH)) return; addHashFieldToReply(c, o, c->argv[2]->ptr); }hget命令的实现最终是调用addHashFieldToReply函数(代码如下),该函数是通过判断哈希对象的编码来决定使用什么函数来获取哈希对象具体field的值,其他命令的实现也是大同小异。
static void addHashFieldToReply(client *c, robj *o, sds field) { int ret; if (o == NULL) { addReply(c, shared.nullbulk); return; } // 根据底层不同编码获取field的值 if (o->encoding == OBJ_ENCODING_ZIPLIST) { unsigned char *vstr = NULL; unsigned int vlen = UINT_MAX; long long vll = LLONG_MAX; ret = hashTypeGetFromZiplist(o, field, &vstr, &vlen, &vll); if (ret < 0) { addReply(c, shared.nullbulk); } else { if (vstr) { addReplyBulkCBuffer(c, vstr, vlen); } else { addReplyBulkLongLong(c, vll); } } } else if (o->encoding == OBJ_ENCODING_HT) { sds value = hashTypeGetFromHashTable(o, field); if (value == NULL) addReply(c, shared.nullbulk); else addReplyBulkCBuffer(c, value, sdslen(value)); } else { serverPanic("Unknown hash encoding"); } } 总结redis中的很多操作都是基于上面介绍的redis对象,了解这些对象的底层实现,可以为之后更多的redis特性做准备。