Created
October 19, 2023 21:29
-
-
Save Salgat/af810521ff3dce4ef89ca61a60b2cc4b to your computer and use it in GitHub Desktop.
Query Redis memory usage per key using C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ran against 1.8 million keys in production (m6g.large instance) without any significant impact on Redis server performance.