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