使用 StackExchange.Redis 封装属于自己的 RedisHelper

目录

  • 核心类 ConnectionMultiplexer
  • 字符串(String)
  • 哈希(Hash)
  • 列表(List)
  • 有序集合(sorted set)
  • Key 操作
  • 发布订阅
  • 其他

简介

  目前 .NET 使用访问 Redis 的的类库主流应该是 StackExchange.Redis,自己参考网上的文章(也许是吃饱了撑着),也尝试做出简单的封装。

    /// <summary>
/// Redis 助手
/// </summary>
public class RedisHelper
{
/// <summary>
/// 连接字符串
/// </summary>
private static readonly string ConnectionString; /// <summary>
/// redis 连接对象
/// </summary>
private static IConnectionMultiplexer _connMultiplexer; /// <summary>
/// 默认的 Key 值(用来当作 RedisKey 的前缀)
/// </summary>
private static readonly string DefaultKey; /// <summary>
/// 锁
/// </summary>
private static readonly object Locker = new object(); /// <summary>
/// 数据库
/// </summary>
private readonly IDatabase _db; /// <summary>
/// 获取 Redis 连接对象
/// </summary>
/// <returns></returns>
public IConnectionMultiplexer GetConnectionRedisMultiplexer()
{
if ((_connMultiplexer == null) || !_connMultiplexer.IsConnected)
{
lock (Locker)
{
if ((_connMultiplexer == null) || !_connMultiplexer.IsConnected)
_connMultiplexer = ConnectionMultiplexer.Connect(ConnectionString);
}
} return _connMultiplexer;
} #region 其它 public ITransaction GetTransaction()
{
return _db.CreateTransaction();
} #endregion 其它 #region 构造函数 static RedisHelper()
{
ConnectionString = ConfigurationManager.ConnectionStrings["RedisConnectionString"].ConnectionString;
_connMultiplexer = ConnectionMultiplexer.Connect(ConnectionString);
DefaultKey = ConfigurationManager.AppSettings["Redis.DefaultKey"];
AddRegisterEvent();
} public RedisHelper(int db = -)
{
_db = _connMultiplexer.GetDatabase(db);
} #endregion 构造函数 #region String 操作 /// <summary>
/// 设置 key 并保存字符串(如果 key 已存在,则覆盖值)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public bool StringSet(string redisKey, string redisValue, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
return _db.StringSet(redisKey, redisValue, expiry);
} /// <summary>
/// 保存多个 Key-value
/// </summary>
/// <param name="keyValuePairs"></param>
/// <returns></returns>
public bool StringSet(IEnumerable<KeyValuePair<RedisKey, RedisValue>> keyValuePairs)
{
keyValuePairs =
keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(AddKeyPrefix(x.Key), x.Value));
return _db.StringSet(keyValuePairs.ToArray());
} /// <summary>
/// 获取字符串
/// </summary>
/// <param name="redisKey"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public string StringGet(string redisKey, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
return _db.StringGet(redisKey);
} /// <summary>
/// 存储一个对象(该对象会被序列化保存)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public bool StringSet<T>(string redisKey, T redisValue, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(redisValue);
return _db.StringSet(redisKey, json, expiry);
} /// <summary>
/// 获取一个对象(会进行反序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public T StringGet<T>(string redisKey, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(_db.StringGet(redisKey));
} #region async /// <summary>
/// 保存一个字符串值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<bool> StringSetAsync(string redisKey, string redisValue, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.StringSetAsync(redisKey, redisValue, expiry);
} /// <summary>
/// 保存一组字符串值
/// </summary>
/// <param name="keyValuePairs"></param>
/// <returns></returns>
public async Task<bool> StringSetAsync(IEnumerable<KeyValuePair<RedisKey, RedisValue>> keyValuePairs)
{
keyValuePairs =
keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(AddKeyPrefix(x.Key), x.Value));
return await _db.StringSetAsync(keyValuePairs.ToArray());
} /// <summary>
/// 获取单个值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<string> StringGetAsync(string redisKey, string redisValue, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.StringGetAsync(redisKey);
} /// <summary>
/// 存储一个对象(该对象会被序列化保存)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<bool> StringSetAsync<T>(string redisKey, T redisValue, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(redisValue);
return await _db.StringSetAsync(redisKey, json, expiry);
} /// <summary>
/// 获取一个对象(会进行反序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<T> StringGetAsync<T>(string redisKey, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(await _db.StringGetAsync(redisKey));
} #endregion async #endregion String 操作 #region Hash 操作 /// <summary>
/// 判断该字段是否存在 hash 中
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public bool HashExists(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashExists(redisKey, hashField);
} /// <summary>
/// 从 hash 中移除指定字段
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public bool HashDelete(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashDelete(redisKey, hashField);
} /// <summary>
/// 从 hash 中移除指定字段
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public long HashDelete(string redisKey, IEnumerable<RedisValue> hashField)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashDelete(redisKey, hashField.ToArray());
} /// <summary>
/// 在 hash 设定值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HashSet(string redisKey, string hashField, string value)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashSet(redisKey, hashField, value);
} /// <summary>
/// 在 hash 中设定值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashFields"></param>
public void HashSet(string redisKey, IEnumerable<HashEntry> hashFields)
{
redisKey = AddKeyPrefix(redisKey);
_db.HashSet(redisKey, hashFields.ToArray());
} /// <summary>
/// 在 hash 中获取值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public RedisValue HashGet(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashGet(redisKey, hashField);
} /// <summary>
/// 在 hash 中获取值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public RedisValue[] HashGet(string redisKey, RedisValue[] hashField, string value)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashGet(redisKey, hashField);
} /// <summary>
/// 从 hash 返回所有的字段值
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public IEnumerable<RedisValue> HashKeys(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashKeys(redisKey);
} /// <summary>
/// 返回 hash 中的所有值
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public RedisValue[] HashValues(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashValues(redisKey);
} /// <summary>
/// 在 hash 设定值(序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HashSet<T>(string redisKey, string hashField, T value)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(value);
return _db.HashSet(redisKey, hashField, json);
} /// <summary>
/// 在 hash 中获取值(反序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public T HashGet<T>(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(_db.HashGet(redisKey, hashField));
} #region async /// <summary>
/// 判断该字段是否存在 hash 中
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<bool> HashExistsAsync(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashExistsAsync(redisKey, hashField);
} /// <summary>
/// 从 hash 中移除指定字段
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<bool> HashDeleteAsync(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashDeleteAsync(redisKey, hashField);
} /// <summary>
/// 从 hash 中移除指定字段
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<long> HashDeleteAsync(string redisKey, IEnumerable<RedisValue> hashField)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashDeleteAsync(redisKey, hashField.ToArray());
} /// <summary>
/// 在 hash 设定值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<bool> HashSetAsync(string redisKey, string hashField, string value)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashSetAsync(redisKey, hashField, value);
} /// <summary>
/// 在 hash 中设定值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashFields"></param>
public async Task HashSetAsync(string redisKey, IEnumerable<HashEntry> hashFields)
{
redisKey = AddKeyPrefix(redisKey);
await _db.HashSetAsync(redisKey, hashFields.ToArray());
} /// <summary>
/// 在 hash 中获取值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<RedisValue> HashGetAsync(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashGetAsync(redisKey, hashField);
} /// <summary>
/// 在 hash 中获取值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<IEnumerable<RedisValue>> HashGetAsync(string redisKey, RedisValue[] hashField, string value)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashGetAsync(redisKey, hashField);
} /// <summary>
/// 从 hash 返回所有的字段值
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<IEnumerable<RedisValue>> HashKeysAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashKeysAsync(redisKey);
} /// <summary>
/// 返回 hash 中的所有值
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<IEnumerable<RedisValue>> HashValuesAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashValuesAsync(redisKey);
} /// <summary>
/// 在 hash 设定值(序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<bool> HashSetAsync<T>(string redisKey, string hashField, T value)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(value);
return await _db.HashSetAsync(redisKey, hashField, json);
} /// <summary>
/// 在 hash 中获取值(反序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<T> HashGetAsync<T>(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(await _db.HashGetAsync(redisKey, hashField));
} #endregion async #endregion Hash 操作 #region List 操作 /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public string ListLeftPop(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListLeftPop(redisKey);
} /// <summary>
/// 移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public string ListRightPop(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListRightPop(redisKey);
} /// <summary>
/// 移除列表指定键上与该值相同的元素
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListRemove(string redisKey, string redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListRemove(redisKey, redisValue);
} /// <summary>
/// 在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListRightPush(string redisKey, string redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListRightPush(redisKey, redisValue);
} /// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListLeftPush(string redisKey, string redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListLeftPush(redisKey, redisValue);
} /// <summary>
/// 返回列表上该键的长度,如果不存在,返回 0
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public long ListLength(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListLength(redisKey);
} /// <summary>
/// 返回在该列表上键所对应的元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public IEnumerable<RedisValue> ListRange(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListRange(redisKey);
} /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public T ListLeftPop<T>(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(_db.ListLeftPop(redisKey));
} /// <summary>
/// 移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public T ListRightPop<T>(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(_db.ListRightPop(redisKey));
} /// <summary>
/// 在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListRightPush<T>(string redisKey, T redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListRightPush(redisKey, Serialize(redisValue));
} /// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListLeftPush<T>(string redisKey, T redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListLeftPush(redisKey, Serialize(redisValue));
} #region List-async /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<string> ListLeftPopAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListLeftPopAsync(redisKey);
} /// <summary>
/// 移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<string> ListRightPopAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListRightPopAsync(redisKey);
} /// <summary>
/// 移除列表指定键上与该值相同的元素
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public async Task<long> ListRemoveAsync(string redisKey, string redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListRemoveAsync(redisKey, redisValue);
} /// <summary>
/// 在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public async Task<long> ListRightPushAsync(string redisKey, string redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListRightPushAsync(redisKey, redisValue);
} /// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public async Task<long> ListLeftPushAsync(string redisKey, string redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListLeftPushAsync(redisKey, redisValue);
} /// <summary>
/// 返回列表上该键的长度,如果不存在,返回 0
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<long> ListLengthAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListLengthAsync(redisKey);
} /// <summary>
/// 返回在该列表上键所对应的元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<IEnumerable<RedisValue>> ListRangeAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListRangeAsync(redisKey);
} /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<T> ListLeftPopAsync<T>(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(await _db.ListLeftPopAsync(redisKey));
} /// <summary>
/// 移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<T> ListRightPopAsync<T>(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(await _db.ListRightPopAsync(redisKey));
} /// <summary>
/// 在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public async Task<long> ListRightPushAsync<T>(string redisKey, T redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListRightPushAsync(redisKey, Serialize(redisValue));
} /// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public async Task<long> ListLeftPushAsync<T>(string redisKey, T redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListLeftPushAsync(redisKey, Serialize(redisValue));
} #endregion List-async #endregion List 操作 #region SortedSet 操作 /// <summary>
/// SortedSet 新增
/// </summary>
/// <param name="redisKey"></param>
/// <param name="member"></param>
/// <param name="score"></param>
/// <returns></returns>
public bool SortedSetAdd(string redisKey, string member, double score)
{
redisKey = AddKeyPrefix(redisKey);
return _db.SortedSetAdd(redisKey, member, score);
} /// <summary>
/// 在有序集合中返回指定范围的元素,默认情况下从低到高。
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public IEnumerable<RedisValue> SortedSetRangeByRank(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.SortedSetRangeByRank(redisKey);
} /// <summary>
/// 返回有序集合的元素个数
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public long SortedSetLength(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.SortedSetLength(redisKey);
} /// <summary>
/// 返回有序集合的元素个数
/// </summary>
/// <param name="redisKey"></param>
/// <param name="memebr"></param>
/// <returns></returns>
public bool SortedSetLength(string redisKey, string memebr)
{
redisKey = AddKeyPrefix(redisKey);
return _db.SortedSetRemove(redisKey, memebr);
} /// <summary>
/// SortedSet 新增
/// </summary>
/// <param name="redisKey"></param>
/// <param name="member"></param>
/// <param name="score"></param>
/// <returns></returns>
public bool SortedSetAdd<T>(string redisKey, T member, double score)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(member); return _db.SortedSetAdd(redisKey, json, score);
} #region SortedSet-Async /// <summary>
/// SortedSet 新增
/// </summary>
/// <param name="redisKey"></param>
/// <param name="member"></param>
/// <param name="score"></param>
/// <returns></returns>
public async Task<bool> SortedSetAddAsync(string redisKey, string member, double score)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.SortedSetAddAsync(redisKey, member, score);
} /// <summary>
/// 在有序集合中返回指定范围的元素,默认情况下从低到高。
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<IEnumerable<RedisValue>> SortedSetRangeByRankAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.SortedSetRangeByRankAsync(redisKey);
} /// <summary>
/// 返回有序集合的元素个数
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<long> SortedSetLengthAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.SortedSetLengthAsync(redisKey);
} /// <summary>
/// 返回有序集合的元素个数
/// </summary>
/// <param name="redisKey"></param>
/// <param name="memebr"></param>
/// <returns></returns>
public async Task<bool> SortedSetRemoveAsync(string redisKey, string memebr)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.SortedSetRemoveAsync(redisKey, memebr);
} /// <summary>
/// SortedSet 新增
/// </summary>
/// <param name="redisKey"></param>
/// <param name="member"></param>
/// <param name="score"></param>
/// <returns></returns>
public async Task<bool> SortedSetAddAsync<T>(string redisKey, T member, double score)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(member); return await _db.SortedSetAddAsync(redisKey, json, score);
} #endregion SortedSet-Async #endregion SortedSet 操作 #region key 操作 /// <summary>
/// 移除指定 Key
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public bool KeyDelete(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.KeyDelete(redisKey);
} /// <summary>
/// 移除指定 Key
/// </summary>
/// <param name="redisKeys"></param>
/// <returns></returns>
public long KeyDelete(IEnumerable<string> redisKeys)
{
var keys = redisKeys.Select(x => (RedisKey)AddKeyPrefix(x));
return _db.KeyDelete(keys.ToArray());
} /// <summary>
/// 校验 Key 是否存在
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public bool KeyExists(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.KeyExists(redisKey);
} /// <summary>
/// 重命名 Key
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisNewKey"></param>
/// <returns></returns>
public bool KeyRename(string redisKey, string redisNewKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.KeyRename(redisKey, redisNewKey);
} /// <summary>
/// 设置 Key 的时间
/// </summary>
/// <param name="redisKey"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public bool KeyExpire(string redisKey, TimeSpan? expiry)
{
redisKey = AddKeyPrefix(redisKey);
return _db.KeyExpire(redisKey, expiry);
} #region key-async /// <summary>
/// 移除指定 Key
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<bool> KeyDeleteAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.KeyDeleteAsync(redisKey);
} /// <summary>
/// 移除指定 Key
/// </summary>
/// <param name="redisKeys"></param>
/// <returns></returns>
public async Task<long> KeyDeleteAsync(IEnumerable<string> redisKeys)
{
var keys = redisKeys.Select(x => (RedisKey)AddKeyPrefix(x));
return await _db.KeyDeleteAsync(keys.ToArray());
} /// <summary>
/// 校验 Key 是否存在
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<bool> KeyExistsAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.KeyExistsAsync(redisKey);
} /// <summary>
/// 重命名 Key
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisNewKey"></param>
/// <returns></returns>
public async Task<bool> KeyRenameAsync(string redisKey, string redisNewKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.KeyRenameAsync(redisKey, redisNewKey);
} /// <summary>
/// 设置 Key 的时间
/// </summary>
/// <param name="redisKey"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<bool> KeyExpireAsync(string redisKey, TimeSpan? expiry)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.KeyExpireAsync(redisKey, expiry);
} #endregion key-async #endregion key 操作 #region 发布订阅 /// <summary>
/// 订阅
/// </summary>
/// <param name="channel"></param>
/// <param name="handle"></param>
public void Subscribe(RedisChannel channel, Action<RedisChannel, RedisValue> handle)
{
var sub = _connMultiplexer.GetSubscriber();
sub.Subscribe(channel, handle);
} /// <summary>
/// 发布
/// </summary>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public long Publish(RedisChannel channel, RedisValue message)
{
var sub = _connMultiplexer.GetSubscriber();
return sub.Publish(channel, message);
} /// <summary>
/// 发布(使用序列化)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public long Publish<T>(RedisChannel channel, T message)
{
var sub = _connMultiplexer.GetSubscriber();
return sub.Publish(channel, Serialize(message));
} #region 发布订阅-async /// <summary>
/// 订阅
/// </summary>
/// <param name="channel"></param>
/// <param name="handle"></param>
public async Task SubscribeAsync(RedisChannel channel, Action<RedisChannel, RedisValue> handle)
{
var sub = _connMultiplexer.GetSubscriber();
await sub.SubscribeAsync(channel, handle);
} /// <summary>
/// 发布
/// </summary>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public async Task<long> PublishAsync(RedisChannel channel, RedisValue message)
{
var sub = _connMultiplexer.GetSubscriber();
return await sub.PublishAsync(channel, message);
} /// <summary>
/// 发布(使用序列化)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public async Task<long> PublishAsync<T>(RedisChannel channel, T message)
{
var sub = _connMultiplexer.GetSubscriber();
return await sub.PublishAsync(channel, Serialize(message));
} #endregion 发布订阅-async #endregion 发布订阅 #region private method /// <summary>
/// 添加 Key 的前缀
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
private static string AddKeyPrefix(string key)
{
return $"{DefaultKey}:{key}";
} #region 注册事件 /// <summary>
/// 添加注册事件
/// </summary>
private static void AddRegisterEvent()
{
_connMultiplexer.ConnectionRestored += ConnMultiplexer_ConnectionRestored;
_connMultiplexer.ConnectionFailed += ConnMultiplexer_ConnectionFailed;
_connMultiplexer.ErrorMessage += ConnMultiplexer_ErrorMessage;
_connMultiplexer.ConfigurationChanged += ConnMultiplexer_ConfigurationChanged;
_connMultiplexer.HashSlotMoved += ConnMultiplexer_HashSlotMoved;
_connMultiplexer.InternalError += ConnMultiplexer_InternalError;
_connMultiplexer.ConfigurationChangedBroadcast += ConnMultiplexer_ConfigurationChangedBroadcast;
} /// <summary>
/// 重新配置广播时(通常意味着主从同步更改)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ConfigurationChangedBroadcast(object sender, EndPointEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ConfigurationChangedBroadcast)}: {e.EndPoint}");
} /// <summary>
/// 发生内部错误时(主要用于调试)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_InternalError(object sender, InternalErrorEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_InternalError)}: {e.Exception}");
} /// <summary>
/// 更改集群时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_HashSlotMoved(object sender, HashSlotMovedEventArgs e)
{
Console.WriteLine(
$"{nameof(ConnMultiplexer_HashSlotMoved)}: {nameof(e.OldEndPoint)}-{e.OldEndPoint} To {nameof(e.NewEndPoint)}-{e.NewEndPoint}, ");
} /// <summary>
/// 配置更改时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ConfigurationChanged(object sender, EndPointEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ConfigurationChanged)}: {e.EndPoint}");
} /// <summary>
/// 发生错误时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ErrorMessage(object sender, RedisErrorEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ErrorMessage)}: {e.Message}");
} /// <summary>
/// 物理连接失败时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ConnectionFailed(object sender, ConnectionFailedEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ConnectionFailed)}: {e.Exception}");
} /// <summary>
/// 建立物理连接时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ConnectionRestored(object sender, ConnectionFailedEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ConnectionRestored)}: {e.Exception}");
} #endregion 注册事件 /// <summary>
/// 序列化
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
private static byte[] Serialize(object obj)
{
if (obj == null)
return null; var binaryFormatter = new BinaryFormatter();
using (var memoryStream = new MemoryStream())
{
binaryFormatter.Serialize(memoryStream, obj);
var data = memoryStream.ToArray();
return data;
}
} /// <summary>
/// 反序列化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data"></param>
/// <returns></returns>
private static T Deserialize<T>(byte[] data)
{
if (data == null)
return default(T); var binaryFormatter = new BinaryFormatter();
using (var memoryStream = new MemoryStream(data))
{
var result = (T)binaryFormatter.Deserialize(memoryStream);
return result;
}
} #endregion private method
}

