Skip to content

Instantly share code, notes, and snippets.

@Salgat
Created October 19, 2023 21:29
Show Gist options
  • Save Salgat/af810521ff3dce4ef89ca61a60b2cc4b to your computer and use it in GitHub Desktop.
Save Salgat/af810521ff3dce4ef89ca61a60b2cc4b to your computer and use it in GitHub Desktop.
Query Redis memory usage per key using C#
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using StackExchange.Redis;
namespace query_redis_memory_usage
{
class Program
{
static async Task Main(string[] args)
{
var connectionString = "127.0.0.1:6379";
var connectionConfiguration = ConfigurationOptions.Parse(connectionString);
var connection = await ConnectionMultiplexer.ConnectAsync(connectionConfiguration).ConfigureAwait(false);
var database = connection.GetDatabase(0);
var cursor = "0";
var keyMemoryMap = new Dictionary<string, long>();
do
{
var result = (RedisResult[])await database.ExecuteAsync("SCAN", cursor, "COUNT", 500);
cursor = (string)result[0];
var keys = (RedisResult[])result[1];
var batch = database.CreateBatch();
var tasks = new List<(string, Task<RedisResult>)>();
foreach (var key in keys)
{
var keyName = (string)key;
var memoryOperation = batch.ScriptEvaluateAsync("return redis.call('MEMORY', 'USAGE', KEYS[1])", new RedisKey[] { keyName });
tasks.Add((keyName, memoryOperation));
}
batch.Execute();
await Task.WhenAll(tasks.Select(t => t.Item2)).ConfigureAwait(false);
foreach (var task in tasks)
{
keyMemoryMap[task.Item1] = (long)task.Item2.Result;
}
} while (cursor != "0");
var sortedKeys = keyMemoryMap.OrderByDescending(kv => kv.Value);
var jsonResult = JToken.FromObject(sortedKeys).ToString();
await File.WriteAllTextAsync(@"C:\temp\allkeys.json", jsonResult);
var aggregatedKeys = new Dictionary<string, long>();
foreach (var (key, value) in keyMemoryMap)
{
var masterKey = key.Split(":").First();
if (aggregatedKeys.TryGetValue(masterKey, out var result))
{
aggregatedKeys[masterKey] = result + value;
}
else
{
aggregatedKeys[masterKey] = value;
}
}
var jsonResultAggregated = JToken.FromObject(aggregatedKeys.OrderByDescending(kv => kv.Value)).ToString();
await File.WriteAllTextAsync(@"C:\temp\allkeysaggregated.json", jsonResultAggregated);
await connection.CloseAsync();
}
}
}
@Salgat
Copy link
Author

Salgat commented Oct 19, 2023

Ran against 1.8 million keys in production (m6g.large instance) without any significant impact on Redis server performance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment