当前位置: 移动技术网 > IT编程>开发语言>.net > Redis分布式队列和缓存更新

Redis分布式队列和缓存更新

2018年09月07日  | 移动技术网IT编程  | 我要评论

天天向上120330,亚冠16强对阵,顺德交友网

  原文链接:

  在使用redis中,我们可能会遇到以下场景:

  例如:

  某用户向服务器中发送一个请求,服务器将用户请求加入redis任务队列,任务完成则移出队列。

  以上场景有几点疑问:

  1. redis队列中数据如果不仅仅来自于我们的应用程序,那么我们怎么把这个数据加入redis?
  2. 当redis队列中用户的请求达程序所能处理的峰值。那么我们该如何处理这些用户请求?

  解决方案:

  1.  对外提供接口,将请求数据添加至db。启动一个定时服务,在规定时间扫描db中的请求数据并添加至redis队列。
  2. 使用分布式异步队列。

  以上解决方案都可以使用插件来实现。

  1. 使用quartz.net
  2. 使用stackexchange.redis

  一、

  关于quartz.net可以通过上面链接获取官方api。它与sql server中的代理作业有着同样功能。

  代码示例:

  

 1  /// <summary>
 2         /// 添加job并以周期的形式运行
 3         /// </summary>
 4         /// <typeparam name="t"></typeparam>
 5         /// <param name="jobname">job名称</param>
 6         /// <param name="jobgroupname">job组名称</param>
 7         /// <param name="replace">job是否可修改</param>
 8         /// <param name="triggername">job触发器的名称</param>
 9         /// <param name="minutes">job执行的时间间隔,以分为单位</param>
10         /// <returns></returns>
11         public datetimeoffset addjob<t>(string jobname, string jobgroupname, bool replace, string triggername, int minutes) where t : ijob
12         {
13             ijobdetail jobdetail = jobbuilder.create<t>().withidentity(jobname, jobgroupname).build();
14             _sched.addjob(jobdetail, replace);
15             itrigger trigger = triggerbuilder.create()
16               .withidentity(triggername, jobgroupname)
17               .startnow()
18               .withsimpleschedule(x => x
19                   .withintervalinminutes(minutes)//表示分钟的时间间隔
20                   .repeatforever())
21               .build();
22             return _sched.schedulejob(jobdetail, trigger).result;
23         }
view code

  以上的代码中是基于quartz封装一个添加了job的方法。这个方法依赖于 “ijobdetail” 和 “itrigger” 这两个对象。

  “ijobdetail” 表示job的身份信息,“itrigger” 则包含了job执行信息,它表示job该如何执行。

  以下为调用示例:

  

1 quartzhelper quartzhelper = quartzhelper.createinstance();
2                 quartzhelper.addjob<testjob>("testjob", "testjob_group",false, "testjob_trigger",1*10);
view code

  上述实例中的 “testjob” 实现quartz.net中的 "ijob" 接口。这个接口只有一个方法 “execute”,并由quartz.net框架自行调用该方法。

  你可以在此方法中执行你的代码。并在添加该job制定你的执行策略 “itrigger” 对象。然后框架会根据你制定的策略进行调用。调用参数请参见上述封装。

 

  下面是向redis队列插入数据的示例job:

  

 1 public class testjob : ijob
 2     {
 3         task ijob.execute(ijobexecutioncontext context)
 4         {
 5             //jobdatamap datamap = context.jobdetail.jobdatamap;
 6             task task = task.run(
 7                   () =>
 8                   {
 9                       console.writeline(string.format("{0}开始执行!当前系统时间{1}", this.gettype().name, datetime.now));
10                       try
11                       {
12                           string rediskey = this.gettype().name;
13                           redishelper redishelper = new redishelper();
14                           if (redishelper.keyexists(rediskey))
15                           {
16                               redishelper.keydelete(rediskey);
17                           };
18 
19                           for (int i = 1; i <= 10; i++)
20                           {
21                               user user = new user()
22                               {
23                                   id = i,
24                                   name = "user" + datetime.now.ticks +"_"+ i                                  
25                               };
26                               redishelper.listleftpush<user>(rediskey, user);//模拟db用户数据
27                           }
28                       }
29                       catch (exception ex)
30                       {
31                           console.writeline(string.format("{0}任务出现异常,异常信息:{1}!当前系统时间{2}", this.gettype().name, ex.message, datetime.now));
32                       }
33                   }
34                   );
35             return task;
36         }
37     }
view code

 

  上面的 “testjob” 模拟了从db加载用户请求数据至redis队列。至此我们已经解决了上面的第一个问题。

 

  二、

  在.net中redis的插件不多。比较流行有 "servicestack.redis" 和 "stackexchange.redis" 。

  "servicestack.redis" 为官方推出的插件。非开源插件,且普通版最高只支持 6000/s 读写。高级版是要收费的。为了后续扩展,这里我们采用 "stackexchange.redis" 。

  关于stackexchange.redis可以通过上面链接获取官方api,目前是开源的。

  在第一个问题中,已经通过定时job的方式向redis队列中填充数据。下面我们通过 "stackexchange.redis" 获取redis队列中的请求并处理这些请求。

 

  1.加载数据至redis:

  

 1 using app_test.job;
 2 using common.quartz;
 3 using common.redis.stackexchange;
 4 using quartz;
 5 using system;
 6 using system.collections.generic;
 7 using system.linq;
 8 using system.text;
 9 using system.threading.tasks;
10 
11 namespace app_test
12 {
13     class program
14     {
15         static void main(string[] args)
16         {
17             {
18                 redishelper redishelpera = new redishelper();
19                 redishelper redishelperb = new redishelper();
20                 string stra = redishelpera.stringget("mykey");
21                 string strb = redishelperb.stringget("mykey");
22                 if (stra== strb)
23                 {
24                     console.writeline(string.format("***********{0}=={1}***********", stra, strb));
25                 }
26                 else
27                 {
28                     console.writeline(string.format("***********{0}!={1}***********", stra, strb));
29                 }
30             }
31 
32             {
33                 
34                 quartzhelper quartzhelper = quartzhelper.createinstance();
35                 quartzhelper.addjob<testjob>("testjob", "testjob_group",false, "testjob_trigger",1*10);//这里设置了以秒为单位
36             }
37 
38             console.readkey();
39         }
40         
41     }
42 }
view code

 

  

 

  可以看到上面代码执行的时间节点与我们所添加job中的 ”itrigger “ 的触发策略完全一致。至此,我们第一步已得到验证。

 

  2.启动处理redis队列中请求的程序。

  

 1 using app_test.models;
 2 using common.redis.stackexchange;
 3 using system;
 4 using system.collections.generic;
 5 using system.linq;
 6 using system.text;
 7 using system.threading.tasks;
 8 
 9 namespace app_redisclienttest
