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

@ -148,4 +148,14 @@ size_t StorageCache::count() const
void StorageCache::beginWriteBatch() { 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,10 +868,15 @@ cant_free:
redisDb *db = g_pserver->db[idb]; redisDb *db = g_pserver->db[idb];
if (db->FStorageProvider()) if (db->FStorageProvider())
{ {
serverLog(LL_WARNING, "Failed to evict keys, falling back to flushing entire cache. Consider increasing maxmemory-samples."); if (db->size() != 0 && db->size(true /*fcachedOnly*/) == 0 && db->keycacheIsEnabled()) {
db->removeAllCachedValues(); serverLog(LL_WARNING, "Key cache exceeds maxmemory, freeing - performance may be affected increase maxmemory if possible");
if (((mem_reported - zmalloc_used_memory()) + mem_freed) >= mem_tofree) db->disableKeyCache();
result = EVICT_OK; } else if (db->size(true /*fCachedOnly*/)) {
serverLog(LL_WARNING, "Failed to evict keys, falling back to flushing entire cache. Consider increasing maxmemory-samples.");
db->removeAllCachedValues();
if (((mem_reported - zmalloc_used_memory()) + mem_freed) >= mem_tofree)
result = EVICT_OK;
}
} }
} }
} }

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;