Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
c45570f4
Commit
c45570f4
authored
Jan 26, 2023
by
Vitaly Arbuzov
Browse files
Make random dict selection fair
parent
2a9c77a2
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/db.c
View file @
c45570f4
...
...
@@ -387,17 +387,26 @@ robj *dbRandomKey(redisDb *db) {
/* Return random non-empty dictionary from this DB. */
dict *getRandomDict(redisDb *db) {
if (db->dict_count == 1) return db->dict[0];
int
i
=
0
,
r
=
0
;
for
(
int
j
=
0
;
j
<
CLUSTER_SLOTS
;
j
++
)
{
/* Skip empty dicts or if we want only rehashing dicts and the dict isn't rehashing. */
if
(
dictSize
(
db
->
dict
[
j
])
==
0
)
continue
;
if
(
i
==
0
||
(
rand
()
%
(
i
+
1
))
==
0
)
{
r
=
j
;
/* Select K-th non-empty bucket with 1/K probability, this keeps balanced probabilities for all non-empty buckets. */
unsigned long long target = rand();
/* If number of keys is greater than max target value, then we should call target once more and get more entropy. */
if (db->key_count > RAND_MAX) {
target <<= 32;
target |= rand();
}
unsigned long long int key_count = dbSize(db);
target = key_count ? target % key_count : 0; /* Random key index in range [0..KEY_COUNT), or 0 if db is empty. */
/* In linearly enumerated key space, find a slot that contains target key. */
dbIterator dbit;
dbInitIterator(&dbit, db);
dict *d = NULL;
while ((d = dbNextDict(&dbit))) {
unsigned long long int ds = dictSize(d);
if (target < ds) { /* Found dict that contains target key. */
break;
}
i
++
;
target -= ds
;
}
return
d
b
->
dict
[
r
]
;
return d;
}
/* Helper for sync and async delete. */
...
...
@@ -427,6 +436,7 @@ int dbGenericDelete(redisDb *db, robj *key, int async, int flags) {
* the key, because it is shared with the main dictionary. */
if (dictSize(db->expires) > 0) dictDelete(db->expires,key->ptr);
dictTwoPhaseUnlinkFree(d,de,plink,table);
db->key_count--;
return 1;
} else {
return 0;
...
...
src/server.h
View file @
c45570f4
...
...
@@ -960,6 +960,7 @@ typedef struct redisDb {
list *rehashing; /* List of dictionaries in this DB that are currently rehashing. */
int dict_count; /* Indicates total number of dictionaires owned by this DB, 1 dict per slot in cluster mode. */
int command_slot; /* Slot that is used by the current command that uses DB, -1 if cluster mode is disabled, or if command uses multiple slots. */
unsigned long long key_count; /* Total number of keys in this DB. */
} redisDb;
/* forward declaration for functions ctx */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment