2
  • I currently have an API in aws with autoscaling so I can have from 7 to 12 services running.
  • For my client manager I am doing builder.register<IRedisClientsManager>(c => new PooledRedisClientManager(conection));
  • For my client I am doing redis.GetCacheClient();
  • to set a cache entry I am doing: cache_client.Set<T>(generate_key<T>(key), values, TimeSpan.FromSeconds(ttl.Value));

  • To get a cache entry I am doing: using (var read_only_client = this.redis.GetReadOnlyClient()) { return read_only_client.GetValue(generate_key<T>(key)); }

ISSUE => I am getting invalid cache values malformed JSON and misplaced text.

QUESTION => the reason I am getting invalid cache values is because I need to use Redis locks before setting or getting a cache value????

1 Answers1

1

You'll rarely ever need to use RedisLocks which are for implementing a custom distributed locking. All Redis operations are atomic and if you need to send multiple operations atomically you can use either Redis Transactions or implement a LUA Script.

Without seeing the full Exception details or corrupted data, the issue is most likely reusing the same Redis Client instance across multiple threads. The IRedisClientsManager is ThreadSafe and should be registered as a singleton, but the client instances it returns are not ThreadSafe and should not be shared amongst multiple threads, used as a singleton, stored in a static variable, etc. To ensure proper usage each thread that uses them should resolve them and

using (var redis = redisManager.GetClient())
{
    //...
}

Redis Client and Cache Registration Example

You should be registering both the IRedisClientsManager and ICacheClient as singletons, e.g:

container.Register<IRedisClientsManager>(c => 
    new RedisManagerPool(connection));

container.Register(c => c.Resolve<IRedisClientsManager>().GetCacheClient());

Given the Redis ICacheClientis ThreadSafe the issue is in another area of your code where you're using the same Redis Instance across multiple threads. Make sure you carefully review all usages of Redis to ensure each Redis Client is properly disposed of and not shared amongst different threads.

If the issue continues despite proper usage of the library, please put together a stand-alone example project (e.g on GitHub) that we can run to see the issue and we'll review it.

mythz
  • 141,670
  • 29
  • 246
  • 390
  • The only thing I can think of is not registering ICacheClient as a singleton. I am doing redis.GetCacheClient(); in the constructor of my class (and the class is not static). But that should not be the problem right ? I always use ICacheClient except on a read but there I am wrapping it on a using using (var read_only_client = this.redis.GetReadOnlyClient()) { return read_only_client.GetValue(generate_key(key)); } – Maria Abreu Oct 04 '17 at 13:57
  • another thing I just saw is that I have two register lines one for my cache an another one of RedisMQServer with different connection string. could that be the problem ? @mythz var redis_factory = new PooledRedisClientManager(queue_connection); builder.register(c => redis_factory); builder.register(c => new RedisMqServer(redis_factory)); ... then builder.Register(c => new PooledRedisClientManager(cache_connection)); – Maria Abreu Oct 04 '17 at 15:12
  • Not registering the Redis ICacheClient is not the problem, also you should be using the same `PooledRedisClientManager` instance for everything including `RedisMqServer`. The best way to identify the issue is to put together a small stand-alone project that we can run to repro the issue. – mythz Oct 04 '17 at 17:29
  • I haven't been able to reproduce the issue locally but it happens a lot in prod. – Maria Abreu Oct 05 '17 at 13:16
  • @MariaAbreu If you can't repro the issue, no-one else is going to be able to either. If you're testing this against a local Redis instance, try running against a remote Redis instance on a different computer. – mythz Oct 05 '17 at 17:49