1、Redis的一些基本数据结构
typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
* LFU data (least significant 8 bits frequency
* and most significant 16 bits access time). */
int refcount;
void *ptr;
} robj;
typedef struct redisDb {
dict *dict; /* The keyspace for this DB */
dict *expires; /* Timeout of keys with a timeout set */
dict *blocking_keys; /* Keys with clients waiting for data (BLPOP)*/
dict *ready_keys; /* Blocked keys that received a PUSH */
dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */
int id; /* Database ID */
long long avg_ttl; /* Average TTL, just for stats */
} redisDb;
typedef struct dict {
dictType *type;
void *privdata;
dictht ht[2];
long rehashidx; /* rehashing not in progress if rehashidx == -1 */
unsigned long iterators; /* number of iterators currently running */
} dict;
typedef struct dictType {
uint64_t (*hashFunction)(const void *key);
void *(*keyDup)(void *privdata, const void *key);
void *(*valDup)(void *privdata, const void *obj);
int (*keyCompare)(void *privdata, const void *key1, const void *key2);
void (*keyDestructor)(void *privdata, void *key);
void (*valDestructor)(void *privdata, void *obj);
} dictType;
typedef struct dictht {
dictEntry **table;
unsigned long size;
unsigned long sizemask;
unsigned long used;
} dictht;
typedef struct dictEntry {
void *key;
union {
void *val;
uint64_t u64;
int64_t s64;
double d;
} v;
struct dictEntry *next;
} dictEntry;
2、scan的实现
命令:scan 0 [match pattern] [count 10]
1、scanCommand
解析游标是否合法;
不合法直接返回。
2、scanGenericCommand
创建list;
解析参数是否含有count、match选项;
从c->db->dict获取到哈希表;
遍历集合,直到‘游标为0’或‘最大迭代次数为0’或‘返回的key大于count’就停止遍历;
将返回的keys和obj放入到一个指针数组中;
3、dictScan
如果dict->ht[0].used + dict->ht[1].used == 0,说明数据库为空,则return;
通过dict->rehashidx是否为-1判断数据库是否在进行rehash;
否:直接遍历ht[0],将key添加到之前的list中;
是:先遍历小集合,在遍历大集合
重新计算游标返回;
过滤元素,不符合pattern的、过期的key;
回复客户端;
//下面的回调忽略了无关代码
void scanCallback(void *privdata, const dictEntry *de) {
void **pd = (void**) privdata;
list *keys = pd[0];
robj *o = pd[1];
robj *key, *val = NULL;
if (o == NULL) {
sds sdskey = dictGetKey(de);
key = createStringObject(sdskey, sdslen(sdskey));
}
listAddNodeTail(keys, key);
}