16

I’m using the spring-boot spring-data-redis 1.8.9.RELEASE RedisCacheManager implementation of CacheManager for caching. One metric that I want visibility into is the cache hit/miss ratio. To get that, I’m extracting the keyspace_hits and keyspace_misses exposed via the redis server which can also be viewed via the redis_cli with INFO STATS. The problem is that RedisCacheManager never registers cache misses, i.e. keyspace_misses never increments even if there is a cache "miss".

Debugging the code, I see that spring-data-redis actually checks to see if the key EXISTS in redis before retrieving it. I see the sense with this approach however when EXISTS is executed against the redis server, it does not register a cache miss.

Is there any way to use RedisCacheManager and register cache misses? I know I can use other redis objects to accomplish this but I was wondering if it could be done with the standard CacheManager implementation?

Edit

The ideal solution won't add a great deal of overhead and I am unable to edit the configuration of the redis server.

Code that RedisCacheManager uses when retrieving an element from cache. Notice Boolean exists:

public RedisCacheElement get(final RedisCacheKey cacheKey) {
    Assert.notNull(cacheKey, "CacheKey must not be null!");
    Boolean exists = (Boolean)this.redisOperations.execute(new RedisCallback<Boolean>() {
        public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
            return connection.exists(cacheKey.getKeyBytes());
        }
    });
    return !exists ? null : new RedisCacheElement(cacheKey, this.fromStoreValue(this.lookup(cacheKey)));
}

The above code will execute these commands on redis viewable via MONITOR on a cache miss. Notice again that EXISTS is executed as per the code:

Redis commands executed for a cache miss

After the above commands are executed, keyspace_misses is not incremented even though there was a cache miss:

enter image description here

Always Learning
  • 2,623
  • 3
  • 20
  • 39

1 Answers1

1

The code mentioned in the question is part of RedisCache provided by Spring.

  1. Extend and Create a custom implementation of RedisCache class to override the behavior of "get" method to suit your need.
  2. Extend RedisCacheManager to override the method "createRedisCache" to use your custom RedisCache that you created in first step instead of default cache.
sm19
  • 11
  • 2
  • Thanks for your input. Can you provide working code to prove your answer out? I've taken a look and I don't see a feasible mechanism to accomplish the above. – Always Learning Jul 31 '18 at 16:44
  • 1
    I know this is old but I can confirm this method works, it is a bit convoluted as not all classes and constructors are public but it is possible to create a Cache decorator and create a CacheManager that decorates the cache with your implementation. – frisco Jun 17 '20 at 16:08