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
c41f94d2
Commit
c41f94d2
authored
Jul 22, 2019
by
antirez
Browse files
Client side caching: split invalidation into key / slot.
parent
09c06698
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/server.c
View file @
c41f94d2
...
@@ -3401,6 +3401,10 @@ int processCommand(client *c) {
...
@@ -3401,6 +3401,10 @@ int processCommand(client *c) {
}
}
}
}
/* Make sure to use a reasonable amount of memory for client side
* caching metadata. */
if
(
server
.
tracking_clients
)
trackingLimitUsedSlots
();
/* Don't accept write commands if there are problems persisting on disk
/* Don't accept write commands if there are problems persisting on disk
* and if this is a master instance. */
* and if this is a master instance. */
int
deny_write_type
=
writeCommandsDeniedByDiskError
();
int
deny_write_type
=
writeCommandsDeniedByDiskError
();
...
...
src/server.h
View file @
c41f94d2
...
@@ -1639,6 +1639,7 @@ void disableTracking(client *c);
...
@@ -1639,6 +1639,7 @@ void disableTracking(client *c);
void
trackingRememberKeys
(
client
*
c
);
void
trackingRememberKeys
(
client
*
c
);
void
trackingInvalidateKey
(
robj
*
keyobj
);
void
trackingInvalidateKey
(
robj
*
keyobj
);
void
trackingInvalidateKeysOnFlush
(
int
dbid
);
void
trackingInvalidateKeysOnFlush
(
int
dbid
);
void
trackingLimitUsedSlots
(
void
);
/* List data type */
/* List data type */
void
listTypeTryConversion
(
robj
*
subject
,
robj
*
value
);
void
listTypeTryConversion
(
robj
*
subject
,
robj
*
value
);
...
...
src/tracking.c
View file @
c41f94d2
...
@@ -154,37 +154,43 @@ void sendTrackingMessage(client *c, long long hash) {
...
@@ -154,37 +154,43 @@ void sendTrackingMessage(client *c, long long hash) {
}
}
}
}
/* This function is called from signalModifiedKey() or other places in Redis
/* Invalidates a caching slot: this is actually the low level implementation
* when a key changes value. In the context of keys tracking, our task here is
* of the API that Redis calls externally, that is trackingInvalidateKey(). */
* to send a notification to every client that may have keys about such caching
void
trackingInvalidateSlot
(
uint64_t
slot
)
{
* slot. */
if
(
TrackingTable
==
NULL
||
TrackingTable
[
slot
]
==
NULL
)
return
;
void
trackingInvalidateKey
(
robj
*
keyobj
)
{
if
(
TrackingTable
==
NULL
||
TrackingTableUsedSlots
==
0
)
return
;
sds
sdskey
=
keyobj
->
ptr
;
uint64_t
hash
=
crc64
(
0
,
(
unsigned
char
*
)
sdskey
,
sdslen
(
sdskey
))
&
(
TRACKING_TABLE_SIZE
-
1
);
if
(
TrackingTable
[
hash
]
==
NULL
)
return
;
raxIterator
ri
;
raxIterator
ri
;
raxStart
(
&
ri
,
TrackingTable
[
hash
]);
raxStart
(
&
ri
,
TrackingTable
[
slot
]);
raxSeek
(
&
ri
,
"^"
,
NULL
,
0
);
raxSeek
(
&
ri
,
"^"
,
NULL
,
0
);
while
(
raxNext
(
&
ri
))
{
while
(
raxNext
(
&
ri
))
{
uint64_t
id
;
uint64_t
id
;
memcpy
(
&
id
,
ri
.
key
,
ri
.
key_len
);
memcpy
(
&
id
,
ri
.
key
,
ri
.
key_len
);
client
*
c
=
lookupClientByID
(
id
);
client
*
c
=
lookupClientByID
(
id
);
if
(
c
==
NULL
||
!
(
c
->
flags
&
CLIENT_TRACKING
))
continue
;
if
(
c
==
NULL
||
!
(
c
->
flags
&
CLIENT_TRACKING
))
continue
;
sendTrackingMessage
(
c
,
hash
);
sendTrackingMessage
(
c
,
slot
);
}
}
raxStop
(
&
ri
);
raxStop
(
&
ri
);
/* Free the tracking table: we'll create the radix tree and populate it
/* Free the tracking table: we'll create the radix tree and populate it
* again if more keys will be modified in this
hash
slot. */
* again if more keys will be modified in this
caching
slot. */
raxFree
(
TrackingTable
[
hash
]);
raxFree
(
TrackingTable
[
slot
]);
TrackingTable
[
hash
]
=
NULL
;
TrackingTable
[
slot
]
=
NULL
;
TrackingTableUsedSlots
--
;
TrackingTableUsedSlots
--
;
}
}
/* This function is called from signalModifiedKey() or other places in Redis
* when a key changes value. In the context of keys tracking, our task here is
* to send a notification to every client that may have keys about such caching
* slot. */
void
trackingInvalidateKey
(
robj
*
keyobj
)
{
if
(
TrackingTable
==
NULL
||
TrackingTableUsedSlots
==
0
)
return
;
sds
sdskey
=
keyobj
->
ptr
;
uint64_t
hash
=
crc64
(
0
,
(
unsigned
char
*
)
sdskey
,
sdslen
(
sdskey
))
&
(
TRACKING_TABLE_SIZE
-
1
);
trackingInvalidateSlot
(
hash
);
}
/* This function is called when one or all the Redis databases are flushed
/* This function is called when one or all the Redis databases are flushed
* (dbid == -1 in case of FLUSHALL). Caching slots are not specific for
* (dbid == -1 in case of FLUSHALL). Caching slots are not specific for
* each DB but are global: currently what we do is sending a special
* each DB but are global: currently what we do is sending a special
...
@@ -235,3 +241,17 @@ void trackingInvalidateKeysOnFlush(int dbid) {
...
@@ -235,3 +241,17 @@ void trackingInvalidateKeysOnFlush(int dbid) {
}
}
}
}
}
}
/* Tracking forces Redis to remember information about which client may have
* keys about certian caching slots. In workloads where there are a lot of
* reads, but keys are hardly modified, the amount of information we have
* to remember server side could be a lot: for each 16 millions of caching
* slots we may end with a radix tree containing many entries.
*
* So Redis allows the user to configure a maximum fill rate for the
* invalidation table. This function makes sure that we don't go over the
* specified fill rate: if we are over, we can just evict informations about
* random caching slots, and send invalidation messages to clients like if
* the key was modified. */
void
trackingLimitUsedSlots
(
void
)
{
}
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