RedisHelepr.cs

核心类 ConnectionMultiplexer

  在 StackExchange.Redis 中最核心(中枢)的是 ConnectionMultiplexer 类,在所有调用之间它的实例对象应该被设计为在整个应用程序域中为共享和重用的,并不应该为每一个操作都创建一个 ConnectionMultiplexer 对象实例,也就是说我们可以使用常见的单例模式进行创建。

  虽然 ConnectionMultiplexer 实现了 IDisposable 接口,但这并不意味着需要使用 using 进行释放,因为创建一个 ConnectionMultiplexer 对象是十分昂贵的 , 所以最好的是我们一直重用一个 ConnectionMultiplexer 对象。

        /// <summary>
/// 连接字符串
/// </summary>
private static readonly string ConnectionString; /// <summary>
/// redis 连接对象
/// </summary>
private static IConnectionMultiplexer _connMultiplexer; /// <summary>
/// 默认的 Key 值(用来当作 RedisKey 的前缀)
/// </summary>
private static readonly string DefaultKey; /// <summary>
/// 锁
/// </summary>
private static readonly object Locker = new object(); /// <summary>
/// 数据库
/// </summary>
private readonly IDatabase _db; /// <summary>
/// 获取 Redis 连接对象
/// </summary>
/// <returns></returns>
public IConnectionMultiplexer GetConnectionRedisMultiplexer()
{
if ((_connMultiplexer == null) || !_connMultiplexer.IsConnected)
{
lock (Locker)
{
if ((_connMultiplexer == null) || !_connMultiplexer.IsConnected)
_connMultiplexer = ConnectionMultiplexer.Connect(ConnectionString);
}
} return _connMultiplexer;
}

  我选择让这些静态变量的字段在静态构造函数中进行统一的初始化,如连接字符串,ConnectionMultiplexer 对象和注册事件等。

        #region 构造函数

        static RedisHelper()
{
ConnectionString = ConfigurationManager.ConnectionStrings["RedisConnectionString"].ConnectionString;
_connMultiplexer = ConnectionMultiplexer.Connect(ConnectionString);
DefaultKey = ConfigurationManager.AppSettings["Redis.DefaultKey"];
AddRegisterEvent();
} public RedisHelper(int db = -)
{
_db = _connMultiplexer.GetDatabase(db);
} #endregion 构造函数
        #region 注册事件

        /// <summary>
