Handle the case where the key cache exceeds maxmemory

Former-commit-id: 01febf902267fec7fe87e6437b0b81fd08b50963
This commit is contained in:
John Sully 2021-10-04 07:34:05 +00:00
parent e580edabac
commit db351b697a
5 changed files with 39 additions and 4 deletions

View File

@ -149,3 +149,13 @@ void StorageCache::beginWriteBatch() {
serverAssert(GlobalLocksAcquired()); // Otherwise we deadlock serverAssert(GlobalLocksAcquired()); // Otherwise we deadlock
m_spstorage->beginWriteBatch(); m_spstorage->beginWriteBatch();
} }
void StorageCache::emergencyFreeCache() {
dict *d = m_pdict;
m_pdict = nullptr;
if (d != nullptr) {
g_pserver->asyncworkqueue->AddWorkFunction([d]{
dictRelease(d);
});
}
}

View File

@ -43,6 +43,8 @@ public:
void bulkInsert(sds *rgkeys, sds *rgvals, size_t celem); void bulkInsert(sds *rgkeys, sds *rgvals, size_t celem);
void retrieve(sds key, IStorage::callbackSingle fn) const; void retrieve(sds key, IStorage::callbackSingle fn) const;
bool erase(sds key); bool erase(sds key);
void emergencyFreeCache();
bool keycacheIsEnabled() const { return m_pdict != nullptr; }
bool enumerate(IStorage::callback fn) const { return m_spstorage->enumerate(fn); } bool enumerate(IStorage::callback fn) const { return m_spstorage->enumerate(fn); }

View File

@ -3065,6 +3065,20 @@ void redisDbPersistentData::removeAllCachedValues()
} }
} }
void redisDbPersistentData::disableKeyCache()
{
if (m_spstorage == nullptr)
return;
m_spstorage->emergencyFreeCache();
}
bool redisDbPersistentData::keycacheIsEnabled()
{
if (m_spstorage == nullptr)
return false;
return m_spstorage->keycacheIsEnabled();
}
void redisDbPersistentData::trackkey(const char *key, bool fUpdate) void redisDbPersistentData::trackkey(const char *key, bool fUpdate)
{ {
if (m_fTrackingChanges && !m_fAllChanged && m_spstorage) { if (m_fTrackingChanges && !m_fAllChanged && m_spstorage) {

View File

@ -868,6 +868,10 @@ cant_free:
redisDb *db = g_pserver->db[idb]; redisDb *db = g_pserver->db[idb];
if (db->FStorageProvider()) if (db->FStorageProvider())
{ {
if (db->size() != 0 && db->size(true /*fcachedOnly*/) == 0 && db->keycacheIsEnabled()) {
serverLog(LL_WARNING, "Key cache exceeds maxmemory, freeing - performance may be affected increase maxmemory if possible");
db->disableKeyCache();
} else if (db->size(true /*fCachedOnly*/)) {
serverLog(LL_WARNING, "Failed to evict keys, falling back to flushing entire cache. Consider increasing maxmemory-samples."); serverLog(LL_WARNING, "Failed to evict keys, falling back to flushing entire cache. Consider increasing maxmemory-samples.");
db->removeAllCachedValues(); db->removeAllCachedValues();
if (((mem_reported - zmalloc_used_memory()) + mem_freed) >= mem_tofree) if (((mem_reported - zmalloc_used_memory()) + mem_freed) >= mem_tofree)
@ -875,6 +879,7 @@ cant_free:
} }
} }
} }
}
if (result == EVICT_FAIL) { if (result == EVICT_FAIL) {
/* At this point, we have run out of evictable items. It's possible /* At this point, we have run out of evictable items. It's possible

View File

@ -1182,6 +1182,8 @@ public:
bool FStorageProvider() { return m_spstorage != nullptr; } bool FStorageProvider() { return m_spstorage != nullptr; }
bool removeCachedValue(const char *key, dictEntry **ppde = nullptr); bool removeCachedValue(const char *key, dictEntry **ppde = nullptr);
void removeAllCachedValues(); void removeAllCachedValues();
void disableKeyCache();
bool keycacheIsEnabled();
bool prefetchKeysAsync(client *c, struct parsed_command &command, bool fExecOK); bool prefetchKeysAsync(client *c, struct parsed_command &command, bool fExecOK);
@ -1337,6 +1339,8 @@ struct redisDb : public redisDbPersistentDataSnapshot
using redisDbPersistentData::endSnapshot; using redisDbPersistentData::endSnapshot;
using redisDbPersistentData::restoreSnapshot; using redisDbPersistentData::restoreSnapshot;
using redisDbPersistentData::removeAllCachedValues; using redisDbPersistentData::removeAllCachedValues;
using redisDbPersistentData::disableKeyCache;
using redisDbPersistentData::keycacheIsEnabled;
using redisDbPersistentData::dictUnsafeKeyOnly; using redisDbPersistentData::dictUnsafeKeyOnly;
using redisDbPersistentData::resortExpire; using redisDbPersistentData::resortExpire;
using redisDbPersistentData::prefetchKeysAsync; using redisDbPersistentData::prefetchKeysAsync;