Merge branch 'moar_perf' into keydbpro_moarperf

Former-commit-id: d0990a465c3c5c29b71f239d84a875af40699281
This commit is contained in:
John Sully 2020-01-11 22:06:20 -05:00
commit f40359cde6
6 changed files with 76 additions and 53 deletions

View File

@ -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. 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.
<img src=https://cdn-images-1.medium.com/max/1400/1*s7mTb7Qb0kxc951mz8bdgA.png width=420 height=300/><img src=https://cdn-images-1.medium.com/max/1400/1*R00A5U4AFGohGOYHMfT6fA.png height=300/> <img src="https://keydb.dev/assets/img/blog/5x_opspersecVSdatasize.PNG"/>
See the full benchmark results and setup information here: https://docs.keydb.dev/blog/2019/10/07/blog-post/
Why fork Redis? Why fork Redis?
--------------- ---------------

View File

@ -1561,3 +1561,10 @@ server-threads 2
# replicas will still sync in the normal way and incorrect ordering when # 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). # bringing up replicas can result in data loss (the first master will win).
# active-replica yes # 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

View File

@ -11,9 +11,11 @@ public:
void arm(client *c) // if a client is passed, then the client is already locked void arm(client *c) // if a client is passed, then the client is already locked
{ {
if (m_fArmed)
return;
if (c != nullptr) if (c != nullptr)
{ {
serverAssert(!m_fArmed);
serverAssert(c->lock.fOwnLock()); serverAssert(c->lock.fOwnLock());
if (!aeTryAcquireLock(true /*fWeak*/)) // avoid locking the client if we can if (!aeTryAcquireLock(true /*fWeak*/)) // avoid locking the client if we can

View File

@ -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 /* Install a file event to send data to the rewrite child if there is
* not one already. */ * not one already. */
aePostFunction(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, []{ if (!g_pserver->aof_rewrite_pending) {
if (g_pserver->aof_pipe_write_data_to_child >= 0) g_pserver->aof_rewrite_pending = true;
aeCreateFileEvent(g_pserver->rgthreadvar[IDX_EVENT_LOOP_MAIN].el, g_pserver->aof_pipe_write_data_to_child, AE_WRITABLE, aofChildWriteDiffData, NULL); 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 /* Write the buffer (possibly composed of multiple blocks) into the specified

View File

@ -3688,9 +3688,6 @@ int processCommand(client *c, int callFlags) {
} }
incrementMvccTstamp(); incrementMvccTstamp();
if (!locker.isArmed())
locker.arm(c);
/* Handle the maxmemory directive. /* Handle the maxmemory directive.
* *
@ -3699,6 +3696,7 @@ int processCommand(client *c, int callFlags) {
* condition, to avoid mixing the propagation of scripts with the * condition, to avoid mixing the propagation of scripts with the
* propagation of DELs due to eviction. */ * propagation of DELs due to eviction. */
if (g_pserver->maxmemory && !g_pserver->lua_timedout) { if (g_pserver->maxmemory && !g_pserver->lua_timedout) {
locker.arm(c);
int out_of_memory = freeMemoryIfNeededAndSafe() == C_ERR; int out_of_memory = freeMemoryIfNeededAndSafe() == C_ERR;
/* freeMemoryIfNeeded may flush replica output buffers. This may result /* freeMemoryIfNeeded may flush replica output buffers. This may result
* into a replica, that may be the active client, to be freed. */ * 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 /* Don't accept write commands if there are problems persisting on disk
* and if this is a master instance. */ * and if this is a master instance. */
int deny_write_type = writeCommandsDeniedByDiskError(); if (c->cmd->flags & CMD_WRITE || c->cmd->proc == pingCommand)
if (deny_write_type != DISK_ERROR_TYPE_NONE &&
listLength(g_pserver->masters) == 0 &&
(c->cmd->flags & CMD_WRITE ||
c->cmd->proc == pingCommand))
{ {
flagTransaction(c); locker.arm(c);
if (deny_write_type == DISK_ERROR_TYPE_RDB) int deny_write_type = writeCommandsDeniedByDiskError();
addReply(c, shared.bgsaveerr); if (deny_write_type != DISK_ERROR_TYPE_NONE &&
else listLength(g_pserver->masters) == 0 &&
addReplySds(c, (c->cmd->flags & CMD_WRITE ||
sdscatprintf(sdsempty(), c->cmd->proc == pingCommand))
"-MISCONF Errors writing to the AOF file: %s\r\n", {
strerror(g_pserver->aof_last_write_errno))); flagTransaction(c);
return C_OK; 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 /* Don't accept write commands if there are not enough good slaves and
* user configured the min-slaves-to-write option. */ * user configured the min-slaves-to-write option. */
if (listLength(g_pserver->masters) == 0 && if (listLength(g_pserver->masters) == 0 &&
g_pserver->repl_min_slaves_to_write && g_pserver->repl_min_slaves_to_write &&
g_pserver->repl_min_slaves_max_lag && g_pserver->repl_min_slaves_max_lag &&
c->cmd->flags & CMD_WRITE && c->cmd->flags & CMD_WRITE &&
g_pserver->repl_good_slaves_count < g_pserver->repl_min_slaves_to_write) g_pserver->repl_good_slaves_count < g_pserver->repl_min_slaves_to_write)
{ {
flagTransaction(c); flagTransaction(c);
addReply(c, shared.noreplicaserr); addReply(c, shared.noreplicaserr);
return C_OK; return C_OK;
} }
/* Don't accept write commands if this is a read only replica. But /* Don't accept write commands if this is a read only replica. But
* accept write commands if this is our master. */ * accept write commands if this is our master. */
if (listLength(g_pserver->masters) && g_pserver->repl_slave_ro && if (listLength(g_pserver->masters) && g_pserver->repl_slave_ro &&
!(c->flags & CLIENT_MASTER) && !(c->flags & CLIENT_MASTER) &&
c->cmd->flags & CMD_WRITE) c->cmd->flags & CMD_WRITE)
{ {
addReply(c, shared.roslaveerr); addReply(c, shared.roslaveerr);
return C_OK; return C_OK;
}
} }
/* Only allow a subset of commands in the context of Pub/Sub if the /* 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; return C_OK;
} }
/* Only allow commands with flag "t", such as INFO, SLAVEOF and so on, if (listLength(g_pserver->masters))
* 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); locker.arm(c);
addReply(c, shared.masterdownerr); /* Only allow commands with flag "t", such as INFO, SLAVEOF and so on,
return C_OK; * 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 /* Loading DB? Return an error if the command has not the
@ -3814,6 +3820,7 @@ int processCommand(client *c, int callFlags) {
queueMultiCommand(c); queueMultiCommand(c);
addReply(c,shared.queued); addReply(c,shared.queued);
} else { } else {
locker.arm(c);
call(c,callFlags); call(c,callFlags);
c->woff = g_pserver->master_repl_offset; c->woff = g_pserver->master_repl_offset;
if (listLength(g_pserver->ready_keys)) if (listLength(g_pserver->ready_keys))

View File

@ -2104,6 +2104,7 @@ struct redisServer {
int aof_stop_sending_diff; /* If true stop sending accumulated diffs int aof_stop_sending_diff; /* If true stop sending accumulated diffs
to child process. */ to child process. */
sds aof_child_diff; /* AOF diff accumulator child side. */ sds aof_child_diff; /* AOF diff accumulator child side. */
int aof_rewrite_pending = 0; /* is a call to aofChildWriteDiffData already queued? */
/* RDB persistence */ /* RDB persistence */
long long dirty; /* Changes to DB from the last save */ long long dirty; /* Changes to DB from the last save */
long long dirty_before_bgsave; /* Used to restore dirty on failed BGSAVE */ long long dirty_before_bgsave; /* Used to restore dirty on failed BGSAVE */