Run KEYS async
Former-commit-id: 214a54a815ff66ef4a1526da90296787240ecdf9
This commit is contained in:
parent
e25a4e80e7
commit
036fc9614d
@ -207,7 +207,7 @@ endif
|
|||||||
|
|
||||||
REDIS_SERVER_NAME=keydb-server
|
REDIS_SERVER_NAME=keydb-server
|
||||||
REDIS_SENTINEL_NAME=keydb-sentinel
|
REDIS_SENTINEL_NAME=keydb-sentinel
|
||||||
REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o acl.o storage.o rdb-s3.o fastlock.o new.o tracking.o $(ASM_OBJ)
|
REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o acl.o storage.o rdb-s3.o fastlock.o new.o tracking.o AsyncWorkQueue.o $(ASM_OBJ)
|
||||||
REDIS_CLI_NAME=keydb-cli
|
REDIS_CLI_NAME=keydb-cli
|
||||||
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o redis-cli-cpphelper.o zmalloc.o release.o anet.o ae.o crc64.o siphash.o crc16.o storage-lite.o fastlock.o new.o $(ASM_OBJ)
|
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o redis-cli-cpphelper.o zmalloc.o release.o anet.o ae.o crc64.o siphash.o crc16.o storage-lite.o fastlock.o new.o $(ASM_OBJ)
|
||||||
REDIS_BENCHMARK_NAME=keydb-benchmark
|
REDIS_BENCHMARK_NAME=keydb-benchmark
|
||||||
|
@ -190,6 +190,8 @@ void unblockClient(client *c) {
|
|||||||
unblockClientWaitingReplicas(c);
|
unblockClientWaitingReplicas(c);
|
||||||
} else if (c->btype == BLOCKED_MODULE) {
|
} else if (c->btype == BLOCKED_MODULE) {
|
||||||
unblockClientFromModule(c);
|
unblockClientFromModule(c);
|
||||||
|
} else if (c->btype == BLOCKED_ASYNC) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
serverPanic("Unknown btype in unblockClient().");
|
serverPanic("Unknown btype in unblockClient().");
|
||||||
}
|
}
|
||||||
|
52
src/db.cpp
52
src/db.cpp
@ -704,20 +704,25 @@ bool redisDbPersistentData::iterate(std::function<bool(const char*)> fn)
|
|||||||
return fResult;
|
return fResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
void keysCommand(client *c) {
|
void keysCommandCore(client *c, redisDbPersistentData *db, sds pattern)
|
||||||
sds pattern = szFromObj(c->argv[1]);
|
{
|
||||||
int plen = sdslen(pattern), allkeys;
|
int plen = sdslen(pattern), allkeys;
|
||||||
unsigned long numkeys = 0;
|
unsigned long numkeys = 0;
|
||||||
void *replylen = addReplyDeferredLen(c);
|
|
||||||
|
aeAcquireLock();
|
||||||
|
void *replylen = addReplyDeferredLenAsync(c);
|
||||||
|
aeReleaseLock();
|
||||||
|
|
||||||
allkeys = (pattern[0] == '*' && pattern[1] == '\0');
|
allkeys = (pattern[0] == '*' && pattern[1] == '\0');
|
||||||
c->db->iterate([&](const char *key)->bool {
|
db->iterate([&](const char *key)->bool {
|
||||||
robj *keyobj;
|
robj *keyobj;
|
||||||
|
|
||||||
if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {
|
if (allkeys || stringmatchlen(pattern,plen,key,sdslen(key),0)) {
|
||||||
keyobj = createStringObject(key,sdslen(key));
|
keyobj = createStringObject(key,sdslen(key));
|
||||||
if (!keyIsExpired(c->db,keyobj)) {
|
if (!keyIsExpired(c->db,keyobj)) {
|
||||||
addReplyBulk(c,keyobj);
|
aeAcquireLock();
|
||||||
|
addReplyBulkAsync(c,keyobj);
|
||||||
|
aeReleaseLock();
|
||||||
numkeys++;
|
numkeys++;
|
||||||
}
|
}
|
||||||
decrRefCount(keyobj);
|
decrRefCount(keyobj);
|
||||||
@ -725,7 +730,42 @@ void keysCommand(client *c) {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
setDeferredArrayLen(c,replylen,numkeys);
|
setDeferredArrayLenAsync(c,replylen,numkeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
int prepareClientToWrite(client *c, bool fAsync);
|
||||||
|
void keysCommand(client *c) {
|
||||||
|
sds pattern = szFromObj(c->argv[1]);
|
||||||
|
|
||||||
|
redisDbPersistentData *snapshot = nullptr;
|
||||||
|
if (!(c->flags & (CLIENT_MULTI | CLIENT_BLOCKED)))
|
||||||
|
snapshot = c->db->createSnapshot(c->mvccCheckpoint);
|
||||||
|
if (snapshot != nullptr)
|
||||||
|
{
|
||||||
|
sds patternCopy = sdsdup(pattern);
|
||||||
|
aeEventLoop *el = serverTL->el;
|
||||||
|
blockClient(c, BLOCKED_ASYNC);
|
||||||
|
redisDb *db = c->db;
|
||||||
|
g_pserver->asyncworkqueue->AddWorkFunction([el, c, db, patternCopy, snapshot]{
|
||||||
|
keysCommandCore(c, snapshot, patternCopy);
|
||||||
|
sdsfree(patternCopy);
|
||||||
|
aePostFunction(el, [c, db, snapshot]{
|
||||||
|
aeReleaseLock(); // we need to lock with coordination of the client
|
||||||
|
|
||||||
|
std::unique_lock<decltype(c->lock)> lock(c->lock);
|
||||||
|
AeLocker locker;
|
||||||
|
locker.arm(c);
|
||||||
|
|
||||||
|
unblockClient(c);
|
||||||
|
db->endSnapshot(snapshot);
|
||||||
|
aeAcquireLock();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
keysCommandCore(c, c->db, pattern);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This callback is used by scanGenericCommand in order to collect elements
|
/* This callback is used by scanGenericCommand in order to collect elements
|
||||||
|
@ -530,6 +530,7 @@ void *addReplyDeferredLenAsync(client *c) {
|
|||||||
if (FCorrectThread(c))
|
if (FCorrectThread(c))
|
||||||
return addReplyDeferredLen(c);
|
return addReplyDeferredLen(c);
|
||||||
|
|
||||||
|
prepareClientToWrite(c, true);
|
||||||
return (void*)((ssize_t)c->bufposAsync);
|
return (void*)((ssize_t)c->bufposAsync);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1316,7 +1317,11 @@ bool freeClient(client *c) {
|
|||||||
c->querybuf = NULL;
|
c->querybuf = NULL;
|
||||||
|
|
||||||
/* Deallocate structures used to block on blocking ops. */
|
/* Deallocate structures used to block on blocking ops. */
|
||||||
if (c->flags & CLIENT_BLOCKED) unblockClient(c);
|
if (c->flags & CLIENT_BLOCKED)
|
||||||
|
{
|
||||||
|
serverAssert(c->btype != BLOCKED_ASYNC);
|
||||||
|
unblockClient(c);
|
||||||
|
}
|
||||||
dictRelease(c->bpop.keys);
|
dictRelease(c->bpop.keys);
|
||||||
|
|
||||||
/* UNWATCH all the keys */
|
/* UNWATCH all the keys */
|
||||||
|
@ -3076,6 +3076,8 @@ void initServer(void) {
|
|||||||
latencyMonitorInit();
|
latencyMonitorInit();
|
||||||
bioInit();
|
bioInit();
|
||||||
g_pserver->initial_memory_usage = zmalloc_used_memory();
|
g_pserver->initial_memory_usage = zmalloc_used_memory();
|
||||||
|
|
||||||
|
g_pserver->asyncworkqueue = new (MALLOC_LOCAL) AsyncWorkQueue(cserver.cthreads);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse the flags string description 'strflags' and set them to the
|
/* Parse the flags string description 'strflags' and set them to the
|
||||||
@ -3831,6 +3833,7 @@ int prepareForShutdown(int flags) {
|
|||||||
|
|
||||||
/* Close the listening sockets. Apparently this allows faster restarts. */
|
/* Close the listening sockets. Apparently this allows faster restarts. */
|
||||||
closeListeningSockets(1);
|
closeListeningSockets(1);
|
||||||
|
|
||||||
serverLog(LL_WARNING,"%s is now ready to exit, bye bye...",
|
serverLog(LL_WARNING,"%s is now ready to exit, bye bye...",
|
||||||
g_pserver->sentinel_mode ? "Sentinel" : "KeyDB");
|
g_pserver->sentinel_mode ? "Sentinel" : "KeyDB");
|
||||||
return C_OK;
|
return C_OK;
|
||||||
|
@ -92,6 +92,7 @@ typedef long long mstime_t; /* millisecond time type. */
|
|||||||
#include "endianconv.h"
|
#include "endianconv.h"
|
||||||
#include "crc64.h"
|
#include "crc64.h"
|
||||||
#include "IStorage.h"
|
#include "IStorage.h"
|
||||||
|
#include "AsyncWorkQueue.h"
|
||||||
|
|
||||||
extern int g_fTestMode;
|
extern int g_fTestMode;
|
||||||
|
|
||||||
@ -389,7 +390,8 @@ public:
|
|||||||
#define BLOCKED_MODULE 3 /* Blocked by a loadable module. */
|
#define BLOCKED_MODULE 3 /* Blocked by a loadable module. */
|
||||||
#define BLOCKED_STREAM 4 /* XREAD. */
|
#define BLOCKED_STREAM 4 /* XREAD. */
|
||||||
#define BLOCKED_ZSET 5 /* BZPOP et al. */
|
#define BLOCKED_ZSET 5 /* BZPOP et al. */
|
||||||
#define BLOCKED_NUM 6 /* Number of blocked states. */
|
#define BLOCKED_ASYNC 6
|
||||||
|
#define BLOCKED_NUM 7 /* Number of blocked states. */
|
||||||
|
|
||||||
/* Client request types */
|
/* Client request types */
|
||||||
#define PROTO_REQ_INLINE 1
|
#define PROTO_REQ_INLINE 1
|
||||||
@ -2060,6 +2062,8 @@ struct redisServer {
|
|||||||
// Upper 44 bits: mstime (least significant 44-bits) enough for ~500 years before rollover from date of addition
|
// Upper 44 bits: mstime (least significant 44-bits) enough for ~500 years before rollover from date of addition
|
||||||
uint64_t mvcc_tstamp;
|
uint64_t mvcc_tstamp;
|
||||||
|
|
||||||
|
AsyncWorkQueue *asyncworkqueue;
|
||||||
|
|
||||||
/* System hardware info */
|
/* System hardware info */
|
||||||
size_t system_memory_size; /* Total memory in system as reported by OS */
|
size_t system_memory_size; /* Total memory in system as reported by OS */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user