Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions redis.conf
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,15 @@ rdb-del-sync-files no
# Note that you must specify a directory here, not a file name.
dir ./

# Redis can try to load an RDB dump produced by a future version of Redis/Valkey.
# This can only work on a best-effort basis, because future RDB versions may
# contain information that's not known to the current version. If no new features
# are used, it may be possible to import the data produced by a later version,
# but loading is aborted if unknown information is encountered. Possible values
# are 'strict' and 'relaxed'. This also applies to replication and the RESTORE
# command.
rdb-version-check relaxed

################################# REPLICATION #################################

# Master-Replica replication. Use replicaof to make a Redis instance a copy of
Expand Down
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ endif

REDIS_SERVER_NAME=redis-server$(PROG_SUFFIX)
REDIS_SENTINEL_NAME=redis-sentinel$(PROG_SUFFIX)
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 crcspeed.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 lolwut.o lolwut5.o lolwut6.o acl.o gopher.o tracking.o connection.o tls.o sha256.o timeout.o setcpuaffinity.o mt19937-64.o
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 crcspeed.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 lolwut.o lolwut5.o lolwut6.o acl.o gopher.o tracking.o connection.o tls.o sha256.o timeout.o setcpuaffinity.o mt19937-64.o rdb_downgrade_compat.o
REDIS_CLI_NAME=redis-cli$(PROG_SUFFIX)
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o ae.o crcspeed.o crc64.o siphash.o crc16.o mt19937-64.o
REDIS_BENCHMARK_NAME=redis-benchmark$(PROG_SUFFIX)
Expand Down
46 changes: 38 additions & 8 deletions src/cluster.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,13 +171,30 @@ int clusterLoadConfig(char *filename) {
n = createClusterNode(argv[0],0);
clusterAddNode(n);
}
/* Address and port */
if ((p = strrchr(argv[1],':')) == NULL) {
/* Address and port. The format is ip:port[,hostname] */
int aux_argc;
sds *aux_argv = sdssplitlen(argv[1],sdslen(argv[1]),",",1,&aux_argc);
if (aux_argv == NULL) {
sdsfreesplitres(argv,argc);
goto fmterr;
}

if (aux_argc > 1) {
if (sdslen(aux_argv[1]) > 0) {
sdsfree(n->hostname);
n->hostname = sdsnew(aux_argv[1]);
} else {
if (n->hostname) sdsclear(n->hostname);
}
}

if ((p = strrchr(aux_argv[0],':')) == NULL) {
sdsfreesplitres(aux_argv,aux_argc);
sdsfreesplitres(argv,argc);
goto fmterr;
}
*p = '\0';
memcpy(n->ip,argv[1],strlen(argv[1])+1);
memcpy(n->ip,aux_argv[0],strlen(aux_argv[0])+1);
char *port = p+1;
char *busp = strchr(port,'@');
if (busp) {
Expand All @@ -189,6 +206,10 @@ int clusterLoadConfig(char *filename) {
* In this case we set it to the default offset of 10000 from the
* base port. */
n->cport = busp ? atoi(busp) : n->port + CLUSTER_PORT_INCR;
sdsfreesplitres(aux_argv,aux_argc);

/* The plaintext port for client in a TLS cluster (n->pport) is not
* stored in nodes.conf. It is received later over the bus protocol. */

/* Parse flags */
p = s = argv[2];
Expand Down Expand Up @@ -786,6 +807,7 @@ clusterNode *createClusterNode(char *nodename, int flags) {
node->data_received = 0;
node->fail_time = 0;
node->link = NULL;
node->hostname = NULL;
memset(node->ip,0,sizeof(node->ip));
node->port = 0;
node->cport = 0;
Expand Down Expand Up @@ -956,6 +978,7 @@ void freeClusterNode(clusterNode *n) {
if (n->link) freeClusterLink(n->link);
listRelease(n->fail_reports);
zfree(n->slaves);
if (n->hostname) sdsfree(n->hostname);
zfree(n);
}

Expand Down Expand Up @@ -1752,12 +1775,12 @@ int clusterProcessPacket(clusterLink *link) {

explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);
explen += (sizeof(clusterMsgDataGossip)*count);
if (totlen != explen) return 1;
if (totlen < explen) return 1;
} else if (type == CLUSTERMSG_TYPE_FAIL) {
uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);

explen += sizeof(clusterMsgDataFail);
if (totlen != explen) return 1;
if (totlen < explen) return 1;
} else if (type == CLUSTERMSG_TYPE_PUBLISH) {
uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);

Expand All @@ -1777,7 +1800,7 @@ int clusterProcessPacket(clusterLink *link) {
uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);

explen += sizeof(clusterMsgDataUpdate);
if (totlen != explen) return 1;
if (totlen < explen) return 1;
} else if (type == CLUSTERMSG_TYPE_MODULE) {
uint32_t explen = sizeof(clusterMsg)-sizeof(union clusterMsgData);

Expand Down Expand Up @@ -4123,11 +4146,15 @@ sds clusterGenNodeDescription(clusterNode *node) {
sds ci;

/* Node coordinates */
ci = sdscatprintf(sdsempty(),"%.40s %s:%d@%d ",
ci = sdscatprintf(sdsempty(),"%.40s %s:%d@%d",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we need to add hostname support, we would need to bring in extensions mechanism to older version as well.

node->name,
node->ip,
node->port,
node->cport);
if (node->hostname && sdslen(node->hostname) > 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to add a nodes.conf file with hostname in it and verify it gets loaded fine.

ci = sdscatfmt(ci,",%s",node->hostname);
}
ci = sdscat(ci," ");

/* Flags */
ci = representClusterNodeFlags(ci, node->flags);
Expand Down Expand Up @@ -4955,7 +4982,10 @@ int verifyDumpPayload(unsigned char *p, size_t len) {

/* Verify RDB version */
rdbver = (footer[1] << 8) | footer[0];
if (rdbver > RDB_VERSION) return C_ERR;
if ((rdbver >= RDB_FOREIGN_VERSION_MIN && rdbver <= RDB_FOREIGN_VERSION_MAX) ||
(rdbver > RDB_VERSION && server.rdb_version_check == RDB_VERSION_CHECK_STRICT)) {
return C_ERR;
}

/* Verify CRC64 */
crc = crc64(0,p,len-8);
Expand Down
1 change: 1 addition & 0 deletions src/cluster.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ typedef struct clusterNode {
int cport; /* Latest known cluster port of this node. */
clusterLink *link; /* TCP/IP link with this node */
list *fail_reports; /* List of nodes signaling this as failing */
sds hostname;
} clusterNode;

typedef struct clusterState {
Expand Down
7 changes: 7 additions & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ configEnum oom_score_adj_enum[] = {
{NULL, 0}
};

configEnum rdb_version_check_enum[] = {
{"strict", RDB_VERSION_CHECK_STRICT}, // strict: Reject future RDB versions.
{"relaxed", RDB_VERSION_CHECK_RELAXED}, // relaxed: Try parsing future RDB versions and fail only when an unknown RDB opcode or type is encountered.
{NULL, 0}
};

/* Output buffer limits presets. */
clientBufferLimitsConfig clientBufferLimitsDefaults[CLIENT_TYPE_OBUF_COUNT] = {
{0, 0, 0}, /* normal */
Expand Down Expand Up @@ -2327,6 +2333,7 @@ standardConfig configs[] = {
createEnumConfig("maxmemory-policy", NULL, MODIFIABLE_CONFIG, maxmemory_policy_enum, server.maxmemory_policy, MAXMEMORY_NO_EVICTION, NULL, NULL),
createEnumConfig("appendfsync", NULL, MODIFIABLE_CONFIG, aof_fsync_enum, server.aof_fsync, AOF_FSYNC_EVERYSEC, NULL, NULL),
createEnumConfig("oom-score-adj", NULL, MODIFIABLE_CONFIG, oom_score_adj_enum, server.oom_score_adj, OOM_SCORE_ADJ_NO, NULL, updateOOMScoreAdj),
createEnumConfig("rdb-version-check", NULL, MODIFIABLE_CONFIG, rdb_version_check_enum, server.rdb_version_check, RDB_VERSION_CHECK_RELAXED, NULL, NULL),

/* Integer configs */
createIntConfig("databases", NULL, IMMUTABLE_CONFIG, 1, INT_MAX, server.dbnum, 16, INTEGER_CONFIG, NULL, NULL),
Expand Down
33 changes: 24 additions & 9 deletions src/rdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@
#include "zipmap.h"
#include "endianconv.h"
#include "stream.h"
#include "rdb_downgrade_compat.h" /* RDB downgrade compatibility */

#include <math.h>
#include <fcntl.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
Expand Down Expand Up @@ -2132,22 +2134,34 @@ int rdbLoadRio(rio *rdb, int rdbflags, rdbSaveInfo *rsi) {
int type, rdbver;
redisDb *db = server.db+0;
char buf[1024];
bool is_valkey_magic;

rdb->update_cksum = rdbLoadProgressCallback;
rdb->max_processing_chunk = server.loading_process_events_interval_bytes;
if (rioRead(rdb,buf,9) == 0) goto eoferr;
buf[9] = '\0';
if (memcmp(buf,"REDIS",5) != 0) {
serverLog(LL_WARNING,"Wrong signature trying to load DB from file");
if (memcmp(buf, "REDIS0", 6) == 0) {
is_valkey_magic = false;
} else if (memcmp(buf, "VALKEY", 6) == 0) {
is_valkey_magic = true;
} else {
serverLog(LL_WARNING, "Wrong signature trying to load DB from file");
errno = EINVAL;
return C_ERR;
}
rdbver = atoi(buf+5);
if (rdbver < 1 || rdbver > RDB_VERSION) {
rdbver = atoi(buf + 6);
if (rdbver < 1 ||
(rdbver >= RDB_FOREIGN_VERSION_MIN && !is_valkey_magic) ||
(rdbver > RDB_VERSION && server.rdb_version_check == RDB_VERSION_CHECK_STRICT)) {
serverLog(LL_WARNING,"Can't handle RDB format version %d",rdbver);
errno = EINVAL;
return C_ERR;
}

/* Log compatibility mode for higher versions */
if (rdbver > RDB_VERSION) {
serverLog(LL_NOTICE,"Loading RDB version %d with downgrade compatibility (current version: %d)", rdbver, RDB_VERSION);
}

/* Key-specific attributes, set by opcodes before the key type. */
long long lru_idle = -1, lfu_freq = -1, expiretime = -1, now = mstime();
Expand Down Expand Up @@ -2246,9 +2260,10 @@ int rdbLoadRio(rio *rdb, int rdbflags, rdbSaveInfo *rsi) {
"Can't load Lua script from RDB file! "
"BODY: %s", (char*)auxval->ptr);
}
} else if (!strcasecmp(auxkey->ptr,"redis-ver")) {
serverLog(LL_NOTICE,"Loading RDB produced by version %s",
(char*)auxval->ptr);
} else if (!strcasecmp(auxkey->ptr, "redis-ver")) {
serverLog(LL_NOTICE, "Loading RDB produced by Redis version %s", (char *)auxval->ptr);
} else if (!strcasecmp(auxkey->ptr, "valkey-ver")) {
serverLog(LL_NOTICE, "Loading RDB produced by Valkey version %s", (char *)auxval->ptr);
} else if (!strcasecmp(auxkey->ptr,"ctime")) {
time_t age = time(NULL)-strtol(auxval->ptr,NULL,10);
if (age < 0) age = 0;
Expand Down Expand Up @@ -2331,8 +2346,8 @@ int rdbLoadRio(rio *rdb, int rdbflags, rdbSaveInfo *rsi) {
/* Read key */
if ((key = rdbGenericLoadStringObject(rdb,RDB_LOAD_SDS,NULL)) == NULL)
goto eoferr;
/* Read value */
if ((val = rdbLoadObject(type,rdb,key)) == NULL) {
/* Read value with compatibility support for higher RDB versions */
if ((val = rdbLoadObjectCompat(type,rdb,key,NULL,rdbver)) == NULL) {
sdsfree(key);
goto eoferr;
}
Expand Down
27 changes: 25 additions & 2 deletions src/rdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,25 @@
#include "server.h"

/* The current RDB version. When the format changes in a way that is no longer
* backward compatible this number gets incremented. */
* backward compatible this number gets incremented.
*
* RDB 11 is the last open-source Redis RDB version, used by Valkey 7.x and 8.x.
*
* RDB 12+ are non-open-source Redis formats.
*
* Next time we bump the Valkey RDB version, use much higher version to avoid
* collisions with non-OSS Redis RDB versions. For example, we could use RDB
* version 90 for Valkey 9.0.
*
* In an RDB file/stream, we also check the magic string REDIS or VALKEY but in
* the DUMP/RESTORE format, there is only the RDB version number and no magic
* string. */
#define RDB_VERSION 9

/* Reserved range for foreign (unsupported, non-OSS) RDB format. */
#define RDB_FOREIGN_VERSION_MIN 12
#define RDB_FOREIGN_VERSION_MAX 79

/* Defines related to the dump file format. To store 32 bits lengths for short
* keys requires a lot of space, so we check the most significant 2 bits of
* the first byte to interpreter the length:
Expand Down Expand Up @@ -91,10 +107,17 @@
#define RDB_TYPE_HASH_ZIPLIST 13
#define RDB_TYPE_LIST_QUICKLIST 14
#define RDB_TYPE_STREAM_LISTPACKS 15
/* RDB 11 types for downgrade compatibility */
#define RDB_TYPE_HASH_LISTPACK 16
#define RDB_TYPE_ZSET_LISTPACK 17
#define RDB_TYPE_LIST_QUICKLIST_2 18
#define RDB_TYPE_STREAM_LISTPACKS_2 19
#define RDB_TYPE_SET_LISTPACK 20
#define RDB_TYPE_STREAM_LISTPACKS_3 21
/* NOTE: WHEN ADDING NEW RDB TYPE, UPDATE rdbIsObjectType() BELOW */

/* Test if a type is an object type. */
#define rdbIsObjectType(t) ((t >= 0 && t <= 7) || (t >= 9 && t <= 15))
#define rdbIsObjectType(t) ((t >= 0 && t <= 7) || (t >= 9 && t <= 21))

/* Special RDB opcodes (saved/loaded with rdbSaveType/rdbLoadType). */
#define RDB_OPCODE_MODULE_AUX 247 /* Module auxiliary data. */
Expand Down
Loading
Loading