10 {
11     class program
12     {
13         static void main(string[] args)
14         {
15             redishelper redishelper = new redishelper();
16             string rediskey = "testjob";
17             while (true)
18             {
19                 action action = new action(() =>
20                 {
21                     user user = redishelper.listleftpop<user>(rediskey);//获取请求数据并移出队列
22                     if (user!=null)
23                     {
24                         console.writeline(string.format("*******{0}*******", user.name));
25                     }                    
26                 }
27                     );
28                 action.endinvoke(action.begininvoke(null, null));
29             }
30             console.readkey();
31         }
32     }
33 }
view code

 

  

  上面我启动3个客户端实例,他们一起处理redis队列中的请求。每当job向redis队列中添加请求对象后就会立即被我们处理请求的程序获取并消费,每当一个请求被消费就会被移出redis队列。并且遵循先入先出的准则。按照上述,如果出现主程序请求量过高情形,我们只需要启动多个处理请求的辅助程序即可缓解主程序的压力。

  至此上面的两个问题已得到验证。

 

  如下附个人基于 "quartz.net" 和 "stackexchange.redis" 封装的帮助类

  

  1 using system;
  2 using system.collections.generic;
  3 
  4 namespace common.quartz
  5 {
  6     using global::quartz;
  7     using global::quartz.impl;
  8     using global::quartz.impl.matchers;
  9 
 10     /// <summary>
 11     /// v:3.0.6.0
 12     /// </summary>
 13     public class quartzhelper
 14     {
 15         private readonly static object _obj = new object();//单例锁
 16 
 17         //private  ischedulerfactory _sf = null;
 18 
 19         private static ischeduler _sched = null;
 20         /// <summary>
 21         /// 提供ischeduler对象,访问异步方法
 22         /// </summary>
 23         public ischeduler scheduler { get { return _sched; } }
 24 
 25         private static quartzhelper _quartzhelper = null;//单例对象
 26 
 27         private quartzhelper()
 28         {
 29             //_sf = new stdschedulerfactory();
 30             //_sched = _sf.getscheduler().result;
 31             _sched = stdschedulerfactory.getdefaultscheduler().result;
 32             _sched.start();
 33         }
 34 
 35         /// <summary>
 36         /// 获取单例对象
 37         /// </summary>
 38         /// <returns></returns>
 39         public static quartzhelper createinstance()
 40         {
 41             if (_quartzhelper == null) //双if +lock
 42             {
 43                 lock (_obj)
 44                 {
 45                     if (_quartzhelper == null)
 46                     {
 47                         _quartzhelper = new quartzhelper();
 48                     }
 49                 }
 50             }
 51             return _quartzhelper;
 52         }
 53         public bool checkexists(triggerkey triggerkey)
 54         {
 55             return _sched.checkexists(triggerkey).result;
 56         }
 57         public bool checkexists(jobkey jobkey)
 58         {
 59             return _sched.checkexists(jobkey).result;
 60         }
 61         public ireadonlycollection<ijobexecutioncontext> getcurrentlyexecutingjobs()
 62         {
 63             return _sched.getcurrentlyexecutingjobs().result;
 64         }
 65 
 66         /// <summary>
 67         /// 添加job并以周期的形式运行
 68         /// </summary>
 69         /// <typeparam name="t"></typeparam>
 70         /// <param name="jobname">job名称</param>
 71         /// <param name="jobgroupname">job组名称</param>
 72         /// <param name="replace">job是否可修改</param>
 73         /// <param name="triggername">job触发器的名称</param>
 74         /// <param name="minutes">job执行的时间间隔,以分为单位</param>
 75         /// <returns></returns>
 76         public datetimeoffset addjob<t>(string jobname, string jobgroupname, bool replace, string triggername, int minutes) where t : ijob
 77         {
 78             ijobdetail jobdetail = jobbuilder.create<t>().withidentity(jobname, jobgroupname).build();
 79             _sched.addjob(jobdetail, replace);
 80             itrigger trigger = triggerbuilder.create()
 81               .withidentity(triggername, jobgroupname)
 82               .startnow()
 83               .withsimpleschedule(x => x
 84                   .withintervalinseconds(minutes)//seconds表示秒的时间间隔
 85                                                  //.withintervalinminutes(minutes)//表示分钟的时间间隔
 86                   .repeatforever())
 87               .build();
 88             return _sched.schedulejob(jobdetail, trigger).result;
 89         }
 90         public bool deletejobs(ireadonlycollection<jobkey> jobkeys)
 91         {
 92             return _sched.deletejobs(jobkeys).result;
 93         }
 94         public ijobdetail getjobdetail(jobkey jobkey)
 95         {
 96             return _sched.getjobdetail(jobkey).result;
 97         }
 98         public ireadonlycollection<string> getjobgroupnames()
 99         {
100             return _sched.getjobgroupnames().result;
101         }
102         public ireadonlycollection<jobkey> getjobkeys(groupmatcher<jobkey> matcher)
103         {
104             return _sched.getjobkeys(matcher).result;
105         }
106         public bool interrupt(jobkey jobkey)
107         {
108             return _sched.interrupt(jobkey).result;
109         }
110         public bool isjobgrouppaused(string groupname)
111         {
112             return _sched.isjobgrouppaused(groupname).result;
113         }
114         public itrigger gettrigger(triggerkey triggerkey)
115         {
116             return _sched.gettrigger(triggerkey).result;
117         }
118         public ireadonlycollection<string> gettriggergroupnames()
119         {
120             return _sched.gettriggergroupnames().result;
121         }
122         public ireadonlycollection<triggerkey> gettriggerkeys(groupmatcher<triggerkey> matcher)
123         {
124             return _sched.gettriggerkeys(matcher).result;
125         }
126         public ireadonlycollection<itrigger> gettriggersofjob(jobkey jobkey)
127         {
128             return _sched.gettriggersofjob(jobkey).result;
129         }
130         public triggerstate gettriggerstate(triggerkey triggerkey)
131         {
132             return _sched.gettriggerstate(triggerkey).result;
133         }
134         public ireadonlycollection<string> getpausedtriggergroups()
135         {
136             return _sched.getpausedtriggergroups().result;
137         }
138         public bool interrupt(string fireinstanceid)
139         {
140             return _sched.interrupt(fireinstanceid).result;
141         }
142         public bool istriggergrouppaused(string groupname)
143         {
144             return _sched.istriggergrouppaused(groupname).result;
145         }
146         public void pauseall()
147         {
148             _sched.pauseall();
149         }
150         public void pausejobs(groupmatcher<jobkey> matcher)
151         {
152             _sched.pausejobs(matcher);
153         }
154         public void pausetriggers(groupmatcher<triggerkey> matcher)
155         {
156             _sched.pausetriggers(matcher);
157         }
158         public void resumeall()
159         {
160             _sched.resumeall();
161         }
162         public void resumejobs(groupmatcher<jobkey> matcher)
163         {
164             _sched.resumejobs(matcher);
165         }
166         public void resumetriggers(groupmatcher<triggerkey> matcher)
167         {
168             _sched.resumetriggers(matcher);
169         }
170         public void schedulejobs(ireadonlydictionary<ijobdetail, ireadonlycollection<itrigger>> triggersandjobs, bool replace)
171         {
172             _sched.schedulejobs(triggersandjobs, replace);
173         }
174         public datetimeoffset? reschedulejob(triggerkey triggerkey, itrigger newtrigger)
175         {
176             return _sched.reschedulejob(triggerkey, newtrigger).result;
177         }
178         public void shutdown(bool waitforjobstocomplete)
179         {
180             _sched.shutdown(waitforjobstocomplete);
181         }
182         public void clear()
183         {
184             _sched.clear();
185         }
186 
187 
188     }
189 }
view code
   1 using stackexchange.redis;
   2 using system;
   3 using system.collections.generic;
   4 using system.configuration;
   5 using system.io;
   6 using system.linq;
   7 using system.runtime.serialization.formatters.binary;
   8 using system.threading.tasks;
   9 using newtonsoft.json;
  10 
  11 namespace common.redis.stackexchange
  12 {
  13     /// <summary>
  14     /// v:1.2.6.0
  15     /// </summary>
  16     public class redishelper
  17     {
  18         #region private field
  19 
  20         /// <summary>
  21         /// 连接字符串
  22         /// </summary>
  23         private static readonly string connectionstring;
  24 
  25         /// <summary>
  26         /// redis 连接对象
  27         /// </summary>
  28         private static iconnectionmultiplexer _connmultiplexer;
  29 
  30         /// <summary>
  31         /// 默认的 key 值(用来当作 rediskey 的前缀)
  32         /// </summary>
  33         private static readonly string defaultkey;
  34 
  35         /// <summary>
  36         /// 锁
  37         /// </summary>
  38         private static readonly object locker = new object();
  39 
  40         /// <summary>
  41         /// 数据库
  42         /// </summary>
  43         private readonly idatabase _db;
  44 
  45         #endregion private field
  46 
  47         #region 构造函数
  48 
  49         static redishelper()
  50         {
  51             connectionstring = configurationmanager.connectionstrings["redisconnectionstring"].connectionstring;
  52             _connmultiplexer = connectionmultiplexer.connect(connectionstring);
  53             defaultkey = configurationmanager.appsettings["redis.defaultkey"];
  54             addregisterevent();
  55         }
  56 
  57         public redishelper(int db = 0)
  58         {
  59             _db = _connmultiplexer.getdatabase(db);
  60         }
  61 
  62         #endregion 构造函数
  63 
  64         #region 其它
  65 
  66         /// <summary>
  67         /// 获取 redis 连接对象
  68         /// </summary>
  69         /// <returns></returns>
  70         public iconnectionmultiplexer getconnectionredismultiplexer()
  71         {
  72             if (_connmultiplexer == null || !_connmultiplexer.isconnected)
  73                 lock (locker)
  74                 {
  75                     if (_connmultiplexer == null || !_connmultiplexer.isconnected)
  76                         _connmultiplexer = connectionmultiplexer.connect(connectionstring);
  77                 }
  78 
  79             return _connmultiplexer;
  80         }
  81 
  82         public itransaction gettransaction()
  83         {
  84             return _db.createtransaction();
  85         }
  86 
  87         #endregion 其它
  88 
  89         #region 类型封装
  90 
  91         #region string 操作
  92 
  93         /// <summary>
  94         /// 设置 key 并保存字符串(如果 key 已存在,则覆盖值)
  95         /// </summary>
  96         /// <param name="rediskey"></param>
  97         /// <param name="redisvalue"></param>
  98         /// <param name="expiry"></param>
  99         /// <returns></returns>
 100         public bool stringset(string rediskey, string redisvalue, timespan? expiry = null)
 101         {
 102             rediskey = addkeyprefix(rediskey);
 103             return _db.stringset(rediskey, redisvalue, expiry);
 104         }
 105 
 106         /// <summary>
 107         /// 保存多个 key-value
 108         /// </summary>
 109         /// <param name="keyvaluepairs"></param>
 110         /// <returns></returns>
 111         public bool stringset(ienumerable<keyvaluepair<string, string>> keyvaluepairs)
 112         {
 113             var pairs = keyvaluepairs.select(x => new keyvaluepair<rediskey, redisvalue>(addkeyprefix(x.key), x.value));
 114             return _db.stringset(pairs.toarray());
 115         }
 116 
 117         /// <summary>
 118         /// 获取字符串
 119         /// </summary>
 120         /// <param name="rediskey"></param>
 121         /// <param name="expiry"></param>
 122         /// <returns></returns>
 123         public string stringget(string rediskey, timespan? expiry = null)
 124         {
 125             rediskey = addkeyprefix(rediskey);
 126             return _db.stringget(rediskey);
 127         }
 128 
 129         /// <summary>
 130         /// 存储一个对象(该对象会被序列化保存)
 131         /// </summary>
 132         /// <param name="rediskey"></param>
 133         /// <param name="redisvalue"></param>
 134         /// <param name="expiry"></param>
 135         /// <returns></returns>
 136         public bool stringset<t>(string rediskey, t redisvalue, timespan? expiry = null)
 137         {
 138             rediskey = addkeyprefix(rediskey);
 139             var json = serialize(redisvalue);
 140             return _db.stringset(rediskey, json, expiry);
 141         }
 142 
 143         /// <summary>
 144         /// 获取一个对象(会进行反序列化)
 145         /// </summary>
 146         /// <param name="rediskey"></param>
 147         /// <param name="expiry"></param>
 148         /// <returns></returns>
 149         public t stringget<t>(string rediskey, timespan? expiry = null)
 150         {
 151             rediskey = addkeyprefix(rediskey);
 152             return deserialize<t>(_db.stringget(rediskey));
 153         }
 154 
 155         #region async
 156 
 157         /// <summary>
 158         /// 保存一个字符串值
 159         /// </summary>
 160         /// <param name="rediskey"></param>
 161         /// <param name="redisvalue"></param>
 162         /// <param name="expiry"></param>
 163         /// <returns></returns>
 164         public async task<bool> stringsetasync(string rediskey, string redisvalue, timespan? expiry = null)
 165         {
 166             rediskey = addkeyprefix(rediskey);
 167             return await _db.stringsetasync(rediskey, redisvalue, expiry);
 168         }
 169 
 170         /// <summary>
 171         /// 保存一组字符串值
 172         /// </summary>
 173         /// <param name="keyvaluepairs"></param>
 174         /// <returns></returns>
 175         public async task<bool> stringsetasync(ienumerable<keyvaluepair<string, string>> keyvaluepairs)
 176         {
 177             var pairs = keyvaluepairs.select(x => new keyvaluepair<rediskey, redisvalue>(addkeyprefix(x.key), x.value));
 178             return await _db.stringsetasync(pairs.toarray());
 179         }
 180 
 181         /// <summary>
 182         /// 获取单个值
 183         /// </summary>
 184         /// <param name="rediskey"></param>
 185         /// <param name="redisvalue"></param>
 186         /// <param name="expiry"></param>
 187         /// <returns></returns>
 188         public async task<string> stringgetasync(string rediskey, string redisvalue, timespan? expiry = null)
 189         {
 190             rediskey = addkeyprefix(rediskey);
 191             return await _db.stringgetasync(rediskey);
 192         }
 193 
 194         /// <summary>
 195         /// 存储一个对象(该对象会被序列化保存)
 196         /// </summary>
 197         /// <param name="rediskey"></param>
 198         /// <param name="redisvalue"></param>
 199         /// <param name="expiry"></param>
 200         /// <returns></returns>
 201         public async task<bool> stringsetasync<t>(string rediskey, t redisvalue, timespan? expiry = null)
 202         {
 203             rediskey = addkeyprefix(rediskey);
 204             var json = serialize(redisvalue);
 205             return await _db.stringsetasync(rediskey, json, expiry);
 206         }
 207 
 208         /// <summary>
 209         /// 获取一个对象(会进行反序列化)
 210         /// </summary>
 211         /// <param name="rediskey"></param>
 212         /// <param name="expiry"></param>
 213         /// <returns></returns>
 214         public async task<t> stringgetasync<t>(string rediskey, timespan? expiry = null)
 215         {
 216             rediskey = addkeyprefix(rediskey);
 217             return deserialize<t>(await _db.stringgetasync(rediskey));
 218         }
 219 
 220         #endregion async
 221 
 222         #endregion string 操作
 223 
 224         #region hash 操作
 225 
 226         /// <summary>
 227         /// 判断该字段是否存在 hash 中
 228         /// </summary>
 229         /// <param name="rediskey"></param>
 230         /// <param name="hashfield"></param>
 231         /// <returns></returns>
 232         public bool hashexists(string rediskey, string hashfield)
 233         {
 234             rediskey = addkeyprefix(rediskey);
 235             return _db.hashexists(rediskey, hashfield);
 236         }
 237 
 238         /// <summary>
 239         /// 从 hash 中移除指定字段
 240         /// </summary>
 241         /// <param name="rediskey"></param>
 242         /// <param name="hashfield"></param>
 243         /// <returns></returns>
 244         public bool hashdelete(string rediskey, string hashfield)
 245         {
 246             rediskey = addkeyprefix(rediskey);
 247             return _db.hashdelete(rediskey, hashfield);
 248         }
 249 
 250         /// <summary>
 251         /// 从 hash 中移除指定字段
 252         /// </summary>
 253         /// <param name="rediskey"></param>
 254         /// <param name="hashfields"></param>
 255         /// <returns></returns>
 256         public long hashdelete(string rediskey, ienumerable<string> hashfields)
 257         {
 258             rediskey = addkeyprefix(rediskey);
 259             var fields = hashfields.select(x => (redisvalue)x);
 260 
 261             return _db.hashdelete(rediskey, fields.toarray());
 262         }
 263 
 264         /// <summary>
 265         /// 在 hash 设定值
 266         /// </summary>
 267         /// <param name="rediskey"></param>
 268         /// <param name="hashfield"></param>
 269         /// <param name="value"></param>
 270         /// <returns></returns>
 271         public bool hashset(string rediskey, string hashfield, string value)
 272         {
 273             rediskey = addkeyprefix(rediskey);
 274             return _db.hashset(rediskey, hashfield, value);
 275         }
 276 
 277         /// <summary>
 278         /// 在 hash 中设定值
 279         /// </summary>
 280         /// <param name="rediskey"></param>
 281         /// <param name="hashfields"></param>
 282         public void hashset(string rediskey, ienumerable<keyvaluepair<string, string>> hashfields)
 283         {
 284             rediskey = addkeyprefix(rediskey);
 285             var entries = hashfields.select(x => new hashentry(x.key, x.value));
 286 
 287             _db.hashset(rediskey, entries.toarray());
 288         }
 289 
 290         /// <summary>
 291         /// 在 hash 中获取值
 292         /// </summary>
 293         /// <param name="rediskey"></param>
 294         /// <param name="hashfield"></param>
 295         /// <returns></returns>
 296         public string hashget(string rediskey, string hashfield)
 297         {
 298             rediskey = addkeyprefix(rediskey);
 299             return _db.hashget(rediskey, hashfield);
 300         }
 301 
 302         /// <summary>
 303         /// 在 hash 中获取值
 304         /// </summary>
 305         /// <param name="rediskey"></param>
 306         /// <param name="hashfields"></param>
 307         /// <returns></returns>
 308         public ienumerable<string> hashget(string rediskey, ienumerable<string> hashfields)
 309         {
 310             rediskey = addkeyprefix(rediskey);
 311             var fields = hashfields.select(x => (redisvalue)x);
 312 
 313             return convertstrings(_db.hashget(rediskey, fields.toarray()));
 314         }
 315 
 316         /// <summary>
 317         /// 从 hash 返回所有的字段值
 318         /// </summary>
 319         /// <param name="rediskey"></param>
 320         /// <returns></returns>
 321         public ienumerable<string> hashkeys(string rediskey)
 322         {
 323             rediskey = addkeyprefix(rediskey);
 324             return convertstrings(_db.hashkeys(rediskey));
 325         }
 326 
 327         /// <summary>
 328         /// 返回 hash 中的所有值
 329         /// </summary>
 330         /// <param name="rediskey"></param>
 331         /// <returns></returns>
 332         public ienumerable<string> hashvalues(string rediskey)
 333         {
 334             rediskey = addkeyprefix(rediskey);
 335             return convertstrings(_db.hashvalues(rediskey));
 336         }
 337 
 338         /// <summary>
 339         /// 在 hash 设定值(序列化)
 340         /// </summary>
 341         /// <param name="rediskey"></param>
 342         /// <param name="hashfield"></param>
 343         /// <param name="redisvalue"></param>
 344         /// <returns></returns>
 345         public bool hashset<t>(string rediskey, string hashfield, t redisvalue)
 346         {
 347             rediskey = addkeyprefix(rediskey);
 348             var json = serialize(redisvalue);
 349 
 350             return _db.hashset(rediskey, hashfield, json);
 351         }
 352 
 353         /// <summary>
 354         /// 在 hash 中获取值(反序列化)
 355         /// </summary>
 356         /// <param name="rediskey"></param>
 357         /// <param name="hashfield"></param>
 358         /// <returns></returns>
 359         public t hashget<t>(string rediskey, string hashfield)
 360         {
 361             rediskey = addkeyprefix(rediskey);
 362 
 363             return deserialize<t>(_db.hashget(rediskey, hashfield));
 364         }
 365 
 366         #region async
 367 
 368         /// <summary>
 369         /// 判断该字段是否存在 hash 中
 370         /// </summary>
 371         /// <param name="rediskey"></param>
 372         /// <param name="hashfield"></param>
 373         /// <returns></returns>
 374         public async task<bool> hashexistsasync(string rediskey, string hashfield)
 375         {
 376             rediskey = addkeyprefix(rediskey);
 377             return await _db.hashexistsasync(rediskey, hashfield);
 378         }
 379 
 380         /// <summary>
 381         /// 从 hash 中移除指定字段
 382         /// </summary>
 383         /// <param name="rediskey"></param>
 384         /// <param name="hashfield"></param>
 385         /// <returns></returns>
 386         public async task<bool> hashdeleteasync(string rediskey, string hashfield)
 387         {
 388             rediskey = addkeyprefix(rediskey);
 389             return await _db.hashdeleteasync(rediskey, hashfield);
 390         }
 391 
 392         /// <summary>
 393         /// 从 hash 中移除指定字段
 394         /// </summary>
 395         /// <param name="rediskey"></param>
 396         /// <param name="hashfields"></param>
 397         /// <returns></returns>
 398         public async task<long> hashdeleteasync(string rediskey, ienumerable<string> hashfields)
 399         {
 400             rediskey = addkeyprefix(rediskey);
 401             var fields = hashfields.select(x => (redisvalue)x);
 402 
 403             return await _db.hashdeleteasync(rediskey, fields.toarray());
 404         }
 405 
 406         /// <summary>
 407         /// 在 hash 设定值
 408         /// </summary>
 409         /// <param name="rediskey"></param>
 410         /// <param name="hashfield"></param>
 411         /// <param name="value"></param>
 412         /// <returns></returns>
 413         public async task<bool> hashsetasync(string rediskey, string hashfield, string value)
 414         {
 415             rediskey = addkeyprefix(rediskey);
 416             return await _db.hashsetasync(rediskey, hashfield, value);
 417         }
 418 
 419         /// <summary>
 420         /// 在 hash 中设定值
 421         /// </summary>
 422         /// <param name="rediskey"></param>
 423         /// <param name="hashfields"></param>
 424         public async task hashsetasync(string rediskey, ienumerable<keyvaluepair<string, string>> hashfields)
 425         {
 426             rediskey = addkeyprefix(rediskey);
 427             var entries = hashfields.select(x => new hashentry(addkeyprefix(x.key), x.value));
 428             await _db.hashsetasync(rediskey, entries.toarray());
 429         }
 430 
 431         /// <summary>
 432         /// 在 hash 中获取值
 433         /// </summary>
 434         /// <param name="rediskey"></param>
 435         /// <param name="hashfield"></param>
 436         /// <returns></returns>
 437         public async task<string> hashgetasync(string rediskey, string hashfield)
 438         {
 439             rediskey = addkeyprefix(rediskey);
 440             return await _db.hashgetasync(rediskey, hashfield);
 441         }
 442 
 443         /// <summary>
 444         /// 在 hash 中获取值
 445         /// </summary>
 446         /// <param name="rediskey"></param>
 447         /// <param name="hashfields"></param>
 448         /// <param name="value"></param>
 449         /// <returns></returns>
 450         public async task<ienumerable<string>> hashgetasync(string rediskey, ienumerable<string> hashfields,
 451             string value)
 452         {
 453             rediskey = addkeyprefix(rediskey);
 454             var fields = hashfields.select(x => (redisvalue)x);
 455 
 456             return convertstrings(await _db.hashgetasync(rediskey, fields.toarray()));
 457         }
 458 
 459         /// <summary>
 460         /// 从 hash 返回所有的字段值
 461         /// </summary>
 462         /// <param name="rediskey"></param>
 463         /// <returns></returns>
 464         public async task<ienumerable<string>> hashkeysasync(string rediskey)
 465         {
 466             rediskey = addkeyprefix(rediskey);
 467             return convertstrings(await _db.hashkeysasync(rediskey));
 468         }
 469 
 470         /// <summary>
 471         /// 返回 hash 中的所有值
 472         /// </summary>
 473         /// <param name="rediskey"></param>
 474         /// <returns></returns>
 475         public async task<ienumerable<string>> hashvaluesasync(string rediskey)
 476         {
 477             rediskey = addkeyprefix(rediskey);
 478             return convertstrings(await _db.hashvaluesasync(rediskey));
 479         }
 480 
 481         /// <summary>
 482         /// 在 hash 设定值(序列化)
 483         /// </summary>
 484         /// <param name="rediskey"></param>
 485         /// <param name="hashfield"></param>
 486         /// <param name="value"></param>
 487         /// <returns></returns>
 488         public async task<bool> hashsetasync<t>(string rediskey, string hashfield, t value)
 489         {
 490             rediskey = addkeyprefix(rediskey);
 491             var json = serialize(value);
 492             return await _db.hashsetasync(rediskey, hashfield, json);
 493         }
 494 
 495         /// <summary>
 496         /// 在 hash 中获取值(反序列化)
 497         /// </summary>
 498         /// <param name="rediskey"></param>
 499         /// <param name="hashfield"></param>
 500         /// <returns></returns>
 501         public async task<t> hashgetasync<t>(string rediskey, string hashfield)
 502         {
 503             rediskey = addkeyprefix(rediskey);
 504             return deserialize<t>(await _db.hashgetasync(rediskey, hashfield));
 505         }
 506 
 507         #endregion async
 508 
 509         #endregion hash 操作
 510 
 511         #region list 操作
 512 
 513         /// <summary>
 514         /// 移除并返回存储在该键列表的第一个元素
 515         /// </summary>
 516         /// <param name="rediskey"></param>
 517         /// <returns></returns>
 518         public string listleftpop(string rediskey)
 519         {
 520             rediskey = addkeyprefix(rediskey);
 521             return _db.listleftpop(rediskey);
 522         }
 523 
 524         /// <summary>
 525         /// 移除并返回存储在该键列表的最后一个元素
 526         /// </summary>
 527         /// <param name="rediskey"></param>
 528         /// <returns></returns>
 529         public string listrightpop(string rediskey)
 530         {
 531             rediskey = addkeyprefix(rediskey);
 532             return _db.listrightpop(rediskey);
 533         }
 534 
 535         /// <summary>
 536         /// 移除列表指定键上与该值相同的元素
 537         /// </summary>
 538         /// <param name="rediskey"></param>
 539         /// <param name="redisvalue"></param>
 540         /// <returns></returns>
 541         public long listremove(string rediskey, string redisvalue)
 542         {
 543             rediskey = addkeyprefix(rediskey);
 544             return _db.listremove(rediskey, redisvalue);
 545         }
 546 
 547         /// <summary>
 548         /// 在列表尾部插入值。如果键不存在,先创建再插入值
 549         /// </summary>
 550         /// <param name="rediskey"></param>
 551         /// <param name="redisvalue"></param>
 552         /// <returns></returns>
 553         public long listrightpush(string rediskey, string redisvalue)
 554         {
 555             rediskey = addkeyprefix(rediskey);
 556             return _db.listrightpush(rediskey, redisvalue);
 557         }
 558 
 559         /// <summary>
 560         /// 在列表头部插入值。如果键不存在,先创建再插入值
 561         /// </summary>
 562         /// <param name="rediskey"></param>
 563         /// <param name="redisvalue"></param>
 564         /// <returns></returns>
 565         public long listleftpush(string rediskey, string redisvalue)
 566         {
 567             rediskey = addkeyprefix(rediskey);
 568             return _db.listleftpush(rediskey, redisvalue);
 569         }
 570 
 571         /// <summary>
 572         /// 返回列表上该键的长度,如果不存在,返回 0
 573         /// </summary>
 574         /// <param name="rediskey"></param>
 575         /// <returns></returns>
 576         public long listlength(string rediskey)
 577         {
 578             rediskey = addkeyprefix(rediskey);
 579             return _db.listlength(rediskey);
 580         }
 581 
 582         /// <summary>
 583         /// 返回在该列表上键所对应的元素
 584         /// </summary>
 585         /// <param name="rediskey"></param>
 586         /// <param name="start"></param>
 587         /// <param name="stop"></param>
 588         /// <returns></returns>
 589         public ienumerable<string> listrange(string rediskey, long start = 0l, long stop = -1l)
 590         {
 591             rediskey = addkeyprefix(rediskey);
 592             return convertstrings(_db.listrange(rediskey, start, stop));
 593         }
 594 
 595         /// <summary>
 596         /// 移除并返回存储在该键列表的第一个元素
 597         /// </summary>
 598         /// <param name="rediskey"></param>
 599         /// <returns></returns>
 600         public t listleftpop<t>(string rediskey)
 601         {
 602             rediskey = addkeyprefix(rediskey);
 603             return deserialize<t>(_db.listleftpop(rediskey));
 604         }
 605 
 606         /// <summary>
 607         /// 移除并返回存储在该键列表的最后一个元素
 608         /// </summary>
 609         /// <param name="rediskey"></param>
 610         /// <returns></returns>
 611         public t listrightpop<t>(string rediskey)
 612         {
 613             rediskey = addkeyprefix(rediskey);
 614             return deserialize<t>(_db.listrightpop(rediskey));
 615         }
 616 
 617         /// <summary>
 618         /// 在列表尾部插入值。如果键不存在,先创建再插入值
 619         /// </summary>
 620         /// <param name="rediskey"></param>
 621         /// <param name="redisvalue"></param>
 622         /// <returns></returns>
 623         public long listrightpush<t>(string rediskey, t redisvalue)
 624         {
 625             rediskey = addkeyprefix(rediskey);
 626             return _db.listrightpush(rediskey, serialize(redisvalue));
 627         }
 628 
 629         /// <summary>
 630         /// 在列表头部插入值。如果键不存在,先创建再插入值
 631         /// </summary>
 632         /// <param name="rediskey"></param>
 633         /// <param name="redisvalue"></param>
 634         /// <returns></returns>
 635         public long listleftpush<t>(string rediskey, t redisvalue)
 636         {
 637             rediskey = addkeyprefix(rediskey);
 638             return _db.listleftpush(rediskey, serialize(redisvalue));
 639         }
 640 
 641         #region list-async
 642 
 643         /// <summary>
 644         /// 移除并返回存储在该键列表的第一个元素
 645         /// </summary>
 646         /// <param name="rediskey"></param>
 647         /// <returns></returns>
 648         public async task<string> listleftpopasync(string rediskey)
 649         {
 650             rediskey = addkeyprefix(rediskey);
 651             return await _db.listleftpopasync(rediskey);
 652         }
 653 
 654         /// <summary>
 655         /// 移除并返回存储在该键列表的最后一个元素
 656         /// </summary>
 657         /// <param name="rediskey"></param>
 658         /// <returns></returns>
 659         public async task<string> listrightpopasync(string rediskey)
 660         {
 661             rediskey = addkeyprefix(rediskey);
 662             return await _db.listrightpopasync(rediskey);
 663         }
 664 
 665         /// <summary>
 666         /// 移除列表指定键上与该值相同的元素
 667         /// </summary>
 668         /// <param name="rediskey"></param>
 669         /// <param name="redisvalue"></param>
 670         /// <returns></returns>
 671         public async task<long> listremoveasync(string rediskey, string redisvalue)
 672         {
 673             rediskey = addkeyprefix(rediskey);
 674             return await _db.listremoveasync(rediskey, redisvalue);
 675         }
 676 
 677         /// <summary>
 678         /// 在列表尾部插入值。如果键不存在,先创建再插入值
 679         /// </summary>
 680         /// <param name="rediskey"></param>
 681         /// <param name="redisvalue"></param>
 682         /// <returns></returns>
 683         public async task<long> listrightpushasync(string rediskey, string redisvalue)
 684         {
 685             rediskey = addkeyprefix(rediskey);
 686             return await _db.listrightpushasync(rediskey, redisvalue);
 687         }
 688 
 689         /// <summary>
 690         /// 在列表头部插入值。如果键不存在,先创建再插入值
 691         /// </summary>
 692         /// <param name="rediskey"></param>
 693         /// <param name="redisvalue"></param>
 694         /// <returns></returns>
 695         public async task<long> listleftpushasync(string rediskey, string redisvalue)
 696         {
 697             rediskey = addkeyprefix(rediskey);
 698             return await _db.listleftpushasync(rediskey, redisvalue);
 699         }
 700 
 701         /// <summary>
 702         /// 返回列表上该键的长度,如果不存在,返回 0
 703         /// </summary>
 704         /// <param name="rediskey"></param>
 705         /// <returns></returns>
 706         public async task<long> listlengthasync(string rediskey)
 707         {
 708             rediskey = addkeyprefix(rediskey);
 709             return await _db.listlengthasync(rediskey);
 710         }
 711 
 712         /// <summary>
 713         /// 返回在该列表上键所对应的元素
 714         /// </summary>
 715         /// <param name="rediskey"></param>
 716         /// <param name="start"></param>
 717         /// <param name="stop"></param>
 718         /// <returns></returns>
 719         public async task<ienumerable<string>> listrangeasync(string rediskey, long start = 0l, long stop = -1l)
 720         {
 721             rediskey = addkeyprefix(rediskey);
 722             var query = await _db.listrangeasync(rediskey, start, stop);
 723             return query.select(x => x.tostring());
 724         }
 725 
 726         /// <summary>
 727         /// 移除并返回存储在该键列表的第一个元素
 728         /// </summary>
 729         /// <param name="rediskey"></param>
 730         /// <returns></returns>
 731         public async task<t> listleftpopasync<t>(string rediskey)
 732         {
 733             rediskey = addkeyprefix(rediskey);
 734             return deserialize<t>(await _db.listleftpopasync(rediskey));
 735         }
 736 
 737         /// <summary>
 738         /// 移除并返回存储在该键列表的最后一个元素
 739         /// </summary>
 740         /// <param name="rediskey"></param>
 741         /// <returns></returns>
 742         public async task<t> listrightpopasync<t>(string rediskey)
 743         {
 744             rediskey = addkeyprefix(rediskey);
 745             return deserialize<t>(await _db.listrightpopasync(rediskey));
 746         }
 747 
 748         /// <summary>
 749         /// 在列表尾部插入值。如果键不存在,先创建再插入值
 750         /// </summary>
 751         /// <param name="rediskey"></param>
 752         /// <param name="redisvalue"></param>
 753         /// <returns></returns>
 754         public async task<long> listrightpushasync<t>(string rediskey, t redisvalue)
 755         {
 756             rediskey = addkeyprefix(rediskey);
 757             return await _db.listrightpushasync(rediskey, serialize(redisvalue));
 758         }
 759 
 760         /// <summary>
 761         /// 在列表头部插入值。如果键不存在,先创建再插入值
 762         /// </summary>
 763         /// <param name="rediskey"></param>
 764         /// <param name="redisvalue"></param>
 765         /// <returns></returns>
 766         public async task<long> listleftpushasync<t>(string rediskey, t redisvalue)
 767         {
 768             rediskey = addkeyprefix(rediskey);
 769             return await _db.listleftpushasync(rediskey, serialize(redisvalue));
 770         }
 771 
 772         #endregion list-async
 773 
 774         #endregion list 操作
 775 
 776         #region sortedset 操作
 777 
 778         /// <summary>
 779         /// sortedset 新增
 780         /// </summary>
 781         /// <param name="rediskey"></param>
 782         /// <param name="member"></param>
 783         /// <param name="score"></param>
 784         /// <returns></returns>
 785         public bool sortedsetadd(string rediskey, string member, double score)
 786         {
 787             rediskey = addkeyprefix(rediskey);
 788             return _db.sortedsetadd(rediskey, member, score);
 789         }
 790 
 791         /// <summary>
 792         /// 在有序集合中返回指定范围的元素,默认情况下从低到高。
 793         /// </summary>
 794         /// <param name="rediskey"></param>
 795         /// <param name="start"></param>
 796         /// <param name="stop"></param>
 797         /// <param name="order"></param>
 798         /// <returns></returns>
 799         public ienumerable<string> sortedsetrangebyrank(string rediskey, long start = 0l, long stop = -1l,
 800             order order = order.ascending)
 801         {
 802             rediskey = addkeyprefix(rediskey);
 803             return _db.sortedsetrangebyrank(rediskey, start, stop, (order)order).select(x => x.tostring());
 804         }
 805 
 806         /// <summary>
 807         /// 返回有序集合的元素个数
 808         /// </summary>
 809         /// <param name="rediskey"></param>
 810         /// <returns></returns>
 811         public long sortedsetlength(string rediskey)
 812         {
 813             rediskey = addkeyprefix(rediskey);
 814             return _db.sortedsetlength(rediskey);
 815         }
 816 
 817         /// <summary>
 818         /// 返回有序集合的元素个数
 819         /// </summary>
 820         /// <param name="rediskey"></param>
 821         /// <param name="memebr"></param>
 822         /// <returns></returns>
 823         public bool sortedsetlength(string rediskey, string memebr)
 824         {
 825             rediskey = addkeyprefix(rediskey);
 826             return _db.sortedsetremove(rediskey, memebr);
 827         }
 828 
 829         /// <summary>
 830         /// sortedset 新增
 831         /// </summary>
 832         /// <param name="rediskey"></param>
 833         /// <param name="member"></param>
 834         /// <param name="score"></param>
 835         /// <returns></returns>
 836         public bool sortedsetadd<t>(string rediskey, t member, double score)
 837         {
 838             rediskey = addkeyprefix(rediskey);
 839             var json = serialize(member);
 840 
 841             return _db.sortedsetadd(rediskey, json, score);
 842         }
 843 
 844         /// <summary>
 845         /// 增量的得分排序的集合中的成员存储键值键按增量
 846         /// </summary>
 847         /// <param name="rediskey"></param>
 848         /// <param name="member"></param>
 849         /// <param name="value"></param>
 850         /// <returns></returns>
 851         public double sortedsetincrement(string rediskey, string member, double value = 1)
 852         {
 853             rediskey = addkeyprefix(rediskey);
 854             return _db.sortedsetincrement(rediskey, member, value);
 855         }
 856 
 857         #region sortedset-async
 858 
 859         /// <summary>
 860         /// sortedset 新增
 861         /// </summary>
 862         /// <param name="rediskey"></param>
 863         /// <param name="member"></param>
 864         /// <param name="score"></param>
 865         /// <returns></returns>
 866         public async task<bool> sortedsetaddasync(string rediskey, string member, double score)
 867         {
 868             rediskey = addkeyprefix(rediskey);
 869             return await _db.sortedsetaddasync(rediskey, member, score);
 870         }
 871 
 872         /// <summary>
 873         /// 在有序集合中返回指定范围的元素,默认情况下从低到高。
 874         /// </summary>
 875         /// <param name="rediskey"></param>
 876         /// <returns></returns>
 877         public async task<ienumerable<string>> sortedsetrangebyrankasync(string rediskey)
 878         {
 879             rediskey = addkeyprefix(rediskey);
 880             return convertstrings(await _db.sortedsetrangebyrankasync(rediskey));
 881         }
 882 
 883         /// <summary>
 884         /// 返回有序集合的元素个数
 885         /// </summary>
 886         /// <param name="rediskey"></param>
 887         /// <returns></returns>
 888         public async task<long> sortedsetlengthasync(string rediskey)
 889         {
 890             rediskey = addkeyprefix(rediskey);
 891             return await _db.sortedsetlengthasync(rediskey);
 892         }
 893 
 894         /// <summary>
 895         /// 返回有序集合的元素个数
 896         /// </summary>
 897         /// <param name="rediskey"></param>
 898         /// <param name="memebr"></param>
 899         /// <returns></returns>
 900         public async task<bool> sortedsetremoveasync(string rediskey, string memebr)
 901         {
 902             rediskey = addkeyprefix(rediskey);
 903             return await _db.sortedsetremoveasync(rediskey, memebr);
 904         }
 905 
 906         /// <summary>
 907         /// sortedset 新增
 908         /// </summary>
 909         /// <param name="rediskey"></param>
 910         /// <param name="member"></param>
 911         /// <param name="score"></param>
 912         /// <returns></returns>
 913         public async task<bool> sortedsetaddasync<t>(string rediskey, t member, double score)
 914         {
 915             rediskey = addkeyprefix(rediskey);
 916             var json = serialize(member);
 917 
 918             return await _db.sortedsetaddasync(rediskey, json, score);
 919         }
 920 
 921         /// <summary>
 922         /// 增量的得分排序的集合中的成员存储键值键按增量
 923         /// </summary>
 924         /// <param name="rediskey"></param>
 925         /// <param name="member"></param>
 926         /// <param name="value"></param>
 927         /// <returns></returns>
 928         public task<double> sortedsetincrementasync(string rediskey, string member, double value = 1)
 929         {
 930             rediskey = addkeyprefix(rediskey);
 931             return _db.sortedsetincrementasync(rediskey, member, value);
 932         }
 933 
 934         #endregion sortedset-async
 935 
 936         #endregion sortedset 操作
 937 
 938         #endregion 类型封装
 939 
 940         #region 将object序列化读写
 941         public void listset<t>(string key, list<t> value)
 942         {
 943             foreach (var single in value)
 944             {
 945                 var jsonobj = jsonconvert.serializeobject(single); //序列化
 946                 this.listleftpush(key, jsonobj); //要一个个的插入
 947                 
 948             }
 949         }
 950         public list<t> listget<t>(string key)
 951         {
 952             var jsonarr = this.listrange(key);
 953             list<t> result = new list<t>();
 954             foreach (var item in jsonarr)
 955             {
 956                 var model = jsonconvert.deserializeobject<t>(item); //反序列化
 957                 result.add(model);
 958             }
 959             return result;
 960         }
 961         #endregion
 962 
 963         #region key 操作
 964 
 965         /// <summary>
 966         /// 删除单个key
 967         /// </summary>
 968         /// <param name="rediskey"></param>
 969         /// <returns>是否删除成功</returns>
 970         public bool keydelete(string rediskey)
 971         {
 972             rediskey = addkeyprefix(rediskey);
 973             return _db.keydelete(rediskey);
 974         }
 975 
 976         /// <summary>
 977         /// 删除多个key
 978         /// </summary>
 979         /// <param name="rediskeys"></param>
 980         /// <returns>成功删除的个数</returns>
 981         public long keydelete(ienumerable<string> rediskeys)
 982         {
 983             var keys = rediskeys.select(x => (rediskey)addkeyprefix(x));
 984             return _db.keydelete(keys.toarray());
 985         }
 986 
 987         /// <summary>
 988         /// 校验 key 是否存在
 989         /// </summary>
 990         /// <param name="rediskey"></param>
 991         /// <returns></returns>
 992         public bool keyexists(string rediskey)
 993         {
 994             rediskey = addkeyprefix(rediskey);
 995             return _db.keyexists(rediskey);
 996         }
 997 
 998         /// <summary>
 999         /// 重命名 key
1000         /// </summary>
1001         /// <param name="rediskey"></param>
1002         /// <param name="redisnewkey"></param>
1003         /// <returns></returns>
1004         public bool keyrename(string rediskey, string redisnewkey)
1005         {
1006             rediskey = addkeyprefix(rediskey);
1007             return _db.keyrename(rediskey, redisnewkey);
1008         }
1009 
1010         /// <summary>
1011         /// 设置 key 的时间
1012         /// </summary>
1013         /// <param name="rediskey"></param>
1014         /// <param name="expiry"></param>
1015         /// <returns></returns>
1016         public bool keyexpire(string rediskey, timespan? expiry)
1017         {
1018             rediskey = addkeyprefix(rediskey);
1019             return _db.keyexpire(rediskey, expiry);
1020         }

                    

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网