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
720d1fd3
Unverified
Commit
720d1fd3
authored
Nov 04, 2019
by
Salvatore Sanfilippo
Committed by
GitHub
Nov 04, 2019
Browse files
Merge pull request #6486 from oranagra/module_lru_lfu
Module API for controlling LRU and LFU, and OpenKey without TOUCH
parents
327cb45e
18b62a51
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/db.c
View file @
720d1fd3
...
...
@@ -151,9 +151,13 @@ robj *lookupKeyRead(redisDb *db, robj *key) {
*
* Returns the linked value object if the key exists or NULL if the key
* does not exist in the specified DB. */
robj
*
lookupKeyWrite
(
redisDb
*
db
,
robj
*
key
)
{
robj
*
lookupKeyWrite
WithFlags
(
redisDb
*
db
,
robj
*
key
,
int
flags
)
{
expireIfNeeded
(
db
,
key
);
return
lookupKey
(
db
,
key
,
LOOKUP_NONE
);
return
lookupKey
(
db
,
key
,
flags
);
}
robj
*
lookupKeyWrite
(
redisDb
*
db
,
robj
*
key
)
{
return
lookupKeyWriteWithFlags
(
db
,
key
,
LOOKUP_NONE
);
}
robj
*
lookupKeyReadOrReply
(
client
*
c
,
robj
*
key
,
robj
*
reply
)
{
...
...
src/module.c
View file @
720d1fd3
...
...
@@ -1865,11 +1865,12 @@ int RM_SelectDb(RedisModuleCtx *ctx, int newid) {
void
*
RM_OpenKey
(
RedisModuleCtx
*
ctx
,
robj
*
keyname
,
int
mode
)
{
RedisModuleKey
*
kp
;
robj
*
value
;
int
flags
=
mode
&
REDISMODULE_OPEN_KEY_NOTOUCH
?
LOOKUP_NOTOUCH
:
0
;
if
(
mode
&
REDISMODULE_WRITE
)
{
value
=
lookupKeyWrite
(
ctx
->
client
->
db
,
keyname
);
value
=
lookupKeyWrite
WithFlags
(
ctx
->
client
->
db
,
keyname
,
flags
);
}
else
{
value
=
lookupKeyRead
(
ctx
->
client
->
db
,
keyname
);
value
=
lookupKeyRead
WithFlags
(
ctx
->
client
->
db
,
keyname
,
flags
);
if
(
value
==
NULL
)
{
return
NULL
;
}
...
...
@@ -6710,6 +6711,38 @@ size_t moduleCount(void) {
return
dictSize
(
modules
);
}
/* Set the key LRU/LFU depending on server.maxmemory_policy.
* The lru_idle arg is idle time in seconds, and is only relevant if the
* eviction policy is LRU based.
* The lfu_freq arg is a logarithmic counter that provides an indication of
* the access frequencyonly (must be <= 255) and is only relevant if the
* eviction policy is LFU based.
* Either or both of them may be <0, in that case, nothing is set. */
/* return value is an indication if the lru field was updated or not. */
int
RM_SetLRUOrLFU
(
RedisModuleKey
*
key
,
long
long
lfu_freq
,
long
long
lru_idle
)
{
if
(
!
key
->
value
)
return
REDISMODULE_ERR
;
if
(
objectSetLRUOrLFU
(
key
->
value
,
lfu_freq
,
lru_idle
,
lru_idle
>=
0
?
LRU_CLOCK
()
:
0
))
return
REDISMODULE_OK
;
return
REDISMODULE_ERR
;
}
/* Gets the key LRU or LFU (depending on the current eviction policy).
* One will be set to the appropiate return value, and the other will be set to -1.
* see RedisModule_SetLRUOrLFU for units and ranges.
* return value is an indication of success. */
int
RM_GetLRUOrLFU
(
RedisModuleKey
*
key
,
long
long
*
lfu_freq
,
long
long
*
lru_idle
)
{
*
lru_idle
=
*
lfu_freq
=
-
1
;
if
(
!
key
->
value
)
return
REDISMODULE_ERR
;
if
(
server
.
maxmemory_policy
&
MAXMEMORY_FLAG_LFU
)
{
*
lfu_freq
=
LFUDecrAndReturn
(
key
->
value
);
}
else
{
*
lru_idle
=
estimateObjectIdleTime
(
key
->
value
)
/
1000
;
}
return
REDISMODULE_OK
;
}
/* Register all the APIs we export. Keep this function at the end of the
* file so that's easy to seek it to add new entries. */
void
moduleRegisterCoreAPI
(
void
)
{
...
...
@@ -6906,6 +6939,8 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API
(
GetClientInfoById
);
REGISTER_API
(
PublishMessage
);
REGISTER_API
(
SubscribeToServerEvent
);
REGISTER_API
(
SetLRUOrLFU
);
REGISTER_API
(
GetLRUOrLFU
);
REGISTER_API
(
BlockClientOnKeys
);
REGISTER_API
(
SignalKeyAsReady
);
REGISTER_API
(
GetBlockedClientReadyKey
);
...
...
src/object.c
View file @
720d1fd3
...
...
@@ -1209,12 +1209,13 @@ sds getMemoryDoctorReport(void) {
* The lru_idle and lru_clock args are only relevant if policy
* is MAXMEMORY_FLAG_LRU.
* Either or both of them may be <0, in that case, nothing is set. */
void
objectSetLRUOrLFU
(
robj
*
val
,
long
long
lfu_freq
,
long
long
lru_idle
,
int
objectSetLRUOrLFU
(
robj
*
val
,
long
long
lfu_freq
,
long
long
lru_idle
,
long
long
lru_clock
)
{
if
(
server
.
maxmemory_policy
&
MAXMEMORY_FLAG_LFU
)
{
if
(
lfu_freq
>=
0
)
{
serverAssert
(
lfu_freq
<=
255
);
val
->
lru
=
(
LFUGetTimeInMinutes
()
<<
8
)
|
lfu_freq
;
return
1
;
}
}
else
if
(
lru_idle
>=
0
)
{
/* Provided LRU idle time is in seconds. Scale
...
...
@@ -1231,7 +1232,9 @@ void objectSetLRUOrLFU(robj *val, long long lfu_freq, long long lru_idle,
if
(
lru_abs
<
0
)
lru_abs
=
(
lru_clock
+
(
LRU_CLOCK_MAX
/
2
))
%
LRU_CLOCK_MAX
;
val
->
lru
=
lru_abs
;
return
1
;
}
return
0
;
}
/* ======================= The OBJECT and MEMORY commands =================== */
...
...
src/redismodule.h
View file @
720d1fd3
...
...
@@ -18,6 +18,10 @@
#define REDISMODULE_READ (1<<0)
#define REDISMODULE_WRITE (1<<1)
/* RedisModule_OpenKey extra flags for the 'mode' argument.
* Avoid touching the LRU/LFU of the key when opened. */
#define REDISMODULE_OPEN_KEY_NOTOUCH (1<<16)
#define REDISMODULE_LIST_HEAD 0
#define REDISMODULE_LIST_TAIL 1
...
...
@@ -577,6 +581,8 @@ int REDISMODULE_API_FUNC(RedisModule_InfoAddFieldDouble)(RedisModuleInfoCtx *ctx
int
REDISMODULE_API_FUNC
(
RedisModule_InfoAddFieldLongLong
)(
RedisModuleInfoCtx
*
ctx
,
char
*
field
,
long
long
value
);
int
REDISMODULE_API_FUNC
(
RedisModule_InfoAddFieldULongLong
)(
RedisModuleInfoCtx
*
ctx
,
char
*
field
,
unsigned
long
long
value
);
int
REDISMODULE_API_FUNC
(
RedisModule_SubscribeToServerEvent
)(
RedisModuleCtx
*
ctx
,
RedisModuleEvent
event
,
RedisModuleEventCallback
callback
);
int
REDISMODULE_API_FUNC
(
RedisModule_SetLRUOrLFU
)(
RedisModuleKey
*
key
,
long
long
lfu_freq
,
long
long
lru_idle
);
int
REDISMODULE_API_FUNC
(
RedisModule_GetLRUOrLFU
)(
RedisModuleKey
*
key
,
long
long
*
lfu_freq
,
long
long
*
lru_idle
);
RedisModuleBlockedClient
*
REDISMODULE_API_FUNC
(
RedisModule_BlockClientOnKeys
)(
RedisModuleCtx
*
ctx
,
RedisModuleCmdFunc
reply_callback
,
RedisModuleCmdFunc
timeout_callback
,
void
(
*
free_privdata
)(
RedisModuleCtx
*
,
void
*
),
long
long
timeout_ms
,
RedisModuleString
**
keys
,
int
numkeys
,
void
*
privdata
);
void
REDISMODULE_API_FUNC
(
RedisModule_SignalKeyAsReady
)(
RedisModuleCtx
*
ctx
,
RedisModuleString
*
key
);
RedisModuleString
*
REDISMODULE_API_FUNC
(
RedisModule_GetBlockedClientReadyKey
)(
RedisModuleCtx
*
ctx
);
...
...
@@ -784,6 +790,8 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API
(
GetClientInfoById
);
REDISMODULE_GET_API
(
PublishMessage
);
REDISMODULE_GET_API
(
SubscribeToServerEvent
);
REDISMODULE_GET_API
(
SetLRUOrLFU
);
REDISMODULE_GET_API
(
GetLRUOrLFU
);
REDISMODULE_GET_API
(
BlockClientOnKeys
);
REDISMODULE_GET_API
(
SignalKeyAsReady
);
REDISMODULE_GET_API
(
GetBlockedClientReadyKey
);
...
...
src/server.h
View file @
720d1fd3
...
...
@@ -2085,9 +2085,10 @@ robj *lookupKeyWrite(redisDb *db, robj *key);
robj
*
lookupKeyReadOrReply
(
client
*
c
,
robj
*
key
,
robj
*
reply
);
robj
*
lookupKeyWriteOrReply
(
client
*
c
,
robj
*
key
,
robj
*
reply
);
robj
*
lookupKeyReadWithFlags
(
redisDb
*
db
,
robj
*
key
,
int
flags
);
robj
*
lookupKeyWriteWithFlags
(
redisDb
*
db
,
robj
*
key
,
int
flags
);
robj
*
objectCommandLookup
(
client
*
c
,
robj
*
key
);
robj
*
objectCommandLookupOrReply
(
client
*
c
,
robj
*
key
,
robj
*
reply
);
void
objectSetLRUOrLFU
(
robj
*
val
,
long
long
lfu_freq
,
long
long
lru_idle
,
int
objectSetLRUOrLFU
(
robj
*
val
,
long
long
lfu_freq
,
long
long
lru_idle
,
long
long
lru_clock
);
#define LOOKUP_NONE 0
#define LOOKUP_NOTOUCH (1<<0)
...
...
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