diff options
author | antirez <antirez@gmail.com> | 2017-03-27 15:26:56 +0200 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2017-03-27 16:37:22 +0200 |
commit | 1409c545da7861912acef4f42c4932f6c23e9937 (patch) | |
tree | 6f8a68a70c28de3c299663470427756166d47cd7 /src/db.c | |
parent | 94751543b0a15ea333dab3121fa32747cf59de8f (diff) | |
download | redis-1409c545da7861912acef4f42c4932f6c23e9937.tar.gz |
Cluster: hash slots tracking using a radix tree.
Diffstat (limited to 'src/db.c')
-rw-r--r-- | src/db.c | 101 |
1 files changed, 48 insertions, 53 deletions
@@ -1301,90 +1301,85 @@ int *migrateGetKeys(struct redisCommand *cmd, robj **argv, int argc, int *numkey /* Slot to Key API. This is used by Redis Cluster in order to obtain in * a fast way a key that belongs to a specified hash slot. This is useful - * while rehashing the cluster. */ -void slotToKeyAdd(robj *key) { + * while rehashing the cluster and in other conditions when we need to + * understand if we have keys for a given hash slot. */ +void slotToKeyUpdateKey(robj *key, int add) { unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr)); + unsigned char buf[64]; + unsigned char *indexed = buf; + size_t keylen = sdslen(key->ptr); + + server.cluster->slots_keys_count[hashslot] += add ? 1 : -1; + if (keylen+2 > 64) indexed = zmalloc(keylen+2); + indexed[0] = (hashslot >> 8) & 0xff; + indexed[1] = hashslot & 0xff; + memcpy(indexed+2,key->ptr,keylen); + if (add) { + raxInsert(server.cluster->slots_to_keys,indexed,keylen+2,NULL); + } else { + raxRemove(server.cluster->slots_to_keys,indexed,keylen+2); + } + if (indexed != buf) zfree(indexed); +} - sds sdskey = sdsdup(key->ptr); - zslInsert(server.cluster->slots_to_keys,hashslot,sdskey); +void slotToKeyAdd(robj *key) { + slotToKeyUpdateKey(key,1); } void slotToKeyDel(robj *key) { - unsigned int hashslot = keyHashSlot(key->ptr,sdslen(key->ptr)); - zslDelete(server.cluster->slots_to_keys,hashslot,key->ptr,NULL); + slotToKeyUpdateKey(key,0); } void slotToKeyFlush(void) { - zslFree(server.cluster->slots_to_keys); - server.cluster->slots_to_keys = zslCreate(); + raxFree(server.cluster->slots_to_keys); + server.cluster->slots_to_keys = raxNew(); + memset(server.cluster->slots_keys_count,0, + sizeof(server.cluster->slots_keys_count)); } /* Pupulate the specified array of objects with keys in the specified slot. * New objects are returned to represent keys, it's up to the caller to * decrement the reference count to release the keys names. */ unsigned int getKeysInSlot(unsigned int hashslot, robj **keys, unsigned int count) { - zskiplistNode *n; - zrangespec range; + raxIterator iter; int j = 0; - - range.min = range.max = hashslot; - range.minex = range.maxex = 0; - - n = zslFirstInRange(server.cluster->slots_to_keys, &range); - while(n && n->score == hashslot && count--) { - keys[j++] = createStringObject(n->ele,sdslen(n->ele)); - n = n->level[0].forward; + unsigned char indexed[2]; + + indexed[0] = (hashslot >> 8) & 0xff; + indexed[1] = hashslot & 0xff; + raxStart(&iter,server.cluster->slots_to_keys); + raxSeek(&iter,indexed,2,">="); + while(count-- && raxNext(&iter,NULL,0,NULL)) { + if (iter.key[0] != indexed[0] || iter.key[1] != indexed[1]) break; + keys[j++] = createStringObject((char*)iter.key+2,iter.key_len-2); } + raxStop(&iter); return j; } /* Remove all the keys in the specified hash slot. * The number of removed items is returned. */ unsigned int delKeysInSlot(unsigned int hashslot) { - zskiplistNode *n; - zrangespec range; + raxIterator iter; int j = 0; + unsigned char indexed[2]; - range.min = range.max = hashslot; - range.minex = range.maxex = 0; + indexed[0] = (hashslot >> 8) & 0xff; + indexed[1] = hashslot & 0xff; + raxStart(&iter,server.cluster->slots_to_keys); + while(server.cluster->slots_keys_count[hashslot]) { + raxSeek(&iter,indexed,2,">="); + raxNext(&iter,NULL,0,NULL); - n = zslFirstInRange(server.cluster->slots_to_keys, &range); - while(n && n->score == hashslot) { - sds sdskey = n->ele; - robj *key = createStringObject(sdskey,sdslen(sdskey)); - n = n->level[0].forward; /* Go to the next item before freeing it. */ + robj *key = createStringObject((char*)iter.key+2,iter.key_len-2); dbDelete(&server.db[0],key); decrRefCount(key); j++; } + raxStop(&iter); return j; } unsigned int countKeysInSlot(unsigned int hashslot) { - zskiplist *zsl = server.cluster->slots_to_keys; - zskiplistNode *zn; - zrangespec range; - int rank, count = 0; - - range.min = range.max = hashslot; - range.minex = range.maxex = 0; - - /* Find first element in range */ - zn = zslFirstInRange(zsl, &range); - - /* Use rank of first element, if any, to determine preliminary count */ - if (zn != NULL) { - rank = zslGetRank(zsl, zn->score, zn->ele); - count = (zsl->length - (rank - 1)); - - /* Find last element in range */ - zn = zslLastInRange(zsl, &range); - - /* Use rank of last element, if any, to determine the actual count */ - if (zn != NULL) { - rank = zslGetRank(zsl, zn->score, zn->ele); - count -= (zsl->length - rank); - } - } - return count; + return server.cluster->slots_keys_count[hashslot]; } |