此篇为对redis五大数据类型中list的分析,希望能有所帮助
List API
listTypeGet函数
robj *listTypeGet(listTypeEntry *entry) {
robj *value = NULL;
/* 检查编码类型是否为 quicklist (快速列表) */
if (entry->li->encoding == OBJ_ENCODING_QUICKLIST) {
/* 元素的值保存在 value 中 */
if (entry->entry.value) {
/* value = 使用当前元素创建的字符串对象 */
value = createStringObject((char *)entry->entry.value,
entry->entry.sz);
/* 元素的值保存在 longval 中 */
} else {
/* value = 使用当前(整型)元素创建的字符串对象 */
value = createStringObjectFromLongLong(entry->entry.longval);
}
} else {
serverPanic("Unknown list encoding");
}
return value;
}
分析:
利用createStringObject函数和createStringObjectFromLongLong函数,检查编码类型并获取元素的值
listTypeInsert函数
void listTypeInsert(listTypeEntry *entry, robj *value, int where) {
/* 检查编码类型是否为 quicklist (快速列表) */
if (entry->li->encoding == OBJ_ENCODING_QUICKLIST) {
/* 获取解码后的 value(实际上是让编码为INT的 value 转为字符串形式(raw 或 embstr))*/
value = getDecodedObject(value);
/* 令 str = value(字符串值),len = value 字符串长度 */
sds str = value->ptr;
size_t len = sdslen(str);
/* 在 entry 后方插入元素 */
if (where == LIST_TAIL) {
quicklistInsertAfter(entry->li->iter, &entry->entry, str, len);
/* 在 entry 前方插入元素 */
} else if (where == LIST_HEAD) {
quicklistInsertBefore(entry->li->iter, &entry->entry, str, len);
}
/* value 的被引用次数 -1 ,value 被引用次数为0时将被释放 */
decrRefCount(value);
} else {
serverPanic("Unknown list encoding");
}
}
分析:
对entry的插入操作,在 entry 的位置前或后方插入元素 value
listTypeReplace函数
void listTypeReplace(listTypeEntry *entry, robj *value) {
/* 检查编码类型是否为 quicklist (快速列表) */
if (entry->li->encoding == OBJ_ENCODING_QUICKLIST) {
/* 获取解码后的 value(实际上是让编码为INT的 value 转为字符串形式(raw 或 embstr))*/
value = getDecodedObject(value);
/* 令 str = value(字符串值),len = value 字符串长度 */
sds str = value->ptr;
size_t len = sdslen(str);
/* 用 value 替换 entry 中的元素 */
quicklistReplaceEntry(entry->li->iter, &entry->entry, str, len);
/* value 的被引用次数 -1 ,value 被引用次数为0时将被释放 */
decrRefCount(value);
} else {
serverPanic("Unknown list encoding");
}
}
分析:
替换 entry 中的元素
listTypeEqual函数
int listTypeEqual(listTypeEntry *entry, robj *o) {
/* 检查编码类型是否为 quicklist (快速列表) */
if (entry->li->encoding == OBJ_ENCODING_QUICKLIST) {
/* 使用断言确保 o 内部编码为字符串(raw 或 embstr) */
serverAssertWithInfo(NULL,o,sdsEncodedObject(o));
/* 调用比较函数进行比较,相同返回1,不相同返回0 */
return quicklistCompare(&entry->entry,o->ptr,sdslen(o->ptr));
} else {
serverPanic("Unknown list encoding");
}
}
分析:
在当前位置比较两个元素是否相同
listTypeDelete函数
void listTypeDelete(listTypeIterator *iter, listTypeEntry *entry) {
/* 检查编码类型是否为 quicklist (快速列表) */
if (entry->li->encoding == OBJ_ENCODING_QUICKLIST) {
/* 调用删除函数将元素删除 */
quicklistDelEntry(iter->iter, &entry->entry);
} else {
serverPanic("Unknown list encoding");
}
}
分析:
删除元素
listTypeDup函数
/* This is a helper function for the COPY command.
* Duplicate a list object, with the guarantee that the returned object
* has the same encoding as the original one.
*
* The resulting object always has refcount set to 1 */
robj *listTypeDup(robj *o) {
robj *lobj;
/* 使用断言确保 o 类型为列表 */
serverAssert(o->type == OBJ_LIST);
switch (o->encoding) {
/* 检查编码类型是否为 quicklist (快速列表) */
case OBJ_ENCODING_QUICKLIST:
/* 创建 o 的副本 lobj */
lobj = createObject(OBJ_LIST, quicklistDup(o->ptr));
lobj->encoding = o->encoding;
break;
default:
serverPanic("Unknown list encoding");
break;
}
return lobj;
}
分析:
检查编码类型,辅助copy命令。复制一个列表对象,并保证返回的对象具有与原始对象相同的编码。返回的对象总是将 refcount 设置为1
listTypeDelRange函数
/* Delete a range of elements from the list. */
int listTypeDelRange(robj *subject, long start, long count) {
/* 检查编码类型是否为 quicklist (快速列表) */
if (subject->encoding == OBJ_ENCODING_QUICKLIST) {
/* 调用范围删除函数进行删除 */
return quicklistDelRange(subject->ptr, start, count);
} else {
serverPanic("Unknown list encoding");
}
}
分析:
在列表中删除一个指定范围内的元素
总结:
本篇分析了 listTypeGet函数、listTypeInsert函数、listTypeReplace函数、listTypeEqual函数等API,即将元素的增删改操作具体分析,有助于更好地理解list类型的操作。