Valkey源码剖析(18):对象引用计数¶
Valkey服务器通过对象的引用计数特性来管理其自行创建的对象,其中对象的计数值就记录在server.h/serverObject结构的refcount属性中:
struct serverObject {
// ...
// 引用计数
unsigned refcount : OBJ_REFCOUNT_BITS;
// ...
};
举个例子,当Valkey服务器在运行过程中需要创建一个对象以保存某项信息的时候,它通常会调用相应的对象构造函数,这些函数会将对象的refcount设置为1。
之后,如果服务器内有其他调用者需要用到刚刚创建的对象,那么服务器将调用object.c/incrRefCount()函数以增加相应对象的引用计数,比如把计数值从1增加为2,等等:
void incrRefCount(robj *o) {
if (o->refcount < OBJ_FIRST_SPECIAL_REFCOUNT) {
// 正常对计数增一
o->refcount++;
} else {
// 处理特殊对象(它们无法增加计数)
if (o->refcount == OBJ_SHARED_REFCOUNT) {
/* Nothing to do: this refcount is immutable. */
} else if (o->refcount == OBJ_STATIC_REFCOUNT) {
serverPanic("You tried to retain an object allocated in the stack");
}
}
}
在此之后,每个调用者将对对象做相应的处理,并在使用完对象之后,调用object.c/decrRefCount()函数以减少对象的引用计数。当对象的计数值降低至0的时候,decrRefCount()函数将调用相应的对象析构函数以自动释放对象:
void decrRefCount(robj *o) {
if (o->refcount == 1) {
// 当引用计数降为0的时候,释放对象
if (o->ptr != NULL) {
// 基于对象的类型调用不同的对象析构函数
switch (o->type) {
case OBJ_STRING: freeStringObject(o); break;
case OBJ_LIST: freeListObject(o); break;
case OBJ_SET: freeSetObject(o); break;
case OBJ_ZSET: freeZsetObject(o); break;
case OBJ_HASH: freeHashObject(o); break;
case OBJ_MODULE: freeModuleObject(o); break;
case OBJ_STREAM: freeStreamObject(o); break;
default: serverPanic("Unknown object type"); break;
}
}
zfree(o);
} else {
// 如果对象当前的引用计数大于1,那么将其计数减一
if (o->refcount <= 0) serverPanic("decrRefCount against refcount <= 0");
if (o->refcount != OBJ_SHARED_REFCOUNT) o->refcount--;
}
}
以上就是Valkey通过引用计数技术管理对象生命周期的原理。
黄健宏
2026.1.12