/// 添加注册事件
/// </summary>
private static void AddRegisterEvent()
{
ConnMultiplexer.ConnectionRestored += ConnMultiplexer_ConnectionRestored;
ConnMultiplexer.ConnectionFailed += ConnMultiplexer_ConnectionFailed;
ConnMultiplexer.ErrorMessage += ConnMultiplexer_ErrorMessage;
ConnMultiplexer.ConfigurationChanged += ConnMultiplexer_ConfigurationChanged;
ConnMultiplexer.HashSlotMoved += ConnMultiplexer_HashSlotMoved;
ConnMultiplexer.InternalError += ConnMultiplexer_InternalError;
ConnMultiplexer.ConfigurationChangedBroadcast += ConnMultiplexer_ConfigurationChangedBroadcast;
} /// <summary>
/// 重新配置广播时(通常意味着主从同步更改)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ConfigurationChangedBroadcast(object sender, EndPointEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ConfigurationChangedBroadcast)}: {e.EndPoint}");
} /// <summary>
/// 发生内部错误时(主要用于调试)
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_InternalError(object sender, InternalErrorEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_InternalError)}: {e.Exception}");
} /// <summary>
/// 更改集群时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_HashSlotMoved(object sender, HashSlotMovedEventArgs e)
{
Console.WriteLine(
$"{nameof(ConnMultiplexer_HashSlotMoved)}: {nameof(e.OldEndPoint)}-{e.OldEndPoint} To {nameof(e.NewEndPoint)}-{e.NewEndPoint}, ");
} /// <summary>
/// 配置更改时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ConfigurationChanged(object sender, EndPointEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ConfigurationChanged)}: {e.EndPoint}");
} /// <summary>
/// 发生错误时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ErrorMessage(object sender, RedisErrorEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ErrorMessage)}: {e.Message}");
} /// <summary>
/// 物理连接失败时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ConnectionFailed(object sender, ConnectionFailedEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ConnectionFailed)}: {e.Exception}");
} /// <summary>
/// 建立物理连接时
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void ConnMultiplexer_ConnectionRestored(object sender, ConnectionFailedEventArgs e)
{
Console.WriteLine($"{nameof(ConnMultiplexer_ConnectionRestored)}: {e.Exception}");
} #endregion 注册事件

