0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-17 23:44:39 -05:00

Added performance metrics to redis cache purging (#19039)

no issue

Began tracking the following metrics when purging the redis cache:
1. cache_reset_scan - total time to scan the keyspace
2. cache_reset_delete - total time to delete all the matching keys
3. cache_reset - total time in ms to reset the cache
4. cache_reset_keys - total number of keys deleted

We can reduce the granularity of these alerts to reduce the load on
elastic eventually, but for now it would be nice to collect metrics at
this granularity so we can optimize the cache purging performance.
This commit is contained in:
Chris Raible 2023-11-17 00:17:16 -08:00 committed by GitHub
parent c0e39affd0
commit 22aac1abd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,5 +1,7 @@
const BaseCacheAdapter = require('@tryghost/adapter-base-cache');
const logging = require('@tryghost/logging');
const metrics = require('@tryghost/metrics');
const debug = require('@tryghost/debug')('redis-cache');
const cacheManager = require('cache-manager');
const redisStoreFactory = require('./redis-store-factory');
const calculateSlot = require('cluster-key-slot');
@ -63,6 +65,7 @@ class AdapterCacheRedis extends BaseCacheAdapter {
}
#getPrimaryRedisNode() {
debug('getPrimaryRedisNode');
if (this.redisClient.constructor.name !== 'Cluster') {
return this.redisClient;
}
@ -77,6 +80,7 @@ class AdapterCacheRedis extends BaseCacheAdapter {
}
#scanNodeForKeys(node) {
debug(`scanNodeForKeys matching ${this._keysPattern}`);
return new Promise((resolve, reject) => {
const stream = node.scanStream({match: this._keysPattern, count: 100});
let keys = [];
@ -93,6 +97,7 @@ class AdapterCacheRedis extends BaseCacheAdapter {
}
async #getKeys() {
debug('#getKeys');
const primaryNode = this.#getPrimaryRedisNode();
if (primaryNode === null) {
return [];
@ -142,6 +147,7 @@ class AdapterCacheRedis extends BaseCacheAdapter {
* @param {*} value
*/
async set(key, value) {
debug('set', key);
try {
return await this.cache.set(this._buildKey(key), value);
} catch (err) {
@ -153,11 +159,21 @@ class AdapterCacheRedis extends BaseCacheAdapter {
* Reset the cache by deleting everything from redis
*/
async reset() {
debug('reset');
try {
const t0 = performance.now();
logging.debug(`[RedisAdapter] Clearing cache: scanning for keys matching ${this._keysPattern}`);
const keys = await this.#getKeys();
logging.debug(`[RedisAdapter] Clearing cache: found ${keys.length} keys matching ${this._keysPattern} in ${(performance.now() - t0).toFixed(1)}ms`);
metrics.metric('cache-reset-scan', (performance.now() - t0).toFixed(1));
const t1 = performance.now();
for (const key of keys) {
await this.cache.del(key);
}
logging.debug(`[RedisAdapter] Clearing cache: deleted ${keys.length} keys matching ${this._keysPattern} in ${(performance.now() - t1).toFixed(1)}ms`);
metrics.metric('cache-reset-delete', (performance.now() - t1).toFixed(1));
metrics.metric('cache-reset', (performance.now() - t0).toFixed(1));
metrics.metric('cache-reset-key-count', keys.length);
} catch (err) {
logging.error(err);
}