安装 StackExchange.Redis
在 NuGet 中搜索 StackExchange.Redis 和 Newtonsoft.Json,直接点击按钮安装即可。
StackExchange.Redis 是 C# 操作 Redis 数据库的客户端。
Newtonsoft.Json 用来序列化 Josn 字符串及反序列化拿到对象。
Redis 使用
Redis 使用
using StackExchange.Redis;
using Newtonsoft.Json;
namespace Redis
{
public class RedisService
{
#region Init
private readonly RedisConfigModel redisConfigModel;
public static volatile ConnectionMultiplexer redisConnection;
private readonly object redisConnectionLock = new object();
public RedisService()
{
var redisConfig = AppSettings.app<RedisConfigModel>("RedisConfig");
if (string.IsNullOrEmpty(redisConfig?.Host))
{
throw new Exception("redis config is empty");
}
this.redisConfigModel = redisConfig;
redisConnection = GetRedisConnection();
}
public RedisService(RedisConfigModel configModel)
{
if (string.IsNullOrEmpty(configModel?.Host))
{
throw new Exception("redis config is empty");
}
this.redisConfigModel = configModel;
redisConnection = GetRedisConnection();
}
private ConnectionMultiplexer GetRedisConnection()
{
if (redisConnection != null && redisConnection.IsConnected)
{
return redisConnection;
}
lock (redisConnectionLock)
{
if (redisConnection != null)
{
//释放redis连接
redisConnection.Dispose();
}
redisConnection = GetRedisConnection(this.redisConfigModel);
}
return redisConnection;
}
public ConnectionMultiplexer GetRedisConnection(RedisConfigModel configModel)
{
var url = configModel?.Host;
try
{
if (!string.IsNullOrEmpty(configModel?.Port))
{
url = $"{url}:{configModel.Port}";
}
var config = new ConfigurationOptions
{
AbortOnConnectFail = false,
AllowAdmin = true,
ConnectTimeout = 15000,//改成15s
SyncTimeout = 5000,
EndPoints = { url }
};
if (!string.IsNullOrEmpty(configModel?.Pwd))
{
config.Password = configModel.Pwd;
}
if (configModel.Db.HasValue)
{
config.DefaultDatabase = configModel.Db.Value;
}
return ConnectionMultiplexer.Connect(config);
}
catch (Exception)
{
throw new Exception($"{url}Redis服务未启用,请开启该服务,并且请注意端口号");
}
}
#endregion
#region 基本方法
/// <summary>
/// 写入redis
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool Set(string key, string value)
{
var result = redisConnection.GetDatabase().StringSet(key, value);
return result;
}
/// <summary>
/// 写入redis
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="timeSpan"></param>
/// <returns></returns>
public static bool Set(string key, string value, TimeSpan timeSpan)
{
var result = redisConnection.GetDatabase().StringSet(key, value, timeSpan);
return result;
}
/// <summary>
/// 写入redis
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
public static bool Set<T>(string key, T value)
{
var result = redisConnection.GetDatabase().StringSet(key, SerializationHelper.SerializeJson(value));
return result;
}
/// <summary>
/// 写入redis
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="timeSpan"></param>
/// <returns></returns>
public static bool Set<T>(string key, T value, TimeSpan timeSpan)
{
var result = redisConnection.GetDatabase().StringSet(key, SerializationHelper.SerializeJson(value), timeSpan);
return result;
}
/// <summary>
/// 获取redis
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public static string Get(string key)
{
var result = redisConnection.GetDatabase().StringGet(key).ToString();
return result;
}
/// <summary>
/// 获取redis
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public static T Get<T>(string key)
{
var value = redisConnection.GetDatabase().StringGet(key);
if (value.HasValue)
{
return SerializationHelper.DeserializeJson<T>(value.ToString());
}
return default(T);
}
/// <summary>
/// 模糊查询Key
/// </summary>
/// <param name="searchKey"></param>
/// <returns></returns>
public static List<string> SearchKeys(string searchKey)
{
var redisResult = GetKeys(searchKey);
if (!redisResult.IsNull)
{
string[] keyList = (string[])redisResult;
return keyList.ToList();
}
return new List<string>();
}
#endregion
#region 获取组数据
/// <summary>
/// 组名前缀,防止和普通key重复
/// </summary>
private readonly static string groupPrefix = "g:";
/// <summary>
/// Hash前缀,防止和普通key重复
/// </summary>
private readonly static string hashPrefix = "h:";
/// <summary>
/// 添加组对象,不覆盖
/// </summary>
/// <param name="group">组名</param>
/// <param name="value">值</param>
/// <param name="keyAry">对象名</param>
public static bool AddGroup<T>(string group, T value, params string[] keyAry)
{
var result = true;
var key = $"{groupPrefix}{group}:{string.Join(":", keyAry)}";
if (value is string cacheValue)
{
result = Set(key, cacheValue);
}
else
{
result = Set(key, value);
}
return result;
}
/// <summary>
/// 添加组对象,不覆盖
/// </summary>
/// <param name="group">组名</param>
/// <param name="value">值</param>
/// <param name="timeSpan">过期时间</param>
/// <param name="keyAry">对象名</param>
public static bool AddGroup<T>(string group, T value, TimeSpan timeSpan, params string[] keyAry)
{
var result = true;
var key = $"{groupPrefix}{group}:{string.Join(":", keyAry)}";
if (value is string cacheValue)
{
result = Set(key, cacheValue, timeSpan);
}
else
{
result = Set(key, value, timeSpan);
}
return result;
}
/// <summary>
/// 添加组对象,覆盖
/// </summary>
/// <param name="group">组名</param>
/// <param name="value">值</param>
/// <param name="keyAry">对象名</param>
public static bool SetGroup<T>(string group, T value, params string[] keyAry)
{
var result = AddGroup<T>(group, value, keyAry);
return result;
}
/// <summary>
/// 添加组对象,覆盖
/// </summary>
/// <param name="group">组名</param>
/// <param name="value">值</param>
/// <param name="timeSpan">过期时间</param>
/// <param name="keyAry">对象名</param>
public static bool SetGroup<T>(string group, T value, TimeSpan timeSpan, params string[] keyAry)
{
var result = AddGroup<T>(group, value, timeSpan, keyAry);
return result;
}
/// <summary>
/// 获取一个组的所有对象合并过的集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="group">组名</param>
/// <returns></returns>
public static List<T> GetGroupList<T>(string group)
{
var redisResult = GetKeys($"{groupPrefix}{group}:*");
var result = new List<T>();
if (!redisResult.IsNull)
{
RedisKey[] preSult = (RedisKey[])redisResult;
var tags = redisConnection.GetDatabase().StringGet(preSult);
foreach (var tag in tags)
{
if (tag.HasValue)
{
var groupList = SerializationHelper.DeserializeJson<List<T>>(tag.ToString());
if (groupList?.Count > 0)
{
result.AddRange(groupList);
}
}
}
}
return result;
}
/// <summary>
/// 获取一个组的其中子项合并过的集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="group">组名</param>
/// <param name="keyAry">对象</param>
/// <returns></returns>
public static List<T> GetFreeGroupList<T>(string group, params string[] keyAry)
{
var redisResult = GetKeys($"{groupPrefix}{group}:{string.Join(":", keyAry)}");
var result = new List<T>();
if (!redisResult.IsNull)
{
RedisKey[] preSult = (RedisKey[])redisResult;
var tags = redisConnection.GetDatabase().StringGet(preSult);
foreach (var tag in tags)
{
if (tag.HasValue)
{
var groupList = SerializationHelper.DeserializeJson<List<T>>(tag.ToString());
if (groupList?.Count > 0)
{
result.AddRange(groupList);
}
}
}
}
return result;
}
/// <summary>
/// 获取一个组的其中一个对象值
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="group">组名</param>
/// <param name="key">对象名</param>
/// <returns></returns>
public static T GetGroup<T>(string group, params string[] key)
{
var result = Get<T>($"{groupPrefix}{group}:{string.Join(":", key)}");
return result;
}
/// <summary>
/// 获取一个组的其中一个对象值(List)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="group">组名</param>
/// <param name="keyAry">对象名</param>
/// <returns></returns>
public static List<T> GetGroupList<T>(string group, params string[] keyAry)
{
var result = Get<List<T>>($"{groupPrefix}{group}:{string.Join(":", keyAry)}");
return result ?? new List<T>();
}
/// <summary>
/// 删除一个组所有的对象
/// </summary>
/// <param name="group">组名</param>
/// <returns></returns>
public static bool RemoveGroup(string group)
{
var redisResult = GetKeys($"{groupPrefix}{group}:*");
try
{
if (!redisResult.IsNull)
{
RedisKey[] preSult = (RedisKey[])redisResult;
return redisConnection.GetDatabase().KeyDelete(preSult) > 0;
}
}
catch (Exception ex)
{
JHSC.Log.Log4Helper.Log.WriteLog("redis remove group error", ex);
return false;
}
return false;
}
/// <summary>
/// 删除一个组的其中子项
/// </summary>
/// <param name="group">组名</param>
/// <param name="keyAry">对象名</param>
/// <returns></returns>
public static bool RemoveFreeGroup(string group, params string[] keyAry)
{
var redisResult = GetKeys($"{groupPrefix}{group}:{string.Join(":", keyAry)}");
try
{
if (!redisResult.IsNull)
{
RedisKey[] preSult = (RedisKey[])redisResult;
return redisConnection.GetDatabase().KeyDelete(preSult) > 0;
}
}
catch (Exception ex)
{
JHSC.Log.Log4Helper.Log.WriteLog("redis remove group error", ex);
return false;
}
return false;
}
/// <summary>
/// 删除一个组其中一个对象
/// </summary>
/// <param name="group">组名</param>
/// <param name="keyAry">对象名</param>
/// <returns></returns>
public static bool RemoveGroup(string group, params string[] keyAry)
{
var result = redisConnection.GetDatabase().KeyDelete($"{groupPrefix}{group}:{string.Join(":", keyAry)}");
return result;
}
#endregion
#region 队列
/// <summary>
/// 往前写入队列信息
/// </summary>
/// <param name="qKey"></param>
/// <param name="qValue"></param>
public static void LWriteQueue(string qKey, string qValue)
{
redisConnection.GetDatabase().ListLeftPush(qKey, qValue);
}
/// <summary>
/// 往前写入队列信息
/// </summary>
/// <param name="qKey"></param>
/// <param name="qValue"></param>
public static void LWriteQueue(string qKey, object qValue)
{
var value = SerializationHelper.SerializeJson(qValue);
LWriteQueue(qKey, value);
}
/// <summary>
/// 往前读取队列信息
/// </summary>
/// <param name="qKey"></param>
/// <param name="qValue"></param>
public static string LReadQueue(string qKey)
{
var result = redisConnection.GetDatabase().ListLeftPop(qKey);
if (result.HasValue)
{
return result.ToString();
}
return "";
}
/// <summary>
/// 往前读取队列信息
/// </summary>
/// <param name="qKey"></param>
/// <param name="qValue"></param>
public static T LReadQueue<T>(string qKey)
{
var result = redisConnection.GetDatabase().ListLeftPop(qKey);
if (result.HasValue)
{
return SerializationHelper.DeserializeJson<T>(result.ToString());
}
return default(T);
}
/// <summary>
/// 往后写入队列信息
/// </summary>
/// <param name="qKey"></param>
/// <param name="qValue"></param>
public static void RWriteQueue(string qKey, string qValue)
{
redisConnection.GetDatabase().ListRightPush(qKey, qValue);
}
/// <summary>
/// 往后写入队列信息
/// </summary>
/// <param name="qKey"></param>
/// <param name="qValue"></param>
public static void RWriteQueue(string qKey, object qValue)
{
var value = SerializationHelper.SerializeJson(qValue);
RWriteQueue(qKey, value);
}
/// <summary>
/// 往后读取队列信息
/// </summary>
/// <param name="qKey"></param>
/// <param name="qValue"></param>
public static string RReadQueue(string qKey)
{
var result = redisConnection.GetDatabase().ListRightPop(qKey);
if (result.HasValue)
{
return result.ToString();
}
return "";
}
/// <summary>
/// 往后读取队列信息
/// </summary>
/// <param name="qKey"></param>
/// <param name="qValue"></param>
public static T RReadQueue<T>(string qKey)
{
var result = redisConnection.GetDatabase().ListRightPop(qKey);
if (result.HasValue)
{
return SerializationHelper.DeserializeJson<T>(result.ToString());
}
return default(T);
}
#endregion
#region 公用方法
/// <summary>
/// 模糊搜索Keys
/// </summary>
/// <param name="searchKey"></param>
/// <returns></returns>
private static RedisResult GetKeys(string searchKey)
{
var result = redisConnection.GetDatabase().ScriptEvaluate(LuaScript.Prepare(
" local res = redis.call('KEYS', @keypattern) " +
" return res "), new { @keypattern = searchKey });
return result;
}
#endregion
#region Hash
/// <summary>
/// Set Hash
/// </summary>
/// <param name="hashId"></param>
/// <param name="key"></param>
/// <param name="value"></param>
public static bool SetHash(string hashId, string key, string value)
{
var result = false;
try
{
result = redisConnection.GetDatabase().HashSet(hashId, key, value);
}
catch (Exception ex)
{
}
return result;
}
/// <summary>
/// Set Hash
/// </summary>
/// <param name="hashId"></param>
/// <param name="key"></param>
/// <param name="value"></param>
public static bool SetHash(string hashId, string key, byte[] value)
{
var result = false;
try
{
result = redisConnection.GetDatabase().HashSet(hashId, key, value);
}
catch (Exception ex)
{
}
return result;
}
/// <summary>
/// 批量Set Hash
/// </summary>
/// <param name="hashId"></param>
/// <param name="valueDict"></param>
public static bool SetHashDict(string hashId, Dictionary<string, string> valueDict)
{
var result = false;
try
{
redisConnection.GetDatabase().HashSet(hashId, valueDict.Select(s => new HashEntry(s.Key, s.Value)).ToArray());
result = true;
}
catch (Exception ex)
{
}
return result;
}
/// <summary>
/// 批量Set Hash
/// </summary>
/// <param name="hashId"></param>
/// <param name="valueDict"></param>
public static bool SetHashDict(string hashId, Dictionary<string, byte[]> valueDict)
{
var result = false;
try
{
redisConnection.GetDatabase().HashSet(hashId, valueDict.Select(s => new HashEntry(s.Key, s.Value)).ToArray());
result = true;
}
catch (Exception ex)
{
}
return result;
}
/// <summary>
/// 添加组Hash值,指定字段为Key,覆盖
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="group">组名</param>
/// <param name="list">数据源</param>
/// <param name="fieldName">指定字段为key</param>
/// <param name="keyAry">对象名</param>
/// <returns></returns>
public static bool SetHashAllKeyList<T>(string group, List<T> list, string fieldName, params string[] keyAry)
{
var result = false;
if (list.Count() > 0)
{
try
{
var dict = ChangeListToDict(list, fieldName);
if (dict?.Count() > 0)
{
result = SetHashDict($"{hashPrefix}{group}:{string.Join(":", keyAry)}", dict);
}
}
catch (Exception ex)
{
}
}
return result;
}
/// <summary>
/// 删除 HashId
/// </summary>
/// <param name="hashId"></param>
public static void RemoveHashId(string hashId)
{
redisConnection.GetDatabase().KeyDelete(hashId);
}
/// <summary>
/// 删除 HashKey
/// </summary>
/// <param name="hashId"></param>
/// <param name="keyAry"></param>
public static void RemoveHash(string hashId, params string[] keyAry)
{
redisConnection.GetDatabase().HashDelete(hashId, keyAry.Select(s => (RedisValue)s).ToArray());
}
/// <summary>
/// 获取Hash组值
/// </summary>
/// <param name="group">HashId组名</param>
/// <param name="key">主键</param>
/// <param name="keyAry">对象名</param>
/// <returns></returns>
public static T GetHash<T>(string group, string key, params string[] keyAry)
{
var result = default(T);
var value = redisConnection.GetDatabase().HashGet($"{hashPrefix}{group}:{string.Join(":", keyAry)}", key);
if (value.HasValue)
{
result = JsonConvert.DeserializeObject<T>(value.ToString());
}
return result;
}
/// <summary>
/// 获取Hash组所有值
/// </summary>
/// <param name="group">HashId组名</param>
/// <param name="keyAry">对象名</param>
/// <returns></returns>
public static List<T> GetHashList<T>(string group, params string[] keyAry)
{
var result = new List<T>();
var list = redisConnection.GetDatabase().HashGetAll($"{hashPrefix}{group}:{string.Join(":", keyAry)}").Select(s => s.Value).ToArray();
if (list?.Length > 0)
{
var jsonStr = $"[{string.Join(",", list)}]";
result = JsonConvert.DeserializeObject<List<T>>(jsonStr);
}
return result;
}
/// <summary>
/// 获取 Hash
/// </summary>
/// <param name="hashId"></param>
/// <param name="keyAry"></param>
/// <returns></returns>
public static HashEntry[] GetHashEntry(string hashId, params string[] keyAry)
{
if (keyAry?.Length > 0)
{
var valueAry = redisConnection.GetDatabase().HashGet(hashId, keyAry.Select(s => (RedisValue)s).ToArray());
var result = new List<HashEntry>();
for (var i = 0; i < keyAry.Length; i++)
{
if (valueAry[i].HasValue)
{
result.Add(new HashEntry(keyAry[i], valueAry[i]));
}
}
return result.ToArray();
}
else
{
var result = redisConnection.GetDatabase().HashGetAll(hashId);
return result;
}
}
/// <summary>
/// 获取 Hash
/// </summary>
/// <param name="hashId"></param>
/// <param name="keyAry"></param>
/// <returns></returns>
public static Dictionary<string, string> GetHashDict(string hashId, params string[] keyAry)
{
var hashAry = GetHashEntry(hashId, keyAry);
var result = new Dictionary<string, string>();
foreach (var entry in hashAry)
{
result.Add(entry.Name, entry.Value);
}
return result;
}
/// <summary>
/// 获取 Hash
/// </summary>
/// <param name="hashId"></param>
/// <param name="keyAry"></param>
/// <returns></returns>
public static Dictionary<string, byte[]> GetHashByte(string hashId, params string[] keyAry)
{
var hashAry = GetHashEntry(hashId);
var result = new Dictionary<string, byte[]>();
foreach (var entry in hashAry)
{
result.Add(entry.Name, entry.Value);
}
return result;
}
/// <summary>
/// List转Dict
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="field">指定字段为key</param>
/// <returns></returns>
private static Dictionary<string, string> ChangeListToDict<T>(List<T> list, string field = "")
{
var result = new Dictionary<string, string>();
if (list?.Count() > 0)
{
var fieldAry = new string[0];
if (!string.IsNullOrEmpty(field))
{
fieldAry = field.Split(',');
}
foreach (var model in list)
{
Type type = model.GetType();
PropertyInfo[] properties = type.GetProperties();
if (properties.Length > 0)
{
var key = "";
if (string.IsNullOrEmpty(field))
{
var value = properties[0].GetValue(model); //读取第一个参数作为Key
if (value != null)
{
key = value.ToString();
}
}
else
{
if (fieldAry?.Length > 0)
{
var keyAry = new List<string>();
foreach (var f in fieldAry)
{
var p = type.GetProperty(f);
if (p != null)
{
var value = p.GetValue(model);
if (value != null)
{
keyAry.Add(value.ToString());
}
}
}
if (keyAry?.Count > 0)
{
key = string.Join("_", keyAry);
}
}
else
{
var p = type.GetProperty(field);
if (p != null)
{
var value = p.GetValue(model);
if (value != null)
{
key = value.ToString();
}
}
}
}
if (!string.IsNullOrEmpty(key))
{
if (!result.ContainsKey(key))
{
result.Add(key, JsonConvert.SerializeObject(model));
}
}
}
}
}
return result;
}
/// <summary>
/// List转Key
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="field">指定字段为key</param>
/// <returns></returns>
private static List<string> ChangeListToKey<T>(List<T> list, string field = "")
{
var result = new List<string>();
if (list?.Count() > 0)
{
var fieldAry = new string[0];
if (!string.IsNullOrEmpty(field))
{
fieldAry = field.Split(',');
}
foreach (var model in list)
{
Type type = model.GetType();
PropertyInfo[] properties = type.GetProperties();
if (properties.Length > 0)
{
var key = "";
if (string.IsNullOrEmpty(field))
{
var value = properties[0].GetValue(model); //读取第一个参数作为Key
if (value != null)
{
key = value.ToString();
}
}
else
{
if (fieldAry?.Length > 0)
{
var keyAry = new List<string>();
foreach (var f in fieldAry)
{
var p = type.GetProperty(f);
if (p != null)
{
var value = p.GetValue(model);
if (value != null)
{
keyAry.Add(value.ToString());
}
}
}
if (keyAry?.Count > 0)
{
key = string.Join("_", keyAry);
}
}
else
{
var p = type.GetProperty(field);
if (p != null)
{
var value = p.GetValue(model);
if (value != null)
{
key = value.ToString();
}
}
}
}
if (!string.IsNullOrEmpty(key))
{
result.Add(key);
}
}
}
}
return result;
}
#endregion
}
}