Skip to content

Commit

Permalink
Make full use of replication backlog memory (redis#8966)
Browse files Browse the repository at this point in the history
According jemalloc size classes, we may allocate much more memory
than our setting of repl_backlog_size, but we don't make full use of it.
  • Loading branch information
ShooterIT authored May 20, 2021
1 parent a59e75a commit 0b2d0be
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 8 deletions.
6 changes: 3 additions & 3 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -2242,10 +2242,10 @@ static int updateJemallocBgThread(int val, int prev, const char **err) {
}

static int updateReplBacklogSize(long long val, long long prev, const char **err) {
/* resizeReplicationBacklog sets server.repl_backlog_size, and relies on
/* resizeReplicationBacklog sets server.cfg_repl_backlog_size, and relies on
* being able to tell when the size changes, so restore prev before calling it. */
UNUSED(err);
server.repl_backlog_size = prev;
server.cfg_repl_backlog_size = prev;
resizeReplicationBacklog(val);
return 1;
}
Expand Down Expand Up @@ -2523,7 +2523,7 @@ standardConfig configs[] = {
createLongLongConfig("latency-monitor-threshold", NULL, MODIFIABLE_CONFIG, 0, LLONG_MAX, server.latency_monitor_threshold, 0, INTEGER_CONFIG, NULL, NULL),
createLongLongConfig("proto-max-bulk-len", NULL, MODIFIABLE_CONFIG, 1024*1024, LONG_MAX, server.proto_max_bulk_len, 512ll*1024*1024, MEMORY_CONFIG, NULL, NULL), /* Bulk request max size */
createLongLongConfig("stream-node-max-entries", NULL, MODIFIABLE_CONFIG, 0, LLONG_MAX, server.stream_node_max_entries, 100, INTEGER_CONFIG, NULL, NULL),
createLongLongConfig("repl-backlog-size", NULL, MODIFIABLE_CONFIG, 1, LLONG_MAX, server.repl_backlog_size, 1024*1024, MEMORY_CONFIG, NULL, updateReplBacklogSize), /* Default: 1mb */
createLongLongConfig("repl-backlog-size", NULL, MODIFIABLE_CONFIG, 1, LLONG_MAX, server.cfg_repl_backlog_size, 1024*1024, MEMORY_CONFIG, NULL, updateReplBacklogSize), /* Default: 1mb */

/* Unsigned Long Long configs */
createULongLongConfig("maxmemory", NULL, MODIFIABLE_CONFIG, 0, ULLONG_MAX, server.maxmemory, 0, MEMORY_CONFIG, NULL, updateMaxmemory),
Expand Down
12 changes: 7 additions & 5 deletions src/replication.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ int bg_unlink(const char *filename) {

void createReplicationBacklog(void) {
serverAssert(server.repl_backlog == NULL);
server.repl_backlog = zmalloc(server.repl_backlog_size);
server.repl_backlog = zmalloc(server.cfg_repl_backlog_size);
server.repl_backlog_size = zmalloc_usable_size(server.repl_backlog);
server.repl_backlog_histlen = 0;
server.repl_backlog_idx = 0;

Expand All @@ -121,24 +122,25 @@ void createReplicationBacklog(void) {

/* This function is called when the user modifies the replication backlog
* size at runtime. It is up to the function to both update the
* server.repl_backlog_size and to resize the buffer and setup it so that
* server.cfg_repl_backlog_size and to resize the buffer and setup it so that
* it contains the same data as the previous one (possibly less data, but
* the most recent bytes, or the same data and more free space in case the
* buffer is enlarged). */
void resizeReplicationBacklog(long long newsize) {
if (newsize < CONFIG_REPL_BACKLOG_MIN_SIZE)
newsize = CONFIG_REPL_BACKLOG_MIN_SIZE;
if (server.repl_backlog_size == newsize) return;
if (server.cfg_repl_backlog_size == newsize) return;

server.repl_backlog_size = newsize;
server.cfg_repl_backlog_size = newsize;
if (server.repl_backlog != NULL) {
/* What we actually do is to flush the old buffer and realloc a new
* empty one. It will refill with new data incrementally.
* The reason is that copying a few gigabytes adds latency and even
* worse often we need to alloc additional space before freeing the
* old buffer. */
zfree(server.repl_backlog);
server.repl_backlog = zmalloc(server.repl_backlog_size);
server.repl_backlog = zmalloc(server.cfg_repl_backlog_size);
server.repl_backlog_size = zmalloc_usable_size(server.repl_backlog);
server.repl_backlog_histlen = 0;
server.repl_backlog_idx = 0;
/* Next byte we have is... the next since the buffer is empty. */
Expand Down
1 change: 1 addition & 0 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -1432,6 +1432,7 @@ struct redisServer {
int repl_ping_slave_period; /* Master pings the slave every N seconds */
char *repl_backlog; /* Replication backlog for partial syncs */
long long repl_backlog_size; /* Backlog circular buffer size */
long long cfg_repl_backlog_size;/* Backlog circular buffer size in config */
long long repl_backlog_histlen; /* Backlog actual data length */
long long repl_backlog_idx; /* Backlog circular buffer current offset,
that is the next byte will'll write to.*/
Expand Down

0 comments on commit 0b2d0be

Please sign in to comment.