使用的是.NET CORE的StackExchange.Redis客户端程序操作redis
以下是个人见解
// 获取全部
var list= await _redisClient.HashGetAllAsync<MemberLive>($"liveRpc:memberLiveListTemp");
// 指定ID获取
var list= await _redisClient.HashGetAsync<MemberLive>($"liveRpc:memberLiveListTemp", new StackExchange.Redis.RedisValue[] { 0, 1, 2, 3 });
1、修改value的json字符对象里面的某一个值,需要序列化为对象,修改后在存入hash,并发下会出现数据不一致问题
2、不可以单独对某一条数据设置过期时间
3、占用内存较大
1、使用Batch命令指定key获取数据,数量多不建议
var batch = _redisClient.CreateBatch();
var tasks = new List<Task<StackExchange.Redis.HashEntry[]>>();
var list = new List<MemberLive>();
for (int i = 0; i < 10000; i++)
{
var task = batch.HashGetAllAsync($"liveRpc:memberLiveList:{i}");
tasks.Add(task);
}
batch.Execute();
foreach (var task in tasks)
{
var hashEntries = await task; // 数据多这里容易出现redis超时
list.Add(hashEntries.ToModel<MemberLive>());
}
2、使用Lua命令,比Batch强
// 模糊查询获取Redis的keys:
var redisResult01 = await _redisClient.ScriptEvaluateAsync(
StackExchange.Redis.LuaScript.Prepare($"local ks = redis.call('KEYS', @keypattern) return ks "),
new { @keypattern = "liveRpc:memberLiveList*" });
// 查询全部
var redisResult02 = await _redisClient.ScriptEvaluateAsync(
StackExchange.Redis.LuaScript.Prepare("local ks = redis.call('KEYS', @keypattern) local rst ={ }; for i, v in pairs(ks) do rst[i] = redis.call('hgetall', v) end; return rst "),
new { @keypattern = "liveRpc:memberLiveList*" });
// 指定key
var keys = new List<StackExchange.Redis.RedisKey>();
for (int i = 0; i < 2000; i++)
{
keys.Add($"liveRpc:memberLiveList:{i}");
}
var sum = 0L;
for (int i = 0; i < 1; i++)
{
var ts1 = DateTime.Now.D2L();
// 指定key
var redisResult03 = await _redisClient.ScriptEvaluateAsync("local rst ={ }; for i, v in pairs(KEYS) do rst[i] = redis.call('hgetall', v) end; return rst", keys.ToArray());
// 指定key和field
var redisResult04 = await _redisClient.ScriptEvaluateAsync("local rst ={ }; for i, v in pairs(KEYS) do rst[i] = redis.call('hmget', v, 'Id', 'GiftTotalMoney') end; return rst", keys.ToArray());
var ts2 = DateTime.Now.D2L();
var tt = ts2 - ts1;
sum = Interlocked.Add(ref sum, tt);
}
3、扩展方法
private static readonly ConcurrentDictionary<int, PropertyInfo[]> _propertysDic = new ConcurrentDictionary<int, PropertyInfo[]>();
public static HashEntry[] GetHashEntryArray<T>(this T t) where T : class, new()
{
List<HashEntry> listHashEntry = new List<HashEntry>();
var properties = t.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);
if (!properties.Any()) return listHashEntry.ToArray();
foreach (PropertyInfo prop in properties)
{
string name = prop.Name; // 获得属性的名字,后面就可以根据名字判断来进行些自己想要的操作
var value = prop.GetValue(t, null); // 用pi.GetValue获得值
listHashEntry.Add(new HashEntry(name, value.ToString()));
}
return listHashEntry.ToArray();
}
public static T ToModel<T>(this HashEntry[] entrys) where T : class, new()
{
T obj = Activator.CreateInstance<T>();
if (entrys == null) return obj;
var properties = _propertysDic.GetOrAdd(obj.GetHashCode(), (value) =>
{
var properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);
return properties;
});
// var properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);
foreach (HashEntry item in entrys)
{
var prop = properties.FirstOrDefault(t => t.Name == item.Name);
if (prop == null) continue;
var value = System.ComponentModel.TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromString(item.Value);
prop.SetValue(obj, value, null);
}
return obj;
}
public static List<T> HashToModel<T>(this RedisResult redisResult) where T : class, new()
{
var r = new List<T>();
var redisResultArray = (RedisResult[])redisResult;
foreach (var item in redisResultArray)
{
string[] preval = (string[])item;
if (preval.Length == 0) continue;
T obj = Activator.CreateInstance<T>();
var properties = _propertysDic.GetOrAdd(obj.GetHashCode(), (value) =>
{
var properties = obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);
return properties;
});
foreach (PropertyInfo prop in properties)
{
int index = Array.IndexOf(preval, prop.Name);
if (index < 0) continue;
var value = System.ComponentModel.TypeDescriptor.GetConverter(prop.PropertyType).ConvertFromString(preval[index + 1]);
prop.SetValue(obj, value, null);
}
r.Add(obj);
}
return r;
}
1、数据修改不频繁、内容比较固定建议用第一种
2、数据修改频繁、需要设置过期时间建议使用第二种