1.在redis中,某个key的hash数据量非常大,一次性获取到数据量可能很大,比如几MB,这样会降低redis的性能,慢查询中肯定会有该条记录,那么怎样解决该问题呢,可以通过分批次查询的方法
例如:
// 创建 Redis 客户端实例
var redis = new CSRedisClient("connstring");
// 设置为全局实例(可选)
RedisHelper.Initialization(redis);
/// <summary>
/// 分批次获取哈希键的所有字段和值
/// </summary>
/// <param name="key"></param>
/// <param name="fieldBatchSize"></param>
/// <returns></returns>
public static async Task<Dictionary<string, string>> GetLargeHashWithPipelineAsync(string key, int fieldBatchSize = 100)
{
// 先获取所有字段名
var allFields = await redis.HKeysAsync(key);
var result = new Dictionary<string, string>();
// 分批获取字段值
for (int i = 0; i < allFields.Length; i += fieldBatchSize)
{
var currentBatch = allFields.Skip(i).Take(fieldBatchSize).ToArray();
// 使用HMGET获取批量字段值
var values = await redis.HMGetAsync(key, currentBatch);
for (int j = 0; j < currentBatch.Length; j++)
{
result[currentBatch[j]] = values[j];
}
}
return result;
}
利用上面这个方法可以获取到该hash的所有数据,且提高了redis性能
使用下面的方法也可以分批获取数据
public async Task<Dictionary<string, string>> GetLargeHashByScanAsync(string key, int batchSize = 50)
{
var result = new Dictionary<string, string>();
long cursor = 0;
do
{
// 使用 HSCAN 命令分批获取
var scanResult = await redis.HScanAsync(key, cursor, count: batchSize);
cursor = scanResult.Cursor;
foreach (var field in scanResult.Items)
{
result[field.field] = field.value;
}
// 可选:添加短暂延迟减少服务器压力
await Task.Delay(10);
} while (cursor != 0); // 当cursor返回0表示扫描完成
return result;
}
2.如何一次性获取多个key的值呢,可以通过下面的方法
public static async Task<Dictionary<string, Dictionary<string, string>>> GetLargeHashesInBatchesAsync(string[] keys,int batchSize = 10)
{
var result = new Dictionary<string, Dictionary<string, string>>();
for (int i = 0; i < keys.Length; i += batchSize)
{
var currentBatch = keys.Skip(i).Take(batchSize).ToArray();
// 使用并行处理每个批次
var batchResults = await ProcessBatchAsync(currentBatch);
foreach (var item in batchResults)
{
result[item.Key] = item.HashData;
}
// 可选:添加延迟以防止服务器过载
await Task.Delay(10);
}
return result;
}
private static async Task<List<(string Key, Dictionary<string, string> HashData)>> ProcessBatchAsync(string[] batchKeys)
{
var tasks = new List<Task<(string, Dictionary<string, string>)>>();
foreach (var key in batchKeys)
{
tasks.Add(Task.Run(async () =>
{
var data = await redis.HGetAllAsync(key);
return (key, data);
}));
}
return (await Task.WhenAll(tasks)).ToList();
}
欢迎大家一起讨论,研究,如果有不对之处,请指出,谢谢!