注册事件的代码

  这里的 Redis.DefaultKey 和 RedisConnectionString 对应配置文件中 App.Config。

  DefaultKey(默认 Key)的作用是给 redisKey 值添加一个前缀,我这里使用了命名空间作为了前缀,在 Redis 可视化工具中可以更直观的进行显示(以“:”进行字符串的拼接)。

字符串(String)

  存储字符串值。所有的同步方法都带有对应的异步方法,所以也进行了简单的封装。比较常用的应该是字符串操作,直接将 value 序列化存放到 redis 中。

        #region String 操作

        /// <summary>
/// 设置 key 并保存字符串(如果 key 已存在,则覆盖值)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public bool StringSet(string redisKey, string redisValue, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
return _db.StringSet(redisKey, redisValue, expiry);
} /// <summary>
/// 保存多个 Key-value
/// </summary>
/// <param name="keyValuePairs"></param>
/// <returns></returns>
public bool StringSet(IEnumerable<KeyValuePair<RedisKey, RedisValue>> keyValuePairs)
{
keyValuePairs =
keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(AddKeyPrefix(x.Key), x.Value));
return _db.StringSet(keyValuePairs.ToArray());
} /// <summary>
/// 获取字符串
/// </summary>
/// <param name="redisKey"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public string StringGet(string redisKey, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
return _db.StringGet(redisKey);
} /// <summary>
/// 存储一个对象(该对象会被序列化保存)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public bool StringSet<T>(string redisKey, T redisValue, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(redisValue);
return _db.StringSet(redisKey, json, expiry);
} /// <summary>
/// 获取一个对象(会进行反序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public T StringGet<T>(string redisKey, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(_db.StringGet(redisKey));
} #region async /// <summary>
/// 保存一个字符串值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<bool> StringSetAsync(string redisKey, string redisValue, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.StringSetAsync(redisKey, redisValue, expiry);
} /// <summary>
/// 保存一组字符串值
/// </summary>
/// <param name="keyValuePairs"></param>
/// <returns></returns>
public async Task<bool> StringSetAsync(IEnumerable<KeyValuePair<RedisKey, RedisValue>> keyValuePairs)
{
keyValuePairs =
keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(AddKeyPrefix(x.Key), x.Value));
return await _db.StringSetAsync(keyValuePairs.ToArray());
} /// <summary>
/// 获取单个值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<string> StringGetAsync(string redisKey, string redisValue, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.StringGetAsync(redisKey);
} /// <summary>
/// 存储一个对象(该对象会被序列化保存)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<bool> StringSetAsync<T>(string redisKey, T redisValue, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(redisValue);
return await _db.StringSetAsync(redisKey, json, expiry);
} /// <summary>
/// 获取一个对象(会进行反序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<T> StringGetAsync<T>(string redisKey, TimeSpan? expiry = null)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(await _db.StringGetAsync(redisKey));
} #endregion async #endregion String 操作

