diff --git a/README.md b/README.md index 8d8c59ff0..70b879d52 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,9 @@ KeyDB maintains full compatibility with the Redis protocol, modules, and scripts On the same hardware KeyDB can perform twice as many queries per second as Redis, with 60% lower latency. Active-Replication simplifies hot-spare failover allowing you to easily distribute writes over replicas and use simple TCP based load balancing/failover. KeyDB's higher performance allows you to do more on less hardware which reduces operation costs and complexity. - + + +See the full benchmark results and setup information here: https://docs.keydb.dev/blog/2019/10/07/blog-post/ Why fork Redis? --------------- diff --git a/keydb.conf b/keydb.conf index 5c31305d8..03087b0c0 100644 --- a/keydb.conf +++ b/keydb.conf @@ -1561,3 +1561,10 @@ server-threads 2 # replicas will still sync in the normal way and incorrect ordering when # bringing up replicas can result in data loss (the first master will win). # active-replica yes + +# Enable Pro? KeyDB pro provides support for pro only features +# note: you may omit the license key to demo pro features for a limited time +# enable-pro [License Key] + +# Enable FLASH support? (Pro Only) +# storage-provider flash /path/to/flash/db diff --git a/src/aelocker.h b/src/aelocker.h index eca15f491..528955380 100644 --- a/src/aelocker.h +++ b/src/aelocker.h @@ -11,9 +11,11 @@ public: void arm(client *c) // if a client is passed, then the client is already locked { + if (m_fArmed) + return; + if (c != nullptr) { - serverAssert(!m_fArmed); serverAssert(c->lock.fOwnLock()); if (!aeTryAcquireLock(true /*fWeak*/)) // avoid locking the client if we can diff --git a/src/aof.cpp b/src/aof.cpp index d1caa7885..ef0152f03 100644 --- a/src/aof.cpp +++ b/src/aof.cpp @@ -165,10 +165,14 @@ void aofRewriteBufferAppend(unsigned char *s, unsigned long len) { /* Install a file event to send data to the rewrite child if there is * not one already. */ - aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, []{ - if (g_pserver->aof_pipe_write_data_to_child >= 0) - aeCreateFileEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, g_pserver->aof_pipe_write_data_to_child, AE_WRITABLE, aofChildWriteDiffData, NULL); - }); + if (!g_pserver->aof_rewrite_pending) { + g_pserver->aof_rewrite_pending = true; + aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, [] { + g_pserver->aof_rewrite_pending = false; + if (g_pserver->aof_pipe_write_data_to_child >= 0) + aeCreateFileEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, g_pserver->aof_pipe_write_data_to_child, AE_WRITABLE, aofChildWriteDiffData, NULL); + }); + } } /* Write the buffer (possibly composed of multiple blocks) into the specified diff --git a/src/server.cpp b/src/server.cpp index 57937e98d..2700daf1c 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -3688,9 +3688,6 @@ int processCommand(client *c, int callFlags) { } incrementMvccTstamp(); - - if (!locker.isArmed()) - locker.arm(c); /* Handle the maxmemory directive. * @@ -3699,6 +3696,7 @@ int processCommand(client *c, int callFlags) { * condition, to avoid mixing the propagation of scripts with the * propagation of DELs due to eviction. */ if (g_pserver->maxmemory && !g_pserver->lua_timedout) { + locker.arm(c); int out_of_memory = freeMemoryIfNeededAndSafe() == C_ERR; /* freeMemoryIfNeeded may flush replica output buffers. This may result * into a replica, that may be the active client, to be freed. */ @@ -3718,44 +3716,48 @@ int processCommand(client *c, int callFlags) { /* Don't accept write commands if there are problems persisting on disk * and if this is a master instance. */ - int deny_write_type = writeCommandsDeniedByDiskError(); - if (deny_write_type != DISK_ERROR_TYPE_NONE && - listLength(g_pserver->masters) == 0 && - (c->cmd->flags & CMD_WRITE || - c->cmd->proc == pingCommand)) + if (c->cmd->flags & CMD_WRITE || c->cmd->proc == pingCommand) { - flagTransaction(c); - if (deny_write_type == DISK_ERROR_TYPE_RDB) - addReply(c, shared.bgsaveerr); - else - addReplySds(c, - sdscatprintf(sdsempty(), - "-MISCONF Errors writing to the AOF file: %s\r\n", - strerror(g_pserver->aof_last_write_errno))); - return C_OK; - } + locker.arm(c); + int deny_write_type = writeCommandsDeniedByDiskError(); + if (deny_write_type != DISK_ERROR_TYPE_NONE && + listLength(g_pserver->masters) == 0 && + (c->cmd->flags & CMD_WRITE || + c->cmd->proc == pingCommand)) + { + flagTransaction(c); + if (deny_write_type == DISK_ERROR_TYPE_RDB) + addReply(c, shared.bgsaveerr); + else + addReplySds(c, + sdscatprintf(sdsempty(), + "-MISCONF Errors writing to the AOF file: %s\r\n", + strerror(g_pserver->aof_last_write_errno))); + return C_OK; + } - /* Don't accept write commands if there are not enough good slaves and - * user configured the min-slaves-to-write option. */ - if (listLength(g_pserver->masters) == 0 && - g_pserver->repl_min_slaves_to_write && - g_pserver->repl_min_slaves_max_lag && - c->cmd->flags & CMD_WRITE && - g_pserver->repl_good_slaves_count < g_pserver->repl_min_slaves_to_write) - { - flagTransaction(c); - addReply(c, shared.noreplicaserr); - return C_OK; - } + /* Don't accept write commands if there are not enough good slaves and + * user configured the min-slaves-to-write option. */ + if (listLength(g_pserver->masters) == 0 && + g_pserver->repl_min_slaves_to_write && + g_pserver->repl_min_slaves_max_lag && + c->cmd->flags & CMD_WRITE && + g_pserver->repl_good_slaves_count < g_pserver->repl_min_slaves_to_write) + { + flagTransaction(c); + addReply(c, shared.noreplicaserr); + return C_OK; + } - /* Don't accept write commands if this is a read only replica. But - * accept write commands if this is our master. */ - if (listLength(g_pserver->masters) && g_pserver->repl_slave_ro && - !(c->flags & CLIENT_MASTER) && - c->cmd->flags & CMD_WRITE) - { - addReply(c, shared.roslaveerr); - return C_OK; + /* Don't accept write commands if this is a read only replica. But + * accept write commands if this is our master. */ + if (listLength(g_pserver->masters) && g_pserver->repl_slave_ro && + !(c->flags & CLIENT_MASTER) && + c->cmd->flags & CMD_WRITE) + { + addReply(c, shared.roslaveerr); + return C_OK; + } } /* Only allow a subset of commands in the context of Pub/Sub if the @@ -3770,16 +3772,20 @@ int processCommand(client *c, int callFlags) { return C_OK; } - /* Only allow commands with flag "t", such as INFO, SLAVEOF and so on, - * when replica-serve-stale-data is no and we are a replica with a broken - * link with master. */ - if (FBrokenLinkToMaster() && - g_pserver->repl_serve_stale_data == 0 && - !(c->cmd->flags & CMD_STALE)) + if (listLength(g_pserver->masters)) { - flagTransaction(c); - addReply(c, shared.masterdownerr); - return C_OK; + locker.arm(c); + /* Only allow commands with flag "t", such as INFO, SLAVEOF and so on, + * when replica-serve-stale-data is no and we are a replica with a broken + * link with master. */ + if (FBrokenLinkToMaster() && + g_pserver->repl_serve_stale_data == 0 && + !(c->cmd->flags & CMD_STALE)) + { + flagTransaction(c); + addReply(c, shared.masterdownerr); + return C_OK; + } } /* Loading DB? Return an error if the command has not the @@ -3814,6 +3820,7 @@ int processCommand(client *c, int callFlags) { queueMultiCommand(c); addReply(c,shared.queued); } else { + locker.arm(c); call(c,callFlags); c->woff = g_pserver->master_repl_offset; if (listLength(g_pserver->ready_keys)) diff --git a/src/server.h b/src/server.h index 35edac232..b467ea4a7 100644 --- a/src/server.h +++ b/src/server.h @@ -2104,6 +2104,7 @@ struct redisServer { int aof_stop_sending_diff; /* If true stop sending accumulated diffs to child process. */ sds aof_child_diff; /* AOF diff accumulator child side. */ + int aof_rewrite_pending = 0; /* is a call to aofChildWriteDiffData already queued? */ /* RDB persistence */ long long dirty; /* Changes to DB from the last save */ long long dirty_before_bgsave; /* Used to restore dirty on failed BGSAVE */