Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
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