String 操作

哈希(Hash)

  哈希是一个 string 类型的 field 和 value 的映射表,哈希特别适合用于存储对象。

        #region Hash 操作

        /// <summary>
/// 判断该字段是否存在 hash 中
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public bool HashExists(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashExists(redisKey, hashField);
} /// <summary>
/// 从 hash 中移除指定字段
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public bool HashDelete(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashDelete(redisKey, hashField);
} /// <summary>
/// 从 hash 中移除指定字段
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public long HashDelete(string redisKey, IEnumerable<RedisValue> hashField)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashDelete(redisKey, hashField.ToArray());
} /// <summary>
/// 在 hash 设定值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HashSet(string redisKey, string hashField, string value)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashSet(redisKey, hashField, value);
} /// <summary>
/// 在 hash 中设定值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashFields"></param>
public void HashSet(string redisKey, IEnumerable<HashEntry> hashFields)
{
redisKey = AddKeyPrefix(redisKey);
_db.HashSet(redisKey, hashFields.ToArray());
} /// <summary>
/// 在 hash 中获取值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public RedisValue HashGet(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashGet(redisKey, hashField);
} /// <summary>
/// 在 hash 中获取值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public RedisValue[] HashGet(string redisKey, RedisValue[] hashField, string value)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashGet(redisKey, hashField);
} /// <summary>
/// 从 hash 返回所有的字段值
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public IEnumerable<RedisValue> HashKeys(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashKeys(redisKey);
} /// <summary>
/// 返回 hash 中的所有值
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public RedisValue[] HashValues(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.HashValues(redisKey);
} /// <summary>
/// 在 hash 设定值(序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public bool HashSet<T>(string redisKey, string hashField, T value)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(value);
return _db.HashSet(redisKey, hashField, json);
} /// <summary>
/// 在 hash 中获取值(反序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public T HashGet<T>(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(_db.HashGet(redisKey, hashField));
} #region async /// <summary>
/// 判断该字段是否存在 hash 中
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<bool> HashExistsAsync(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashExistsAsync(redisKey, hashField);
} /// <summary>
/// 从 hash 中移除指定字段
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<bool> HashDeleteAsync(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashDeleteAsync(redisKey, hashField);
} /// <summary>
/// 从 hash 中移除指定字段
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<long> HashDeleteAsync(string redisKey, IEnumerable<RedisValue> hashField)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashDeleteAsync(redisKey, hashField.ToArray());
} /// <summary>
/// 在 hash 设定值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<bool> HashSetAsync(string redisKey, string hashField, string value)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashSetAsync(redisKey, hashField, value);
} /// <summary>
/// 在 hash 中设定值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashFields"></param>
public async Task HashSetAsync(string redisKey, IEnumerable<HashEntry> hashFields)
{
redisKey = AddKeyPrefix(redisKey);
await _db.HashSetAsync(redisKey, hashFields.ToArray());
} /// <summary>
/// 在 hash 中获取值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<RedisValue> HashGetAsync(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashGetAsync(redisKey, hashField);
} /// <summary>
/// 在 hash 中获取值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<IEnumerable<RedisValue>> HashGetAsync(string redisKey, RedisValue[] hashField, string value)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashGetAsync(redisKey, hashField);
} /// <summary>
/// 从 hash 返回所有的字段值
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<IEnumerable<RedisValue>> HashKeysAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashKeysAsync(redisKey);
} /// <summary>
/// 返回 hash 中的所有值
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<IEnumerable<RedisValue>> HashValuesAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.HashValuesAsync(redisKey);
} /// <summary>
/// 在 hash 设定值(序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <param name="value"></param>
/// <returns></returns>
public async Task<bool> HashSetAsync<T>(string redisKey, string hashField, T value)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(value);
return await _db.HashSetAsync(redisKey, hashField, json);
} /// <summary>
/// 在 hash 中获取值(反序列化)
/// </summary>
/// <param name="redisKey"></param>
/// <param name="hashField"></param>
/// <returns></returns>
public async Task<T> HashGetAsync<T>(string redisKey, string hashField)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(await _db.HashGetAsync(redisKey, hashField));
} #endregion async #endregion Hash 操作

