一. 写在前面
毕业工作后,今天终于能回家了,回想了一些这半年来所做的内容,总是觉得还停留在那么基础的水平 ,在解决各种问题的过程中,自己的创新思路比较少,靠搜索来的比较多 。不想做16年的总结了 ,希望17年能学更多的我爱的技术,看更多的开源代码,能学到更多的设计思想和代码思路,能再更新这两年来对代码的理解。
这篇分享,主要是弥补我之前redisrepository的不足。
半年前由于我stackexchange.redis文档阅读不足,所分享的redisrepository有所错误。下面列举我的主要错误:
错误1,没有单例化connectionmultiplexer redis连接对象,并且我天真的以为给单例对象加锁,在并发情况下,会限制了redis的性能。
错误2,在主从情况下,我以为在发生手动切换的时候,我们要订阅切换事件,并在事件发生后,动态改变连接对象指向的endpoint。
当我再一次仔细阅读文档时,才明白我的错误,这是一篇迟到的修正,但是我自用的repository自我感觉还是有很多不足之处,所以我真的需要老司机的指点和建议。
修正1,redis连接对象创建的代价很大,并且单例加锁并不会影响redis性能,因为在发生网络请求的期间,连接对象并没有在等待中。
修正2,redis主从时,在哨兵切换主从关系后,stackexchange.redis会为我们识别新的主从,不需要我们做任何操作。
目前为止我还有两个疑问。
疑问1,在看文档后没有明确结果。当做主从读写分离时, 我们在endpoint collection集合中添加多个节点就会自动读写分离?还是说需要 我们在读取命令的方法中指定commandflags.preferslave? 我认为是后者吧?所以我在我所有的读取方法都指定了preferslave。 老司机们怎么说?
疑问2,我使用luascript.prepare(lua)后再load出来,执行lua总是无效果,并且luascript.getcachedscriptcount()为0. 不过我直接使用scriptevaluateasync却是好用的,老司机如果有好的例子,希望老司机给些指导或者分享。
二. 代码结构,仅供参考
结构大概就是这样,redisasynchelper下的所有类都是部分类,他们的类名称是redishelper。他们共同实现了iredishelper的接口,并且留下了详细的注释。
同步版本和异步版本的目录结构是一样的。
三. 预备阶段
commonhelper中的两个帮助类:
redisinnertypehelper.cs
using stackexchange.redis;
using system.collections.generic;
using system.linq;
namespace fantasy.redisrepository.commonhelper
{
internal class redisinnertypehelper
{
public static list<t> redisvaluestogenericlist<t>(redisvalue[] redisvalues)
{
var result = new list<t>();
redisvalues.tolist().foreach(r => result.add(serializehelper.deserialize<t>(r)));
return result;
}
public static redisvalue[] genericlisttoredisvalues<t>(list<t> values)
{
var redisvalues = new list<redisvalue>();
values.foreach(v => redisvalues.add(serializehelper.serialize(values)));
return redisvalues.toarray();
}
public static rediskey[] genericlisttorediskeys(list<string> keys)
{
var rediskeys = new list<rediskey>();
keys.foreach(k => rediskeys.add(k));
return rediskeys.toarray();
}
}
}
serializehelper.cs
using system.io;
using system.runtime.serialization.formatters.binary;
namespace fantasy.redisrepository.commonhelper
{
internal static class serializehelper
{
/// <summary>
/// 字节数组序列化
/// </summary>
/// <param name="o"></param>
/// <returns></returns>
internal static byte[] serialize(object o)
{
if (o == null)
{
return null;
}
binaryformatter binaryformatter = new binaryformatter();
using (memorystream memorystream = new memorystream())
{
binaryformatter.serialize(memorystream, o);
byte[] objectdataasstream = memorystream.toarray();
return objectdataasstream;
}
}
/// <summary>
/// 字节数组反序列化
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="stream"></param>
/// <returns></returns>
internal static t deserialize<t>(byte[] stream)
{
if (stream == null)
{
return default(t);
}
binaryformatter binaryformatter = new binaryformatter();
using (memorystream memorystream = new memorystream(stream))
{
t result = (t)binaryformatter.deserialize(memorystream);
return result;
}
}
}
}
config中的配置类:
confighelper.csusing system;
using system.configuration;
namespace fantasy.redisrepository.config
{
internal class confighelper
{
internal static t get<t>(string appsettingskey, t defaultvalue)
{
string text = configurationmanager.appsettings[appsettingskey];
if (string.isnullorwhitespace(text))
return defaultvalue;
try
{
var value = convert.changetype(text, typeof(t));
return (t)value;
}
catch
{
return defaultvalue;
}
}
}
}
redisclientconfig.cs
namespace fantasy.redisrepository.config
{
internal class redisclientconfig
{
private static string _server = confighelper.get("redisserver", "115.xx.xx.31");
/// <summary>
/// 节点ip
/// </summary>
public static string server
{
get { return _server; }
set { _server = value; }
}
private static int _port = confighelper.get("redisport", 6380);
/// <summary>
/// 节点端口
/// </summary>
public static int port
{
get { return _port; }
set { _port = value; }
}
private static string _slaveserver = confighelper.get("slaveserver", "115.xx.xx.31");
/// <summary>
/// 节点ip
/// </summary>
public static string slaveserver
{
get { return _slaveserver; }
set { _slaveserver = value; }
}
private static int _slaveport = confighelper.get("slaveport", 6381);
/// <summary>
/// 节点端口
/// </summary>
public static int slaveport
{
get { return _slaveport; }
set { _slaveport = value; }
}
private static string _auth = confighelper.get("redisauth", "fantasy..");
/// <summary>
/// 节点密码
/// </summary>
public static string redisauth
{
get { return _auth; }
set { _auth = value; }
}
private static int _defaultdatabase = confighelper.get("redisdatabase", 0);
/// <summary>
/// redis默认0号库
/// </summary>
public static int defaultdatabase
{
get { return _defaultdatabase; }
set { _defaultdatabase = value; }
}
private static int _connecttimeout = 10000;
public static int connecttimeout
{
get { return _connecttimeout; }
set { _connecttimeout = value; }
}
private static int _connectretry = 3;
public static int connectretry
{
get { return _connectretry; }
set { _connectretry = value; }
}
private static bool _preserveasyncorder = false;
public static bool preserveasyncorder
{
get { return _preserveasyncorder; }
set { _preserveasyncorder = value; }
}
}
}
redisconnection.cs
using fantasy.redisrepository.config;
using stackexchange.redis;
namespace fantasy.redisrepository
{
/// <summary>
/// redis连接类
/// </summary>
public static class redisconnection
{
private static connectionmultiplexer _connection;
private static readonly object syncobject = new object();
/// <summary>
/// redis连接对象,单例加锁不影响性能
/// </summary>
public static connectionmultiplexer generateconnection
{
get
{
if (_connection == null || !_connection.isconnected)
{
lock (syncobject)
{
var configurationoptions = new configurationoptions()
{
password = redisclientconfig.redisauth,
endpoints =
{
{redisclientconfig.server, redisclientconfig.port},
{redisclientconfig.slaveserver, redisclientconfig.slaveport}
}
};
_connection = connectionmultiplexer.connect(configurationoptions);
}
}
return _connection;
}
}
}
}
四. redishelper
实际上就是做了层序列化包装而已。
iredishelper:
using system;
using stackexchange.redis;
using system.collections.generic;
using system.threading.tasks;
namespace fantasy.redisrepository.redishelpers
{
/// <summary>
/// 异步方法接口 --author 吴双 www.cnblogs.com/tdws
/// 存入数据均为方法内部序列化后的byte,所以取数据的时候需要反序列化时,请指定正确的数据类型
/// </summary>
public partial interface iredishelper
{
#region redis数据类型—string
/// <summary>
/// 将任何数据以redis string存储
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="timeout"></param>
/// <returns></returns>
task<bool> stringsetasync<t>(string key, t value, timespan? timeout = null);
/// <summary>
/// 对数值进行减法操作,默认-1
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns>操作后的结果</returns>
task<long> stringdecrementasync(string key, long value = 1l);
/// <summary>
/// 对数值进行加法操作,默认+1
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns>操作后的结果</returns>
task<long> stringincrementasync(string key, long value = 1l);
/// <summary>
/// 从redis string中以指定类型取出
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
task<t> stringgetasync<t>(string key);
#endregion
#region redis数据类型—hash
/// <summary>
/// 向hash key中存储任意类型任意值
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="field"></param>
/// <param name="value"></param>
/// <returns>是否成功</returns>
task<bool> hashsetasync<t>(string key, string field, t value);
/// <summary>
/// 批量 向hash key中存储任意类型任意值
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="hashfields"></param>
/// <returns>无返回值</returns>
task hashmultisetasync<t>(string key, dictionary<string, t> hashfields);
/// <summary>
/// 对指定hash key中制定field做数量增加操作 默认自增1
/// 如果此操作前key不存在 则创建。 如果此操作前该field不存在或者非数字 则先被置0,再被继续操作
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
/// <param name="incrcount"></param>
/// <returns>操作后的结果</returns>
task<long> hashincrementasync(string key, string field, long incrcount = 1);
/// <summary>
/// 对指定hash key中制定field做数量增加操作 默认自减1
/// 如果此操作前key不存在 则创建。 如果此操作前该field不存在或者非数字 则先被置0,再被继续操作
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
/// <param name="decrcount"></param>
/// <returns>操作后的结果</returns>
task<long> hashdecrementasync(string key, string field, long decrcount = 1);
/// <summary>
/// 从指定hash中 删除指定field
/// 如果key或者field不存在,则false
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
/// <returns>是否成功</returns>
task<bool> hashdeletefieldasync(string key, string field);
/// <summary>
/// 从指定hash key中 批量删除指定field
/// 如果key或者field不存在,则false
/// </summary>
/// <param name="key"></param>
/// <param name="fields"></param>
/// <returns>移除数量</returns>
task<long> hashmultideletefieldasync(string key, list<string> fields);
/// <summary>
/// 从指定hash key中获取指定field值
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="field"></param>
/// <returns></returns>
task<t> hashgetasync<t>(string key, string field);
/// <summary>
/// 从指定hash key中判断field是否存在
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
/// <returns></returns>
task<bool> hashfieldexistasync(string key, string field);
/// <summary>
/// 获取指定hash key中的所有field的值
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
task<list<t>> hashvaluesasync<t>(string key);
/// <summary>
/// 获取指定hash key中所有 field名称及其value
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
task<dictionary<string, t>> hashgetallasync<t>(string key);
/// <summary>
/// 获取指定hash key中所有field
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
task<list<string>> hashfieldsasync(string key);
#endregion
#region redis数据类型—list
/// <summary>
/// 在指定pivot后插入value, 如果pivot不存在,则返回-1, 如果key不存在,则返回0
/// 如果存在多个相同指定的的pivot,则插入第一个指定pivot后面.
/// 即链表从左向右查找,遇到指定pivot,则确定位置
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="pivot">list中的一个值</param>
/// <param name="value"></param>
/// <returns></returns>
task<long> listinsertafterasync<t>(string key, string pivot, t value);
/// <summary>
/// 在指定pivot前插入value, 如果pivot不存在,则返回-1, 如果key不存在,则返回0
/// 如果存在多个相同指定的的pivot,则插入第一个指定pivot前面.
/// 即链表从左向右查找,遇到指定pivot,则确定位置
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="pivot"></param>
/// <param name="value"></param>
/// <returns></returns>
task<long> listinsertbeforeasync<t>(string key, string pivot, t value);
/// <summary>
/// 从链表左侧弹出第一个元素(弹出能获取到该元素并且被删除)
/// 如果key不存在 或者链表为空 则为null
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
task<t> listleftpopasync<t>(string key);
/// <summary>
/// 从链表左侧增加一个元素,key不存在则被创建
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns>返回操作后的链表长度</returns>
task<long> listleftpushasync<t>(string key, t value);
/// <summary>
/// 从链表左侧批量增加元素,如果 a b c 则c会在链表左侧第一位 b第二位 a第三位
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="values"></param>
/// <returns>返回操作后的链表长度</returns>
task<long> listleftmultipushasync<t>(string key, list<t> values);
/// <summary>
/// 获取链表长度,不存在key则为0
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
task<long> listlengthasync<t>(string key);
/// <summary>
/// 获取链表中所有数据,从左侧start开始到stop结束,从0—-1则认为获取全部,默认获取全部
/// start为负数则代表从链表右侧开始,-1为右侧第一位,-2为右侧第二位
/// start要小于stop,否则返回null
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="start"></param>
/// <param name="stop"></param>
/// <returns></returns>
task<list<t>> listrangeasync<t>(string key, long start = 0l, long stop = -1l);
/// <summary>
/// 从链表中一处count数量的value. count大于0则从左至右,count小于0则从右至左,count=0则移除全部
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="count"></param>
/// <returns></returns>
task<long> listremoveasync<t>(string key, t value, long count = 0l);
/// <summary>
/// 从右侧弹出第一个元素(弹出能获取到该元素并且被删除)
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
task<t> listrightpopasync<t>(string key);
/// <summary>
/// 从链表右侧加入元素,如果 rpush a b c 则c为右侧第一位 b第二位 c第三位
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
task<long> listrightpushasync<t>(string key, t value);
/// <summary>
/// 从右侧批量插入,和左侧相反
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="values"></param>
/// <returns></returns>
task<long> listrightmultipushasync<t>(string key, list<t> values);
/// <summary>
/// 在链表指定索引处,插入元素
/// 正数索引从0开始,代表左侧。负数从-1开始 代表从右侧。-1为右侧第一位
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="index"></param>
/// <param name="value"></param>
/// <returns></returns>
task listsetbyindexasync<t>(string key, int index, t value);
/// <summary>
/// 留下start到stop之间的数据。负数代表从右侧寻找 -1为右侧第一位
/// </summary>
/// <param name="key"></param>
/// <param name="start"></param>
/// <param name="stop"></param>
/// <returns></returns>
task listtrimasync(string key, long start, long stop);
/// <summary>
/// 获取指定index的值,负数代表从右侧寻找 -1为右侧第一位
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="index"></param>
/// <returns></returns>
task<t> listgetbyindexasync<t>(string key, long index);
#endregion
#region redis数据类型—set
/// <summary>
/// 向指定集合中增加一个元素
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
task<bool> setaddasync<t>(string key, t value);
/// <summary>
/// 指定集合计算操作operation枚举,指定计算结果将存的目标destkey,指定需要参与计算的多个key
/// </summary>
/// <param name="operation"></param>
/// <param name="destkey"></param>
/// <param name="combinekeys"></param>
/// <returns></returns>
task<long> setcombineandstoreasync(setoperation operation, string destkey, list<string> combinekeys);
/// <summary>
/// 指定集合计算操作operation枚举,指定需要参与计算的多个key
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="operation"></param>
/// <param name="combinekeys"></param>
/// <returns></returns>
task<list<t>> setcombineasync<t>(setoperation operation, list<string> combinekeys);
/// <summary>
/// 指定值是否存在于指定集合中
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
task<bool> setcontainsasync<t>(string key, t value);
/// <summary>
/// 获取指定集合中元素个数
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
task<long> setlengthasync(string key);
/// <summary>
/// 获取指定集合中的所有元素
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
task<list<t>> setmembersasync<t>(string key, t value);
/// <summary>
/// 从sourcekey移除指定value到目标distkey集合当中
/// 如果sourcekey存在指定value则返回true,否则不做任何操作返回false
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="sourcekey"></param>
/// <param name="distkey"></param>
/// <param name="value"></param>
/// <returns></returns>
task<bool> setmoveasync<t>(string sourcekey, string distkey, t value);
/// <summary>
/// 从指定集合当中随机取出一个元素
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
task<t> setrandommemberasync<t>(string key);
/// <summary>
/// 从指定集合随机弹出(删除并获取)一个元素
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
task<t> setpopasync<t>(string key);
/// <summary>
/// 从集合中随机弹出(删除并获取)多个元素
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
task<list<t>> setrandommembersasync<t>(string key);
/// <summary>
/// 从集合中移除指定元素
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <returns></returns>
task<bool> setremoveasync<t>(string key, t value);
/// <summary>
/// 从集合中批量移除元素
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="values"></param>
/// <returns></returns>
task<long> setmultiremoveasync<t>(string key, list<t> values);
#endregion
#region redis数据类型—sortset
#endregion
#region redis key操作
/// <summary>
/// 删除指定key
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
task<bool> keydeleteasync(string key);
/// <summary>
/// 设置key过期时间具体datetime
/// </summary>
/// <param name="key"></param>
/// <param name="expireat"></param>
/// <returns></returns>
task<bool> keyexpireatasync(string key, datetime expireat);
/// <summary>
/// 设置key在将来的timeout后过期(timespan)
/// </summary>
/// <param name="key"></param>
/// <param name="timeout"></param>
/// <returns></returns>
task<bool> keyexpireinasync(string key, timespan timeout);
/// <summary>
/// key重命名
/// </summary>
/// <param name="key"></param>
/// <param name="newkey"></param>
/// <returns></returns>
task<bool> keyrenameasync(string key, string newkey);
/// <summary>
/// 判断key是否已存在
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
task<bool> keyexistsasync(string key);
#endregion
#region redis transcation
/// <summary>
/// 在事务中执行一系列redis命令。注意:在委托中的一系列命令的所有 值 都需要进行字节数组序列化
/// </summary>
/// <param name="ranoperations"></param>
/// <returns></returns>
task<bool> dointranscationasync(action<itransaction> ranoperations);
#endregion
task<redisresult> test();
}
}
redishelper部分类redisstringhelperasync.cs
using system;
using fantasy.redisrepository.commonhelper;
using stackexchange.redis;
using system.threading.tasks;
namespace fantasy.redisrepository.redishelpers
{
/// <summary>
/// redis异步操作类 string部分类
/// </summary>
internal partial class redishelper// : iredishelper
{
private static idatabase _client;
internal redishelper()
{
_client = redisconnection.generateconnection.getdatabase();
}
#region string 写操作
/// <summary>
/// 将任何数据添加到redis中
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
/// <param name="timeout"></param>
/// <returns></returns>
public async task<bool> stringsetasync<t>(string key, t value, timespan? timeout = null)
{
return await _client.stringsetasync(key, serializehelper.serialize(value), timeout);
}
public async task<long> stringdecrementasync(string key, long value = 1l)
{
return await _client.stringdecrementasync(key, value);
}
public async task<long> stringincrementasync(string key, long value = 1l)
{
return await _client.stringincrementasync(key, value);
}
#endregion
#region string 读操作
/// <summary>
/// 根据key获取指定类型数据
/// </summary>
/// <typeparam name="t"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public async task<t> stringgetasync<t>(string key)
{
return serializehelper.deserialize<t>(await _client.stringgetasync(key, commandflags.preferslave));
}
#endregion
}
}
redishelper部分类redishashhelperasync.cs
using fantasy.redisrepository.commonhelper;
using stackexchange.redis;
using system.collections.generic;
using system.linq;
using system.threading.tasks;
namespace fantasy.redisrepository.redishelpers
{
/// <summary>
/// redis异步操作类 hash部分类
/// </summary>
internal partial class redishelper
{
#region hash 写操作
public async task<bool> hashsetasync<t>(string key, string field, t value)
{
return await _client.hashsetasync(key, field, serializehelper.serialize(value));
}
public async task hashmultisetasync<t>(string key, dictionary<string, t> hashfields)
{
list<hashentry> entries = new list<hashentry>();
hashfields.tolist().foreach(d => entries.add(new hashentry(d.key, serializehelper.serialize(d.value))));
await _client.hashsetasync(key, entries.toarray());
}
public async task<long> hashincrementasync(string key, string field, long incrcount = 1)
{
return await _client.hashincrementasync(key, field, incrcount);
}
public async task<long> hashdecrementasync(string key, string field, long decrcount = 1)
{
return await _client.hashdecrementasync(key, field, decrcount);
}
public async task<bool> hashdeletefieldasync(string key, string field)
{
return await _client.hashdeleteasync(key, field);
}
public async task<long> hashmultideletefieldasync(string key, list<string> fields)
{
list<redisvalue> values = new list<redisvalue>();
fields.foreach(f => values.add(f));
return await _client.hashdeleteasync(key, values.toarray());
}
#endregion
#region hash 读操作
/// <summary>
/// redis 指定hash类型key中field是否存在
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
/// <returns></returns>
public async task<bool> hashfieldexistasync(string key, string field)
{
return await _client.hashexistsasync(key, field, commandflags.preferslave);
}
public async task<list<string>> hashfieldsasync(string key)
{
redisvalue[] values = await _client.hashkeysasync(key, commandflags.preferslave);
return redisinnertypehelper.redisvaluestogenericlist<string>(values);
}
public async task<list<t>> hashvaluesasync<t>(string key)
{
var values = await _client.hashvaluesasync(key, commandflags.preferslave);
return redisinnertypehelper.redisvaluestogenericlist<t>(values);
}
public async task<t> hashgetasync<t>(string key, string field)
{
return serializehelper.deserialize<t>(await _client.hashgetasync(key, field, commandflags.preferslave));
}
public async task<dictionary<string, t>> hashgetallasync<t>(string key)
{
hashentry[] entries = await _client.hashgetallasync(key, commandflags.preferslave);
dictionary<string, t> dic = new dictionary<string, t>();
entries.tolist().foreach(e => dic.add(e.name, serializehelper.deserialize<t>(e.value)));
return dic;
}
#endregion
}
}
redishelper部分类redislisthelperasync.cs
using fantasy.redisrepository.commonhelper;
using stackexchange.redis;
using system.collections.generic;
using system.linq;
using system.threading.tasks;
namespace fantasy.redisrepository.redishelpers
{
/// <summary>
/// redis异步操作类 hash部分类
/// </summary>
internal partial class redishelper
{
#region hash 写操作
public async task<bool> hashsetasync<t>(string key, string field, t value)
{
return await _client.hashsetasync(key, field, serializehelper.serialize(value));
}
public async task hashmultisetasync<t>(string key, dictionary<string, t> hashfields)
{
list<hashentry> entries = new list<hashentry>();
hashfields.tolist().foreach(d => entries.add(new hashentry(d.key, serializehelper.serialize(d.value))));
await _client.hashsetasync(key, entries.toarray());
}
public async task<long> hashincrementasync(string key, string field, long incrcount = 1)
{
return await _client.hashincrementasync(key, field, incrcount);
}
public async task<long> hashdecrementasync(string key, string field, long decrcount = 1)
{
return await _client.hashdecrementasync(key, field, decrcount);
}
public async task<bool> hashdeletefieldasync(string key, string field)
{
return await _client.hashdeleteasync(key, field);
}
public async task<long> hashmultideletefieldasync(string key, list<string> fields)
{
list<redisvalue> values = new list<redisvalue>();
fields.foreach(f => values.add(f));
return await _client.hashdeleteasync(key, values.toarray());
}
#endregion
#region hash 读操作
/// <summary>
/// redis 指定hash类型key中field是否存在
/// </summary>
/// <param name="key"></param>
/// <param name="field"></param>
/// <returns></returns>
public async task<bool> hashfieldexistasync(string key, string field)
{
return await _client.hashexistsasync(key, field, commandflags.preferslave);
}
public async task<list<string>> hashfieldsasync(string key)
{
redisvalue[] values = await _client.hashkeysasync(key, commandflags.preferslave);
return redisinnertypehelper.redisvaluestogenericlist<string>(values);
}
public async task<list<t>> hashvaluesasync<t>(string key)
{
var values = await _client.hashvaluesasync(key, commandflags.preferslave);
return redisinnertypehelper.redisvaluestogenericlist<t>(values);
}
public async task<t> hashgetasync<t>(string key, string field)
{
return serializehelper.deserialize<t>(await _client.hashgetasync(key, field, commandflags.preferslave));
}
public async task<dictionary<string, t>> hashgetallasync<t>(string key)
{
hashentry[] entries = await _client.hashgetallasync(key, commandflags.preferslave);
dictionary<string, t> dic = new dictionary<string, t>();
entries.tolist().foreach(e => dic.add(e.name, serializehelper.deserialize<t>(e.value)));
return dic;
}
#endregion
}
}
redisluahelper.cs 这里打算装一些功能行lua脚本, 外部依然是传key一类的参数,这个不完整,只是个实例。
using stackexchange.redis;
using system.threading.tasks;
namespace fantasy.redisrepository.redishelpers
{
internal partial class redishelper
{
public async task<redisresult> luamutilgethash()
{
string lua = @"local result={}
for i, v in ipairs(keys) do
result[i] = redis.call('hgetall',v)
end
return result";
var res = await _client.scriptevaluateasync(lua, new rediskey[] { "people:1", "people:2", "people:3" });
var res1= luascript.getcachedscriptcount();
return res;
}
}
}
关于transcation的封装,我个人没有什么好的方法,提供了这样一个方法
public async task<bool> dointranscationasync(action<itransaction> runoperations)
{
var tran = redisconnection.generateconnection.getdatabase().createtransaction();
runoperations(tran);
return await tran.executeasync();
}
redisfactory.cs
using fantasy.redisrepository.redishelpers;
namespace fantasy.redisrepository
{
public class redisfactory
{
/// <summary>
/// 外部访问redis入口,暂时只暴露异步方法
/// </summary>
/// <returns></returns>
public static iredishelper createredisrepository()
{
return new redishelper();
}
}
}
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!
更多redisrepository 分享和纠错。