Run KEYS async

Former-commit-id: 214a54a815ff66ef4a1526da90296787240ecdf9
This commit is contained in:
John Sully 2019-11-19 22:12:52 -05:00
parent e25a4e80e7
commit 036fc9614d
6 changed files with 63 additions and 9 deletions

View File

@ -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

View File

@ -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().");
} }

View File

@ -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

View File

@ -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 */

View File

@ -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;

View File

@ -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 */