Hash 操作

列表(List)

  列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素导列表的头部(左边)或者尾部(右边)。

        #region List 操作

        /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public string ListLeftPop(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListLeftPop(redisKey);
} /// <summary>
/// 移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public string ListRightPop(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListRightPop(redisKey);
} /// <summary>
/// 移除列表指定键上与该值相同的元素
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListRemove(string redisKey, string redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListRemove(redisKey, redisValue);
} /// <summary>
/// 在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListRightPush(string redisKey, string redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListRightPush(redisKey, redisValue);
} /// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListLeftPush(string redisKey, string redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListLeftPush(redisKey, redisValue);
} /// <summary>
/// 返回列表上该键的长度,如果不存在,返回 0
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public long ListLength(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListLength(redisKey);
} /// <summary>
/// 返回在该列表上键所对应的元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public IEnumerable<RedisValue> ListRange(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListRange(redisKey);
} /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public T ListLeftPop<T>(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(_db.ListLeftPop(redisKey));
} /// <summary>
/// 移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public T ListRightPop<T>(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(_db.ListRightPop(redisKey));
} /// <summary>
/// 在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListRightPush<T>(string redisKey, T redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListRightPush(redisKey, Serialize(redisValue));
} /// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public long ListLeftPush<T>(string redisKey, T redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return _db.ListLeftPush(redisKey, Serialize(redisValue));
} #region List-async /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<string> ListLeftPopAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListLeftPopAsync(redisKey);
} /// <summary>
/// 移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<string> ListRightPopAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListRightPopAsync(redisKey);
} /// <summary>
/// 移除列表指定键上与该值相同的元素
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public async Task<long> ListRemoveAsync(string redisKey, string redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListRemoveAsync(redisKey, redisValue);
} /// <summary>
/// 在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public async Task<long> ListRightPushAsync(string redisKey, string redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListRightPushAsync(redisKey, redisValue);
} /// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public async Task<long> ListLeftPushAsync(string redisKey, string redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListLeftPushAsync(redisKey, redisValue);
} /// <summary>
/// 返回列表上该键的长度,如果不存在,返回 0
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<long> ListLengthAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListLengthAsync(redisKey);
} /// <summary>
/// 返回在该列表上键所对应的元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<IEnumerable<RedisValue>> ListRangeAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListRangeAsync(redisKey);
} /// <summary>
/// 移除并返回存储在该键列表的第一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<T> ListLeftPopAsync<T>(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(await _db.ListLeftPopAsync(redisKey));
} /// <summary>
/// 移除并返回存储在该键列表的最后一个元素
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<T> ListRightPopAsync<T>(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return Deserialize<T>(await _db.ListRightPopAsync(redisKey));
} /// <summary>
/// 在列表尾部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public async Task<long> ListRightPushAsync<T>(string redisKey, T redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListRightPushAsync(redisKey, Serialize(redisValue));
} /// <summary>
/// 在列表头部插入值。如果键不存在,先创建再插入值
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisValue"></param>
/// <returns></returns>
public async Task<long> ListLeftPushAsync<T>(string redisKey, T redisValue)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.ListLeftPushAsync(redisKey, Serialize(redisValue));
} #endregion List-async #endregion List 操作

List 操作

有序集合(sorted set)

  有序集合成员是唯一的,这就意味着集合中不能出现重复的数据。

        #region SortedSet 操作

        /// <summary>
/// SortedSet 新增
/// </summary>
/// <param name="redisKey"></param>
/// <param name="member"></param>
/// <param name="score"></param>
/// <returns></returns>
public bool SortedSetAdd(string redisKey, string member, double score)
{
redisKey = AddKeyPrefix(redisKey);
return _db.SortedSetAdd(redisKey, member, score);
} /// <summary>
/// 在有序集合中返回指定范围的元素,默认情况下从低到高。
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public IEnumerable<RedisValue> SortedSetRangeByRank(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.SortedSetRangeByRank(redisKey);
} /// <summary>
/// 返回有序集合的元素个数
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public long SortedSetLength(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.SortedSetLength(redisKey);
} /// <summary>
/// 返回有序集合的元素个数
/// </summary>
/// <param name="redisKey"></param>
/// <param name="memebr"></param>
/// <returns></returns>
public bool SortedSetLength(string redisKey, string memebr)
{
redisKey = AddKeyPrefix(redisKey);
return _db.SortedSetRemove(redisKey, memebr);
} /// <summary>
/// SortedSet 新增
/// </summary>
/// <param name="redisKey"></param>
/// <param name="member"></param>
/// <param name="score"></param>
/// <returns></returns>
public bool SortedSetAdd<T>(string redisKey, T member, double score)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(member); return _db.SortedSetAdd(redisKey, json, score);
} #region SortedSet-Async /// <summary>
/// SortedSet 新增
/// </summary>
/// <param name="redisKey"></param>
/// <param name="member"></param>
/// <param name="score"></param>
/// <returns></returns>
public async Task<bool> SortedSetAddAsync(string redisKey, string member, double score)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.SortedSetAddAsync(redisKey, member, score);
} /// <summary>
/// 在有序集合中返回指定范围的元素,默认情况下从低到高。
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<IEnumerable<RedisValue>> SortedSetRangeByRankAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.SortedSetRangeByRankAsync(redisKey);
} /// <summary>
/// 返回有序集合的元素个数
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<long> SortedSetLengthAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.SortedSetLengthAsync(redisKey);
} /// <summary>
/// 返回有序集合的元素个数
/// </summary>
/// <param name="redisKey"></param>
/// <param name="memebr"></param>
/// <returns></returns>
public async Task<bool> SortedSetRemoveAsync(string redisKey, string memebr)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.SortedSetRemoveAsync(redisKey, memebr);
} /// <summary>
/// SortedSet 新增
/// </summary>
/// <param name="redisKey"></param>
/// <param name="member"></param>
/// <param name="score"></param>
/// <returns></returns>
public async Task<bool> SortedSetAddAsync<T>(string redisKey, T member, double score)
{
redisKey = AddKeyPrefix(redisKey);
var json = Serialize(member); return await _db.SortedSetAddAsync(redisKey, json, score);
} #endregion SortedSet-Async #endregion SortedSet 操作

