Timestamp writes to objects so we can be smarter about merging databases

Former-commit-id: 5dc9f70386617b02fab7eee1194f321f6b4b25c5
This commit is contained in:
John Sully 2019-04-20 00:52:07 -04:00
parent 53253d993f
commit a28120cb9e
6 changed files with 31 additions and 25 deletions

View File

@ -44,8 +44,6 @@ endif
endif endif
endif endif
# CXXFLAGS+= -DENABLE_MVCC
USEASM?=true USEASM?=true
# Do we use our assembly spinlock? X64 only # Do we use our assembly spinlock? X64 only
ifeq ($(uname_S),Linux) ifeq ($(uname_S),Linux)

View File

@ -70,6 +70,10 @@ static robj *lookupKey(redisDb *db, robj *key, int flags) {
val->lru = LRU_CLOCK(); val->lru = LRU_CLOCK();
} }
} }
if (flags & LOOKUP_UPDATEMVCC) {
val->mvcc_tstamp = getMvccTstamp();
}
return val; return val;
} else { } else {
return NULL; return NULL;
@ -157,7 +161,7 @@ robj_roptr lookupKeyRead(redisDb *db, robj *key) {
* does not exist in the specified DB. */ * does not exist in the specified DB. */
robj *lookupKeyWrite(redisDb *db, robj *key) { robj *lookupKeyWrite(redisDb *db, robj *key) {
expireIfNeeded(db,key); expireIfNeeded(db,key);
return lookupKey(db,key,LOOKUP_NONE); return lookupKey(db,key,LOOKUP_UPDATEMVCC);
} }
robj_roptr lookupKeyReadOrReply(client *c, robj *key, robj *reply) { robj_roptr lookupKeyReadOrReply(client *c, robj *key, robj *reply) {
@ -175,9 +179,7 @@ robj *lookupKeyWriteOrReply(client *c, robj *key, robj *reply) {
int dbAddCore(redisDb *db, robj *key, robj *val) { int dbAddCore(redisDb *db, robj *key, robj *val) {
sds copy = sdsdup(szFromObj(key)); sds copy = sdsdup(szFromObj(key));
int retval = dictAdd(db->pdict, copy, val); int retval = dictAdd(db->pdict, copy, val);
#ifdef ENABLE_MVCC
val->mvcc_tstamp = key->mvcc_tstamp = getMvccTstamp(); val->mvcc_tstamp = key->mvcc_tstamp = getMvccTstamp();
#endif
if (retval == DICT_OK) if (retval == DICT_OK)
{ {
@ -211,12 +213,9 @@ void dbOverwriteCore(redisDb *db, dictEntry *de, robj *val, bool fUpdateMvcc)
if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) { if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {
val->lru = old->lru; val->lru = old->lru;
} }
#ifdef ENABLE_MVCC
if (fUpdateMvcc) if (fUpdateMvcc)
val->mvcc_tstamp = getMvccTstamp(); val->mvcc_tstamp = getMvccTstamp();
#else
UNUSED(fUpdateMvcc);
#endif
dictSetVal(db->pdict, de, val); dictSetVal(db->pdict, de, val);
if (server.lazyfree_lazy_server_del) { if (server.lazyfree_lazy_server_del) {
@ -247,14 +246,14 @@ int dbMerge(redisDb *db, robj *key, robj *val, int fReplace)
dictEntry *de = dictFind(db->pdict, ptrFromObj(key)); dictEntry *de = dictFind(db->pdict, ptrFromObj(key));
if (de == nullptr) if (de == nullptr)
return (dbAddCore(db, key, val) == DICT_OK); return (dbAddCore(db, key, val) == DICT_OK);
#ifdef ENABLE_MVCC
robj *old = (robj*)dictGetVal(de); robj *old = (robj*)dictGetVal(de);
if (old->mvcc_tstamp <= val->mvcc_tstamp) if (old->mvcc_tstamp <= val->mvcc_tstamp)
#endif
{ {
dbOverwriteCore(db, de, val, false); dbOverwriteCore(db, de, val, false);
return true; return true;
} }
return false; return false;
} }
else else

View File

@ -44,9 +44,7 @@ robj *createObject(int type, void *ptr) {
o->encoding = OBJ_ENCODING_RAW; o->encoding = OBJ_ENCODING_RAW;
o->m_ptr = ptr; o->m_ptr = ptr;
o->refcount = 1; o->refcount = 1;
#ifdef ENABLE_MVCC
o->mvcc_tstamp = OBJ_MVCC_INVALID; o->mvcc_tstamp = OBJ_MVCC_INVALID;
#endif
/* Set the LRU to the current lruclock (minutes resolution), or /* Set the LRU to the current lruclock (minutes resolution), or
* alternatively the LFU counter. */ * alternatively the LFU counter. */
@ -94,9 +92,8 @@ robj *createEmbeddedStringObject(const char *ptr, size_t len) {
o->type = OBJ_STRING; o->type = OBJ_STRING;
o->encoding = OBJ_ENCODING_EMBSTR; o->encoding = OBJ_ENCODING_EMBSTR;
o->refcount = 1; o->refcount = 1;
#ifdef ENABLE_MVCC
o->mvcc_tstamp = OBJ_MVCC_INVALID; o->mvcc_tstamp = OBJ_MVCC_INVALID;
#endif
if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) { if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) {
o->lru = (LFUGetTimeInMinutes()<<8) | LFU_INIT_VAL; o->lru = (LFUGetTimeInMinutes()<<8) | LFU_INIT_VAL;
} else { } else {

View File

@ -1061,11 +1061,9 @@ int rdbSaveKeyValuePair(rio *rdb, robj *key, robj *val, long long expiretime) {
if (rdbWriteRaw(rdb,buf,1) == -1) return -1; if (rdbWriteRaw(rdb,buf,1) == -1) return -1;
} }
#ifdef ENABLE_MVCC
char szMvcc[32]; char szMvcc[32];
snprintf(szMvcc, 32, "%" PRIu64, val->mvcc_tstamp); snprintf(szMvcc, 32, "%" PRIu64, val->mvcc_tstamp);
if (rdbSaveAuxFieldStrStr(rdb,"mvcc-tstamp", szMvcc) == -1) return -1; if (rdbSaveAuxFieldStrStr(rdb,"mvcc-tstamp", szMvcc) == -1) return -1;
#endif
/* Save type, key, value */ /* Save type, key, value */
if (rdbSaveObjectType(rdb,val) == -1) return -1; if (rdbSaveObjectType(rdb,val) == -1) return -1;
@ -1822,11 +1820,8 @@ robj *rdbLoadObject(int rdbtype, rio *rdb, robj *key, uint64_t mvcc_tstamp) {
} else { } else {
rdbExitReportCorruptRDB("Unknown RDB encoding type %d",rdbtype); rdbExitReportCorruptRDB("Unknown RDB encoding type %d",rdbtype);
} }
#ifdef ENABLE_MVCC
o->mvcc_tstamp = mvcc_tstamp; o->mvcc_tstamp = mvcc_tstamp;
#else
UNUSED(mvcc_tstamp);
#endif
return o; return o;
} }

View File

@ -2933,6 +2933,8 @@ void initServer(void) {
server.aof_last_write_errno = 0; server.aof_last_write_errno = 0;
server.repl_good_slaves_count = 0; server.repl_good_slaves_count = 0;
server.mvcc_tstamp = 0;
/* Create the timer callback, this is our way to process many background /* Create the timer callback, this is our way to process many background
* operations incrementally, like clients timeout, eviction of unaccessed * operations incrementally, like clients timeout, eviction of unaccessed
* expired keys and so forth. */ * expired keys and so forth. */
@ -3423,6 +3425,7 @@ int processCommand(client *c, int callFlags) {
AssertCorrectThread(c); AssertCorrectThread(c);
serverAssert(GlobalLocksAcquired()); serverAssert(GlobalLocksAcquired());
incrementMvccTstamp();
/* Now lookup the command and check ASAP about trivial error conditions /* Now lookup the command and check ASAP about trivial error conditions
* such as wrong arity, bad command name and so forth. */ * such as wrong arity, bad command name and so forth. */
@ -4879,7 +4882,20 @@ int redisIsSupervised(int mode) {
uint64_t getMvccTstamp() uint64_t getMvccTstamp()
{ {
return (server.mstime << 16); return server.mvcc_tstamp;
}
void incrementMvccTstamp()
{
uint64_t msPrev = server.mvcc_tstamp >> 22;
if (msPrev >= (uint64_t)server.mstime) // we can be greater if the count overflows
{
atomicIncr(server.mvcc_tstamp, 1);
}
else
{
server.mvcc_tstamp = ((uint64_t)server.mstime) << 22;
}
} }
void *workerThreadMain(void *parg) void *workerThreadMain(void *parg)

View File

@ -709,10 +709,8 @@ typedef struct redisObject {
unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
* LFU data (least significant 8 bits frequency * LFU data (least significant 8 bits frequency
* and most significant 16 bits access time). */ * and most significant 16 bits access time). */
#ifdef ENABLE_MVCC
uint64_t mvcc_tstamp;
#endif
mutable int refcount; mutable int refcount;
uint64_t mvcc_tstamp;
void *m_ptr; void *m_ptr;
} robj; } robj;
@ -1526,6 +1524,7 @@ struct redisServer {
unsigned char uuid[UUID_BINARY_LEN]; /* This server's UUID - populated on boot */ unsigned char uuid[UUID_BINARY_LEN]; /* This server's UUID - populated on boot */
struct fastlock flock; struct fastlock flock;
uint64_t mvcc_tstamp;
}; };
typedef struct pubsubPattern { typedef struct pubsubPattern {
@ -2136,6 +2135,7 @@ void objectSetLRUOrLFU(robj *val, long long lfu_freq, long long lru_idle,
long long lru_clock); long long lru_clock);
#define LOOKUP_NONE 0 #define LOOKUP_NONE 0
#define LOOKUP_NOTOUCH (1<<0) #define LOOKUP_NOTOUCH (1<<0)
#define LOOKUP_UPDATEMVCC (1<<1)
void dbAdd(redisDb *db, robj *key, robj *val); void dbAdd(redisDb *db, robj *key, robj *val);
void dbOverwrite(redisDb *db, robj *key, robj *val); void dbOverwrite(redisDb *db, robj *key, robj *val);
int dbMerge(redisDb *db, robj *key, robj *val, int fReplace); int dbMerge(redisDb *db, robj *key, robj *val, int fReplace);
@ -2447,6 +2447,7 @@ struct redisMaster *MasterInfoFromClient(client *c);
/* MVCC */ /* MVCC */
uint64_t getMvccTstamp(); uint64_t getMvccTstamp();
void incrementMvccTstamp();
#if defined(__GNUC__) #if defined(__GNUC__)
#ifndef __cplusplus #ifndef __cplusplus