StackExchange.Redis帮助类解决方案RedisRepository封装(字符串类型数据操作)
本文版权归博客园和作者本人共同所有,转载和爬虫请注明原文链接 http://www.cnblogs.com/tdws/tag/NoSql/
一、基础配置封装
四、List列表类型数据操作封装(建议自行封装)
五、Set集合类型数据操作封装(建议自行封装)
六、Sort Set集合数据类型操作封装(建议自行封装)
七、发布订阅(Pub/Sub)模式在StackExchange.Redis中的使用
八、主从配置,哨兵相关配置
下面这段画如果看一遍没看懂,请看过代码后再次来阅读:
我们有必要先提到ConnectionMultiplexer类,它是StackExchange提供给我们的一个类,它将多服务器的详细信息隐藏,因为这个类为我们做了很多事情,它的设计目的是为了在调用者间共享和重用。你不用每次操作都创建这样一个ConnectionMultiplexer,它是完全线程安全的。它拥有ConnectionMultiplexer.Connect和onnectionMultiplexer.ConnectAsync来链接Redis。链接 参数是一个字符串或者一个ConfigurationOptions对象。这个类实现了IDisposable接口,你可以在你不需要的时候释放对象,通过using或者dispose。但是你不用经常来释放它,因为我们要经常复用。你有三种需求时,需要使用ConnectionMultiplexer,链接Redis,发布订阅模式,访问一个单独的服务器或者监控的目的。除了基本使用,更多的请看github文档,https://github.com/StackExchange/StackExchange.Redis/blob/master/Docs/Basics.md
我们在IRedisClient中定义如下String数据类型方法:
如果你觉得代码太多,当VS按下快捷键ctrl+M+O吧
#region 程序集 RedisRepository, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// Author:吴双 2016.8.28 联系邮箱 wscoder@outlook.com
#endregion
using System;
using System.Collections.Generic;
using StackExchange.Redis; namespace RedisRepository
{
public interface IRedisClient
{
#region Redis String类型操作
/// <summary>
/// Redis String类型 新增一条记录
/// </summary>
/// <typeparam name="T">generic refrence type</typeparam>
/// <param name="key">unique key of value</param>
/// <param name="value">value of key of type object</param>
/// <param name="expiresAt">time span of expiration</param>
/// <param name= "when">枚举类型</param>
/// <param name="commandFlags"></param>
/// <returns>true or false</returns>
bool StringSet<T>(string key, object value, TimeSpan? expiry = default(TimeSpan?), When when = When.Always, CommandFlags commandFlags = CommandFlags.None) where T : class; /// <summary>
/// Redis String类型 新增一条记录
/// </summary>
/// <typeparam name="T">generic refrence type</typeparam>
/// <param name="key">unique key of value</param>
/// <param name="value">value of key of type object</param>
/// <param name="expiresAt">time span of expiration</param>
/// <param name= "when">枚举类型</param>
/// <param name="commandFlags"></param>
/// <returns>true or false</returns>
bool StringSet<T>(string key, T value, TimeSpan? expiry = default(TimeSpan?), When when = When.Always, CommandFlags commandFlags = CommandFlags.None) where T : class; /// <summary>
/// 更新时应使用此方法,代码更可读。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="expiresAt"></param>
/// <param name="when"></param>
/// <param name="commandFlags"></param>
/// <returns></returns>
bool StringUpdate<T>(string key, T value, TimeSpan expiresAt, When when = When.Always, CommandFlags commandFlags = CommandFlags.None) where T : class; /// <summary>
/// Redis String类型 Get
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="commandFlags"></param>
/// <returns>T</returns>
T StringGet<T>(string key, CommandFlags commandFlags = CommandFlags.None) where T : class; /// <summary>
/// Redis String数据类型 获取指定key中字符串长度
/// </summary>
/// <param name="key"></param>
/// <param name="commandFlags"></param>
/// <returns></returns>
long StringLength(string key, CommandFlags commandFlags = CommandFlags.None); /// <summary>
/// Redis String数据类型 返回拼接后总长度
/// </summary>
/// <param name="key"></param>
/// <param name="appendVal"></param>
/// <param name="commandFlags"></param>
/// <returns>总长度</returns>
long StringAppend(string key, string appendVal, CommandFlags commandFlags = CommandFlags.None); /// <summary>
/// 设置新值并且返回旧值
/// </summary>
/// <param name="key"></param>
/// <param name="newVal"></param>
/// <param name="commandFlags"></param>
/// <returns>OldVal</returns>
string StringGetAndSet(string key, string newVal, CommandFlags commandFlags = CommandFlags.None); /// <summary>
/// 为数字增长val
/// </summary>
/// <param name="key"></param>
/// <param name="val"></param>
/// <param name="commandFlags"></param>
/// <returns>增长后的值</returns>
double StringIncrement(string key, double val, CommandFlags commandFlags = CommandFlags.None); /// <summary>
/// Redis String数据类型
/// 类似于模糊查询 key* 查出所有key开头的键
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="pageSize"></param>
/// <param name="commandFlags"></param>
/// <returns>返回List<T></returns>
List<T> StringGetList<T>(string key, int pageSize = , CommandFlags commandFlags = CommandFlags.None) where T : class;
#endregion #region Redis各数据类型公用 /// <summary>
/// Redis中是否存在指定Key
/// </summary>
/// <param name="key"></param>
/// <param name="commandFlags"></param>
/// <returns></returns>
bool KeyExists(string key, CommandFlags commandFlags = CommandFlags.None); /// <summary>
/// 从Redis中移除键
/// </summary>
/// <param name="key"></param>
/// <param name="commandFlags"></param>
/// <returns></returns>
bool KeyRemove(string key, CommandFlags commandFlags = CommandFlags.None); /// <summary>
/// 从Redis中移除多个键
/// </summary>
/// <param name="keys"></param>
/// <param name="commandFlags"></param>
/// <returns></returns>
void KeyRemove(RedisKey[] keys, CommandFlags commandFlags = CommandFlags.None); /// <summary>
/// Dispose DB connection 释放DB相关链接
/// </summary>
void DbConnectionStop();
#endregion
}
}
在RedisClient.cs中实现如下:
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using StackExchange.Redis; namespace RedisRepository
{
public class RedisClient : IRedisClient
{ #region 初始化 private static readonly IDatabase _db;
private static readonly ConnectionMultiplexer _redis; /// <summary>
/// 构造函数,在其中注册Redis事件
/// </summary>
static RedisClient()
{
const string configuration = "{0},abortConnect=false,defaultDatabase={1},ssl=false,ConnectTimeout={2},allowAdmin=true,connectRetry={3}";
_redis = ConnectionMultiplexer
.Connect(string.Format(configuration, RedisClientConfigurations.Url,
RedisClientConfigurations.DefaultDatabase, RedisClientConfigurations.ConnectTimeout,
RedisClientConfigurations.ConnectRetry));
_redis.PreserveAsyncOrder = RedisClientConfigurations.PreserveAsyncOrder;
//_redis.ConnectionFailed;
_db = _redis.GetDatabase();
} #endregion #region Redis String数据类型操作 /// <summary>
/// Redis String类型 新增一条记录
/// </summary>
/// <typeparam name="T">generic refrence type</typeparam>
/// <param name="key">unique key of value</param>
/// <param name="value">value of key of type T</param>
/// <param name="expiresAt">time span of expiration</param>
/// <returns>true or false</returns>
public bool StringSet<T>(string key, T value, TimeSpan? expiresAt = default(TimeSpan?), When when = When.Always, CommandFlags commandFlags = CommandFlags.None) where T : class
{
var stringContent = SerializeContent(value);
return _db.StringSet(key, stringContent, expiresAt, when, commandFlags);
} /// <summary>
/// Redis String类型 新增一条记录
/// </summary>
/// <typeparam name="T">generic refrence type</typeparam>
/// <param name="key">unique key of value</param>
/// <param name="value">value of key of type object</param>
/// <param name="expiresAt">time span of expiration</param>
/// <returns>true or false</returns>
public bool StringSet<T>(string key, object value, TimeSpan? expiresAt = default(TimeSpan?), When when = When.Always, CommandFlags commandFlags = CommandFlags.None) where T : class
{
var stringContent = SerializeContent(value); return _db.StringSet(key, stringContent, expiresAt, when, commandFlags);
} /// <summary>
/// Redis String数据类型 获取指定key中字符串长度
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public long StringLength(string key, CommandFlags commandFlags = CommandFlags.None)
{
return _db.StringLength(key, commandFlags);
} /// <summary>
/// Redis String数据类型 返回拼接后总长度
/// </summary>
/// <param name="key"></param>
/// <param name="appendVal"></param>
/// <returns>总长度</returns>
public long StringAppend(string key, string appendVal, CommandFlags commandFlags = CommandFlags.None)
{
return _db.StringAppend(key, appendVal, commandFlags);
} /// <summary>
/// 设置新值并且返回旧值
/// </summary>
/// <param name="key"></param>
/// <param name="newVal"></param>
/// <param name="commandFlags"></param>
/// <returns>OldVal</returns>
public string StringGetAndSet(string key, string newVal, CommandFlags commandFlags = CommandFlags.None)
{
return DeserializeContent<string>(_db.StringGetSet(key, newVal, commandFlags));
} /// <summary>
/// 更新时应使用此方法,代码更可读。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="expiresAt"></param>
/// <param name="when"></param>
/// <param name="commandFlags"></param>
/// <returns></returns>
public bool StringUpdate<T>(string key, T value, TimeSpan expiresAt, When when = When.Always, CommandFlags commandFlags = CommandFlags.None) where T : class
{
var stringContent = SerializeContent(value);
return _db.StringSet(key, stringContent, expiresAt, when, commandFlags);
} /// <summary>
/// 为数字增长val
/// </summary>
/// <param name="key"></param>
/// <param name="val">可以为负</param>
/// <param name="commandFlags"></param>
/// <returns>增长后的值</returns>
public double StringIncrement(string key, double val, CommandFlags commandFlags = CommandFlags.None)
{
return _db.StringIncrement(key, val, commandFlags);
} /// <summary>
/// Redis String类型 Get
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns>T</returns>
public T StringGet<T>(string key, CommandFlags commandFlags = CommandFlags.None) where T : class
{
try
{
RedisValue myString = _db.StringGet(key, commandFlags);
if (myString.HasValue && !myString.IsNullOrEmpty)
{
return DeserializeContent<T>(myString);
}
else
{
return null;
}
}
catch (Exception)
{
// Log Exception
return null;
}
} /// <summary>
/// Redis String类型
/// 类似于模糊查询 key* 查出所有key开头的键
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="pageSize"></param>
/// <param name="commandFlags"></param>
/// <returns>List<T></returns>
public List<T> StringGetList<T>(string key, int pageSize = , CommandFlags commandFlags = CommandFlags.None) where T : class
{
try
{
var server = _redis.GetServer(host: RedisClientConfigurations.Url,
port: RedisClientConfigurations.Port);
var keys = server.Keys(_db.Database, key, pageSize, commandFlags);
var keyValues = _db.StringGet(keys.ToArray(), commandFlags); var result = new List<T>();
foreach (var redisValue in keyValues)
{
if (redisValue.HasValue && !redisValue.IsNullOrEmpty)
{
var item = DeserializeContent<T>(redisValue);
result.Add(item);
}
} return result;
}
catch (Exception)
{
// Log Exception
return null;
}
} #endregion #region Redis Hash散列数据类型操作 #endregion #region Redis List列表数据类型操作 #endregion #region Redis Set集合数据类型操作 #endregion #region Redis Sort Set有序集合数据类型操作 #endregion #region Redis各数据类型公用 /// <summary>
/// Redis中是否存在指定Key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool KeyExists(string key, CommandFlags commandFlags = CommandFlags.None)
{
return _db.KeyExists(key, commandFlags);
} /// <summary>
/// Dispose DB connection 释放DB相关链接
/// </summary>
public void DbConnectionStop()
{
_redis.Dispose();
} /// <summary>
/// 从Redis中移除键
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public bool KeyRemove(string key, CommandFlags commandFlags = CommandFlags.None)
{
return _db.KeyDelete(key, commandFlags);
}
/// <summary>
/// 从Redis中移除多个键
/// </summary>
/// <param name="keys"></param>
public void KeyRemove(RedisKey[] keys, CommandFlags commandFlags = CommandFlags.None)
{
_db.KeyDelete(keys, commandFlags);
}
#endregion #region 私有公用方法 // serialize and Deserialize content in separate functions as redis can save value as array of binary.
// so, any time you need to change the way of handling value, do it here. private string SerializeContent(object value)
{
return JsonConvert.SerializeObject(value);
} private T DeserializeContent<T>(RedisValue myString)
{
return JsonConvert.DeserializeObject<T>(myString);
} #endregion
}
}
下面简单介绍一下本文中的方法细节之处。
首先在RedisClient类的构造方法中初始化Redis数据操作对象_db。每个方法更多的详尽信息请注意方法注释。如果关于Redis命令还不了解,请看前期Redis命令拾遗系列文章 http://www.cnblogs.com/tdws/tag/NoSql/
有园友指出问题说
Because the ConnectionMultiplexer does a lot, it is designed to be shared and reused between callers. You should not create a ConnectionMultiplexer per operation. It is fully thread-safe and ready for this usage.
这是官方文档的原话,ConnectionMultiplexer比较“重”,建议共用,不要每次操作就创建一个
所以暂时将构造函数改为静态构造。如果有问题,欢迎提之处
30日,反思了一下,还是加锁的单例更为合适。
StackExchange.Redis帮助类解决方案RedisRepository封装(字符串类型数据操作)的更多相关文章
- StackExchange.Redis帮助类解决方案RedisRepository封装(基础配置)
本文版权归博客园和作者吴双本人共同所有,转载和爬虫,请注明原文地址.http://www.cnblogs.com/tdws/p/5815735.html 写在前面 这不是教程,分享而已,也欢迎园友们多 ...
- StackExchange.Redis帮助类解决方案RedisRepository封装(散列Hash类型数据操作)
本文版权归博客园和作者本人共同所有,转载和爬虫请注明本系列分享地址:http://www.cnblogs.com/tdws/p/5815735.html 上一篇文章的不合理之处,已经有所修改. 今天分 ...
- redis:string字符串类型的操作
1. string字符串类型的操作: 1.1. set 设置单个值 语法:set key value [EX seconds] [PX milliseconds] [NX|XX] 注: EX seco ...
- Python学习笔记(三)字符串类型及其操作(2)
1.字符串的表示 字符串是字符的序列表示,可以由一对单引号(‘).双引号(“)或三引号(’‘’)构成.其中,单引号.双引号和三引号都可以表示单行字符串,但是只有三引号可以表示多行字符串 在使用双引号时 ...
- StackExchange.Redis 异步超时解决方案
Timeout awaiting response (outbound=0KiB, inbound=45417KiB, 5891ms elapsed, timeout is 5000ms), comm ...
- 封装字符串的Format操作
相信即使再讨厌MFC的朋友也不会把厌恶牵扯到CString类上,而且CString现在也提升为ATL和MFC的共享类.用CString类,当然不能忘记它的Format方法,其用于格式化字符串.示例操作 ...
- Redis常用命令入门1:字符串类型命令
Redis总共有五种数据类型,在学习的时候,一定要开一个redis-cli程序,边看边练,提高效率. 一.最简单的命令 1.获得符合规则的键名列表 keys * 这里的*号,是指列出所有的键,同时*号 ...
- Redis自学笔记:3.2入门-字符串类型
3.2字符串类型 实际上redis不只是数据库,更多的公司和团队将redis用作缓存和 队列系统 3.2.1介绍 字符串类型是redis最基本的数据类型,它能存储任何形式的字符串, 包括二进制数据.你 ...
- mysql字符串类型数据
字符串类型是在数据库中存储字符串的数据类型,字符串类型包括char,varchar,text,enum和set. OK,我们来一个一个的看下上面提到的几种类型. char类型和varchar类型 ch ...
随机推荐
- XML技术之DOM4J解析器
由于DOM技术的解析,存在很多缺陷,比如内存溢出,解析速度慢等问题,所以就出现了DOM4J解析技术,DOM4J技术的出现大大改进了DOM解析技术的缺陷. 使用DOM4J技术解析XML文件的步骤? pu ...
- SQL Server 2016白皮书
随着SQL Server 2016正式版发布日临近,相关主要特性通过以下预览学习: Introducing Microsoft SQL Server 2016 e-bookSQL Server 201 ...
- Node.js学习笔记——Node.js开发Web后台服务
一.简介 Node.js 是一个基于Google Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.Node.j ...
- SharePoint2016安装的过程的”Microsoft.SharePoint.Upgrade.SPUpgradeException”错误解决方法
前提 在windows server 2012的服务器上运行安装sharepoint2016出现如下错误: Could not load file or assembly ‘Microsoft.Dat ...
- 【腾讯bugly干货分享】微信Android热补丁实践演进之路
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1264& ...
- 【腾讯Bugly干货分享】微信终端跨平台组件 mars 系列(二) - 信令传输超时设计
本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/9DJxipJaaBC8yC-buHgnTQ 作者简介: ...
- WPF - 属性系统 (4 of 4)
依赖项属性的重写 在基于C#的编程中,对属性的重写常常是一种行之有效的解决方案:在基类所提供的属性访问符实现不能满足当前要求的时候,我们就需要重新定义属性的访问符. 但对于依赖项属性而言,属性执行逻辑 ...
- Windows10-UWP中设备序列显示不同XAML的三种方式[3]
阅读目录: 概述 DeviceFamily-Type文件夹 DeviceFamily-Type扩展 InitializeComponent重载 结论 概述 Windows10-UWP(Universa ...
- 工欲善其事,必先利其器 之 WPF篇: 随着开发轨迹来看高效WPF开发的工具和技巧
之前一篇<工欲善其事,必先利其器.VS2013全攻略(安装,技巧,快捷键,插件)!> 看到很多朋友回复和支持,非常感谢,尤其是一些拍砖的喷油,感谢你们的批评,受益良多. 我第一份工作便是W ...
- Entity Framework 6 Recipes 2nd Edition(12-7)译 -> 设定默认值
12-7. 设定默认值 问题 在把一个实体保存到数据库之前,设置该实体属性的默认值 解决方案 假设你有一个如Figure 12-9所示的表, 它保存采购订单(purchase order). 主键Pu ...