SortedSet 操作

Key 操作

        #region key 操作

        /// <summary>
/// 移除指定 Key
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public bool KeyDelete(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.KeyDelete(redisKey);
} /// <summary>
/// 移除指定 Key
/// </summary>
/// <param name="redisKeys"></param>
/// <returns></returns>
public long KeyDelete(IEnumerable<string> redisKeys)
{
var keys = redisKeys.Select(x => (RedisKey)AddKeyPrefix(x));
return _db.KeyDelete(keys.ToArray());
} /// <summary>
/// 校验 Key 是否存在
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public bool KeyExists(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.KeyExists(redisKey);
} /// <summary>
/// 重命名 Key
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisNewKey"></param>
/// <returns></returns>
public bool KeyRename(string redisKey, string redisNewKey)
{
redisKey = AddKeyPrefix(redisKey);
return _db.KeyRename(redisKey, redisNewKey);
} /// <summary>
/// 设置 Key 的时间
/// </summary>
/// <param name="redisKey"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public bool KeyExpire(string redisKey, TimeSpan? expiry)
{
redisKey = AddKeyPrefix(redisKey);
return _db.KeyExpire(redisKey, expiry);
} #region key-async /// <summary>
/// 移除指定 Key
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<bool> KeyDeleteAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.KeyDeleteAsync(redisKey);
} /// <summary>
/// 移除指定 Key
/// </summary>
/// <param name="redisKeys"></param>
/// <returns></returns>
public async Task<long> KeyDeleteAsync(IEnumerable<string> redisKeys)
{
var keys = redisKeys.Select(x => (RedisKey)AddKeyPrefix(x));
return await _db.KeyDeleteAsync(keys.ToArray());
} /// <summary>
/// 校验 Key 是否存在
/// </summary>
/// <param name="redisKey"></param>
/// <returns></returns>
public async Task<bool> KeyExistsAsync(string redisKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.KeyExistsAsync(redisKey);
} /// <summary>
/// 重命名 Key
/// </summary>
/// <param name="redisKey"></param>
/// <param name="redisNewKey"></param>
/// <returns></returns>
public async Task<bool> KeyRenameAsync(string redisKey, string redisNewKey)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.KeyRenameAsync(redisKey, redisNewKey);
} /// <summary>
/// 设置 Key 的时间
/// </summary>
/// <param name="redisKey"></param>
/// <param name="expiry"></param>
/// <returns></returns>
public async Task<bool> KeyExpireAsync(string redisKey, TimeSpan? expiry)
{
redisKey = AddKeyPrefix(redisKey);
return await _db.KeyExpireAsync(redisKey, expiry);
} #endregion key-async #endregion key 操作

key 操作

发布订阅

  一般会使用第三方的 MQ,如 RabbitMQ。

        #region 发布订阅

        /// <summary>
/// 订阅
/// </summary>
/// <param name="channel"></param>
/// <param name="handle"></param>
public void Subscribe(RedisChannel channel, Action<RedisChannel, RedisValue> handle)
{
var sub = ConnMultiplexer.GetSubscriber();
sub.Subscribe(channel, handle);
} /// <summary>
/// 发布
/// </summary>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public long Publish(RedisChannel channel, RedisValue message)
{
var sub = ConnMultiplexer.GetSubscriber();
return sub.Publish(channel, message);
} /// <summary>
/// 发布(使用序列化)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public long Publish<T>(RedisChannel channel, T message)
{
var sub = ConnMultiplexer.GetSubscriber();
return sub.Publish(channel, Serialize(message));
} #region 发布订阅-async /// <summary>
/// 订阅
/// </summary>
/// <param name="channel"></param>
/// <param name="handle"></param>
public async Task SubscribeAsync(RedisChannel channel, Action<RedisChannel, RedisValue> handle)
{
var sub = ConnMultiplexer.GetSubscriber();
await sub.SubscribeAsync(channel, handle);
} /// <summary>
/// 发布
/// </summary>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public async Task<long> PublishAsync(RedisChannel channel, RedisValue message)
{
var sub = ConnMultiplexer.GetSubscriber();
return await sub.PublishAsync(channel, message);
} /// <summary>
/// 发布(使用序列化)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public async Task<long> PublishAsync<T>(RedisChannel channel, T message)
{
var sub = ConnMultiplexer.GetSubscriber();
return await sub.PublishAsync(channel, Serialize(message));
} #endregion 发布订阅-async #endregion 发布订阅

发布订阅

其他

  这里使用了二进制序列化器进行序列化操作。

        /// <summary>
