Get all keys from Redis Cache database

28,312

Solution 1

Function that you need is under IServer interface, and can be reached with:

ConnectionMultiplexer m = CreateConnection();
m.GetServer("host").Keys();

Note that prior to version 2.8 of redis server that will use KEYS command you mentioned, and it can be very slow in certain cases. However if you use redis 2.8+ - it will use SCAN command instead, which performs better. Also ensure that you really need to get all keys, in my practice I've never ever needed this.

Solution 2

string connectionString = "my_connection_string";
ConfigurationOptions options = ConfigurationOptions.Parse(connectionString);
ConnectionMultiplexer connection = ConnectionMultiplexer.Connect(options);
IDatabase db = connection.GetDatabase();
EndPoint endPoint = connection.GetEndPoints().First();
RedisKey[] keys = connection.GetServer(endPoint).Keys(pattern: "*").ToArray();

Solution 3

Try using this code snippet, it worked for me:

IServer server = Connection.GetServer("yourcache.redis.cache.windows....", 6380);
foreach (var key in server.Keys())
{
   Console.WriteLine(key);
}

source

Solution 4

You need db to distinguish where to look for keys. So the last line of MTZ4 answer then becomes:

RedisKey[] keys = connection.GetServer(endPoint).Keys(database: db.Database, pattern: "*").ToArray();

where db.Database is the numeric identifier of the Redis Database you want to query.

Solution 5

ASP.Net Core 3.1

Add following packages to your .csproj

<ItemGroup>
  <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="3.1.15" />
  <PackageReference Include="StackExchange.Redis.Extensions.AspNetCore" Version="7.0.1" />
  <PackageReference Include="StackExchange.Redis.Extensions.Core" Version="7.0.1" />
  <PackageReference Include="StackExchange.Redis.Extensions.Newtonsoft" Version="7.0.1" />
</ItemGroup>

In Startup.cs this is how you would be able to register Redis Client ready to be injected in your workflow code.

public class Startup
{
  public void ConfigureServices(IServiceCollection services)
  {
    // ... other registrations

    // Used By : Sample Below : RedisCacheHelperController (Method 1 Only)
    services.AddSingleton<IConnectionMultiplexer>(
            ConnectionMultiplexer.Connect(DbHelper.GetRedisConnectionHost(Options.IsDevDb()))
        );

    // Used By : Sample Below : DistributedCacheController (Method 2 Only)
    services.AddStackExchangeRedisCache(options => 
            options.Configuration = DbHelper.GetRedisConnectionHost(Options.IsDevDb())
        );

    // ... other registrations
  }
}

Note:

DbHelper.GetRedisConnectionHost(Options.IsDevDb()) :>>> is my way to resolve the connection information/string for my Redis instance respective to my environment. You can have your own way here for that or you can hard-code it here if you like to begin with.

Method 1

So, having the above stuffs in place, would be able to inject the Redis IConnectionMultiplexer into your Controllers or Services.

public class RedisCacheHelperController : ControllerBase
{
    private readonly IConnectionMultiplexer multiplexer;

    public RedisCacheHelperController(IConnectionMultiplexer multiplexer)
    {
        this.multiplexer = multiplexer;
    }
}

Here are the helper APIs to demonstrate how can you use the IConnectionMultiplexer.

public class RedisCacheHelperController : ControllerBase
{
    private readonly IConnectionMultiplexer multiplexer;

    public RedisCacheHelperController(IConnectionMultiplexer multiplexer)
    {
        this.multiplexer = multiplexer;
    }

    [HttpGet("{key}")]
    public async Task<IActionResult> GetCacheByKey([FromRoute] string key)
    {
        var responseContent = await multiplexer.GetDatabase().StringGetAsync(key);

        return Content(
           responseContent,
           Constants.ContentTypeHeaderValueJson // "application/json"
       );
    }

    [HttpPost("{key}")]
    public async Task<IActionResult> PostCacheByKey([FromRoute] string key, [FromBody] object data)
    {
        var requestContent = data.Json(); // JsonConvert.SerializeObject(data)
        await multiplexer.GetDatabase().StringSetAsync(key, requestContent);
        return Ok(key);
    }

    [HttpDelete("{key}")]
    public async Task<IActionResult> DeleteCacheByKey([FromRoute] string key)
    {
        await multiplexer.GetDatabase().KeyDeleteAsync(key);
        return Ok(key);
    }

    [HttpGet("CachedKeys")]
    public IActionResult GetListCacheKeys([FromQuery] [DefaultValue("*")] string pattern)
    {
        var keys = multiplexer
            .GetServer(multiplexer
                .GetEndPoints()
                .First())
            .Keys(pattern: pattern ?? "*")
            .Select(x => x.Get());

        return Ok(keys);
    }
   
    // ... could have more Reids supported operations here
}

Now the above is the use-case where you want access Redis Client and do more Redis specific stuffs. The package Microsoft.Extensions.Caching.StackExchangeRedis we included in .csproj above supports Reids to be registered and injected in as a IDistributedCache. The interface IDistributedCache is been defined by the Microsoft and supports basic/common functionalities by the different distributed cache solutions where Redis is one of that.

Meaning if your purpose is limited to set and/or get cache as a key-value pair, you would rather like to do it this way in Method 2 below.

Method 2

public class DistributedCacheController : ControllerBase
{
    private readonly IDistributedCache distributedCache;

    public DistributedCacheController(IDistributedCache distributedCache)
    {
        this.distributedCache = distributedCache;
    }
    
    [HttpPost("{key}")]
    public async Task<IActionResult> PostCacheByKey([FromRoute] string key, [FromBody] object data)
    {
        var requestContent = data.Json(); // JsonConvert.SerializeObject(data)
        await distributedCache.SetStringAsync(key, requestContent);
        return Ok(key);
    }

    [HttpGet("{key}")]
    public async Task<IActionResult> GetCacheByKey([FromRoute] string key)
    {
        var responseContent = await distributedCache.GetStringAsync(key);

        if (!string.IsNullOrEmpty(responseContent))
        {
            return Content(
               responseContent,
               Constants.ContentTypeHeaderValueJson // "application/json"
            );
        }

        return NotFound();
    }

    [HttpDelete("{key}")]
    public async Task<IActionResult> DeleteCacheByKey([FromRoute] string key)
    {
        await distributedCache.RemoveAsync(key);
        return Ok(key);
    }
}
Share:
28,312
Rahul
Author by

Rahul

Updated on January 26, 2022

Comments

  • Rahul
    Rahul over 2 years

    I am using Redis cache for caching purpose (specifically stackexchange.Redis C# driver. Was wondering is there any ways to get all the keys available in cache at any point in time. I mean the similar thing I can do in ASP.NET cache object (below code sample)

    var keys = Cache.GetEnumerator();                               
    while(keys.MoveNext())
    {
         keys.Key.ToString() // Key
    }
    

    Redis documentation talks about KESY command but do stackexchange.Redis have implementation for that command.

    Debugging through the connection.GetDataBase() instance, I don't see any method / property for that.

    Any idea?