Skip to content

Commit 101b3a6

Browse files
committed
Convert quicklist RDB to store ziplist nodes
Turns out it's a huge improvement during save/reload/migrate/restore because, with compression enabled, we're compressing 4k or 8k chunks of data consisting of multiple elements in one ziplist instead of compressing series of smaller individual elements.
1 parent 127c15e commit 101b3a6

File tree

2 files changed

+24
-15
lines changed

2 files changed

+24
-15
lines changed

src/rdb.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ int rdbSaveObjectType(rio *rdb, robj *o) {
434434
return rdbSaveType(rdb,REDIS_RDB_TYPE_STRING);
435435
case REDIS_LIST:
436436
if (o->encoding == REDIS_ENCODING_QUICKLIST)
437-
return rdbSaveType(rdb,REDIS_RDB_TYPE_LIST);
437+
return rdbSaveType(rdb,REDIS_RDB_TYPE_LIST_QUICKLIST);
438438
else
439439
redisPanic("Unknown list encoding");
440440
case REDIS_SET:
@@ -484,22 +484,16 @@ int rdbSaveObject(rio *rdb, robj *o) {
484484
} else if (o->type == REDIS_LIST) {
485485
/* Save a list value */
486486
if (o->encoding == REDIS_ENCODING_QUICKLIST) {
487-
quicklist *list = o->ptr;
488-
quicklistIter *li = quicklistGetIterator(list, AL_START_HEAD);
489-
quicklistEntry entry;
487+
quicklist *ql = o->ptr;
488+
quicklistNode *node = ql->head;
490489

491-
if ((n = rdbSaveLen(rdb,quicklistCount(list))) == -1) return -1;
490+
if ((n = rdbSaveLen(rdb,ql->len)) == -1) return -1;
492491
nwritten += n;
493492

494-
while (quicklistNext(li,&entry)) {
495-
if (entry.value) {
496-
if ((n = rdbSaveRawString(rdb,entry.value,entry.sz)) == -1) return -1;
497-
} else {
498-
if ((n = rdbSaveLongLongAsStringObject(rdb,entry.longval)) == -1) return -1;
499-
}
493+
do {
494+
if ((n = rdbSaveRawString(rdb,node->zl,node->sz)) == -1) return -1;
500495
nwritten += n;
501-
}
502-
quicklistReleaseIterator(li);
496+
} while ((node = node->next));
503497
} else {
504498
redisPanic("Unknown list encoding");
505499
}
@@ -974,7 +968,19 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) {
974968

975969
/* All pairs should be read by now */
976970
redisAssert(len == 0);
971+
} else if (rdbtype == REDIS_RDB_TYPE_LIST_QUICKLIST) {
972+
if ((len = rdbLoadLen(rdb,NULL)) == REDIS_RDB_LENERR) return NULL;
973+
o = createQuicklistObject();
977974

975+
while (len--) {
976+
if ((ele = rdbLoadStringObject(rdb)) == NULL) return NULL;
977+
/* 'ele' contains a sds of the ziplist, but we need to extract
978+
* the actual ziplist for future usage. We must copy the
979+
* sds contents to a new buffer. */
980+
unsigned char *zl = (unsigned char *)sdsnative(ele->ptr);
981+
zfree(ele); /* free robj container since we keep the ziplist */
982+
quicklistAppendZiplist(o->ptr, zl);
983+
}
978984
} else if (rdbtype == REDIS_RDB_TYPE_HASH_ZIPMAP ||
979985
rdbtype == REDIS_RDB_TYPE_LIST_ZIPLIST ||
980986
rdbtype == REDIS_RDB_TYPE_SET_INTSET ||

src/rdb.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
/* The current RDB version. When the format changes in a way that is no longer
4040
* backward compatible this number gets incremented. */
41-
#define REDIS_RDB_VERSION 6
41+
#define REDIS_RDB_VERSION 7
4242

4343
/* Defines related to the dump file format. To store 32 bits lengths for short
4444
* keys requires a lot of space, so we check the most significant 2 bits of
@@ -74,16 +74,19 @@
7474
#define REDIS_RDB_TYPE_SET 2
7575
#define REDIS_RDB_TYPE_ZSET 3
7676
#define REDIS_RDB_TYPE_HASH 4
77+
/* NOTE: WHEN ADDING NEW RDB TYPE, UPDATE rdbIsObjectType() BELOW */
7778

7879
/* Object types for encoded objects. */
7980
#define REDIS_RDB_TYPE_HASH_ZIPMAP 9
8081
#define REDIS_RDB_TYPE_LIST_ZIPLIST 10
8182
#define REDIS_RDB_TYPE_SET_INTSET 11
8283
#define REDIS_RDB_TYPE_ZSET_ZIPLIST 12
8384
#define REDIS_RDB_TYPE_HASH_ZIPLIST 13
85+
#define REDIS_RDB_TYPE_LIST_QUICKLIST 14
86+
/* NOTE: WHEN ADDING NEW RDB TYPE, UPDATE rdbIsObjectType() BELOW */
8487

8588
/* Test if a type is an object type. */
86-
#define rdbIsObjectType(t) ((t >= 0 && t <= 4) || (t >= 9 && t <= 13))
89+
#define rdbIsObjectType(t) ((t >= 0 && t <= 4) || (t >= 9 && t <= 14))
8790

8891
/* Special RDB opcodes (saved/loaded with rdbSaveType/rdbLoadType). */
8992
#define REDIS_RDB_OPCODE_EXPIRETIME_MS 252

0 commit comments

Comments
 (0)