/// 添加 Key 的前缀
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
private static string AddKeyPrefix(string key)
{
return $"{DefaultKey}:{key}";
} /// <summary>
/// 序列化
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
private static byte[] Serialize(object obj)
{
if (obj == null)
return null; var binaryFormatter = new BinaryFormatter();
using (var memoryStream = new MemoryStream())
{
binaryFormatter.Serialize(memoryStream, obj);
var data = memoryStream.ToArray();
return data;
}
} /// <summary>
/// 反序列化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="data"></param>
/// <returns></returns>
private static T Deserialize<T>(byte[] data)
{
if (data == null)
return default(T); var binaryFormatter = new BinaryFormatter();
using (var memoryStream = new MemoryStream(data))
{
var result = (T)binaryFormatter.Deserialize(memoryStream);
return result;
}
}

  测试代码:

  【备注】内部还有很多的接口和方法没有进行封装,还需要自己进行封装。

【GitHub】https://github.com/liqingwen2015/Wen.Helpers  后续维护只在代码中


【博主】反骨仔

【原文】http://www.cnblogs.com/liqingwen/p/6672452.html

【参考】http://www.cnblogs.com/qtqq/p/5951201.html

[C#] 使用 StackExchange.Redis 封装属于自己的 Helper的更多相关文章

  1. [C#] 使用 StackExchange.Redis 封装属于自己的 RedisHelper

    使用 StackExchange.Redis 封装属于自己的 RedisHelper 目录 核心类 ConnectionMultiplexer 字符串(String) 哈希(Hash) 列表(List ...

  2. 使用 StackExchange.Redis 封装属于自己的 RedisHelper

    目录 核心类 ConnectionMultiplexer 字符串(String) 哈希(Hash) 列表(List) 有序集合(sorted set) Key 操作 发布订阅 其他 简介 目前 .NE ...

  3. StackExchange.Redis 封装

    博主最近开始玩Redis啊~~ 看了很多Redis的文章,感觉有点云里雾里的,之前看到是ServiceStack.Redis,看了一些大佬封装的Helper类,还是懵懵的QAQ 没办法啊只能硬着**上 ...

  4. c#使用 StackExchange.Redis 封装 RedisHelper

    公司一直在用.net自带的缓存,大家都知道.net自带缓存的缺点,就不多说了,不知道的可以查一查,领导最近在说分布式缓存,我们选的是redis,领导让我不忙的时候封装一下,搜索了两天,选了选第三方的插 ...

  5. 功能比较全的StackExchange.Redis封装帮助类(.Net/C#)

    Redis官网https://redis.io/ 以下内容未全部验证,如有问题请指出 //static NewtonsoftSerializer serializer = new Newtonsoft ...

  6. DotNet Core 使用 StackExchange.Redis 简单封装和实现分布式锁

    前言 公司的项目以前一直使用 CSRedis 这个类库来操作 Redis,最近增加了一些新功能,会存储一些比较大的数据,内测的时候发现其中有两台服务器会莫名的报错 Unexpected respons ...

  7. C# StackExchange.Redis 用法总结

    安装 StackExchange.Redis 在 NuGet 中搜索 StackExchange.Redis 和 Newtonsoft.Json,直接点击按钮安装即可. StackExchange.R ...

  8. redis的安装、启动、主从配置,以及.Net下StackExchange.Redis的使用

    开门见山,Linux下配个环境真是苦逼死了,这里记录一下,囧 一.环境 服务端:Ubuntu16.04 LTS(虚拟机,redis官方没有window发布版本,而且在Linux下运行更稳定) 客户端: ...

  9. StackExchange.Redis帮助类解决方案RedisRepository封装(基础配置)

    本文版权归博客园和作者吴双本人共同所有,转载和爬虫,请注明原文地址.http://www.cnblogs.com/tdws/p/5815735.html 写在前面 这不是教程,分享而已,也欢迎园友们多 ...

随机推荐

  1. 一张图理解RACSignal的Subscription过程

    通过下面一张图理解RACSignal的调用过程: 创建signale RACSignal通过子类[RACDynamicSignal createSignal:]方法获得Signal,并将disSubs ...

  2. storyboard页面跳转传值

    受学姐的影响,习惯纯代码编程,这次要修改别人的代码,很多编程风格还不习惯. 在此之前,页面跳转我都用的是Navigation,故事板上的页面跳转带传值,让我卡了好半天. 页面跳转: [self per ...

  3. 将Error异常日志从普通日志中剥离

    开发过程中经常需要调试和线上环境查看异常日志的需求,但普通消息与异常消息混在一起实在是非常难得找,上则NM的文档够你头痛,所以就将Error级别的日志抽离出来. 本示例采用log4net来配置: 1. ...

  4. Manual | BSD手册| Linux手册 | 数据库手册 | 编程开发手册 | WEB开发手册 | 软件应用手册 | 网络技术手册 | GNU手册

    豆豆手册 □ BSD手册 □ Linux手册 □ 数据库手册 □ 编程开发手册 □ WEB开发手册 □ 软件应用手册 □ 网络技术手册 □ GNU手册 在线手册 首 页 BSD手册   ·FreeBS ...

  5. Asp.net mvc 4.0 高级编程 百度云下载

    Asp.net mvc 4.0 高级编程 百度云下载地址:链接:http://pan.baidu.com/s/1o6zFvOe 密码:xyss 1.基于 ASP.NET MVC4.0 + WebAPI ...

  6. javascipt : reduce

    $scope.totalPrice = function () { return $scope.addcartProduct.reduce(function (money, product) { re ...

  7. Nginx错误页面优雅显示

    一.Nginx错误页面优雅显示的原因?   当我们访问网站时,由于特殊的原因,经常会出现诸如403,404,503等错误,这极大的影响用户的访问体验,所以我们很有必要做一下错误页面的优雅显示,以提升用 ...

  8. Struts2之访问路径

    上一篇已经和大家分享了关于Struts2命名空间和Action的三种创建方式,本篇我们接着命名空间的内容,来一起探讨一下关于Struts2的访问路径问题,何为访问路径,就是指当我们在浏览器输入地址,点 ...

  9. React 入门之路(1)

    React React简介 是由Facebook公司推广的一套框架,已经应用instagram等产品 React就是为了提供应用程序性能而设计的一套框架 在angular中,对dom提供了一些指令,让 ...

  10. struts2(二) 表单参数自动封装和参数类型自动转换

    前篇文章对struts2的一个入门,重点是对struts2的架构图有一个大概的了解即可,之后的几篇文章,就是细化struts2,将struts2中的各种功能进行梳理,其实学完之后,对struts2的使 ...