zoukankan      html  css  js  c++  java
  • Windows下Redis哨兵模式配置以及在.NetCore中使用StackExchange.Redis连接哨兵

    一,Redis哨兵模式配置

    1,下载Redis,然后解压复制5个文件夹分别如下命名。

     2,哨兵模式配置

    (1)修改主节点Redis-6379中redis.windows.conf配置文件如下

      

       

    (2)修改从节点Redis-6380中redis.windows.conf配置文件如下

       

       

     (3)配置哨兵,在哨兵文件夹下添加Sentinel.conf配置文件

       

      a,哨兵Redis-26379配置如下

      

       其他哨兵节点修改26379端口即可。

     二,Redis帮助类封装(StackExchange.Redis)

      项目文件结构如下:

      

       1,RedisHelper.cs

       1 using Microsoft.Extensions.Configuration;
       2 using StackExchange.Redis;
       3 using System;
       4 using System.Collections.Generic;
       5 using System.IO;
       6 using System.Linq;
       7 using System.Runtime.Serialization.Formatters.Binary;
       8 using System.Threading.Tasks;
       9 
      10 namespace MS.Quality.Component.Cache.Redis
      11 {
      12     /// <summary>
      13     /// Redis 助手
      14     /// </summary>
      15     public class RedisHelper
      16     {
      17         /// <summary>
      18         /// 连接字符串
      19         /// </summary>
      20         private static readonly string ConnectionString;
      21 
      22         /// <summary>
      23         /// redis 连接对象
      24         /// </summary>
      25         private static IConnectionMultiplexer _connMultiplexer;
      26 
      27         /// <summary>
      28         /// 默认的 Key 值(用来当作 RedisKey 的前缀)
      29         /// </summary>
      30         private static readonly string DefaultKey;
      31 
      32         /// <summary>
      33         ///  34         /// </summary>
      35         private static readonly object Locker = new object();
      36 
      37         /// <summary>
      38         /// 数据库
      39         /// </summary>
      40         private readonly IDatabase _db;
      41 
      42         /// <summary>
      43         /// 获取 Redis 连接对象
      44         /// </summary>
      45         /// <returns></returns>
      46         public IConnectionMultiplexer GetConnectionRedisMultiplexer()
      47         {
      48             if ((_connMultiplexer == null) || !_connMultiplexer.IsConnected)
      49             {
      50                 lock (Locker)
      51                 {
      52                     if ((_connMultiplexer == null) || !_connMultiplexer.IsConnected)
      53                         _connMultiplexer = ConnectionMultiplexer.Connect(ConnectionString);
      54                 }
      55             }
      56 
      57             return _connMultiplexer;
      58         }
      59 
      60         #region 其它
      61 
      62         public ITransaction GetTransaction()
      63         {
      64             return _db.CreateTransaction();
      65         }
      66 
      67         #endregion 其它
      68 
      69         #region 构造函数
      70 
      71         static RedisHelper()
      72         {
      73             var builder = new ConfigurationBuilder()
      74                .SetBasePath(Directory.GetCurrentDirectory())
      75                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
      76             IConfigurationRoot configuration = builder.Build();
      77             if (configuration.GetSection("Redis:Sentinel").Exists())
      78             {
      79                 ConfigurationOptions sentinelOptions = new ConfigurationOptions();
      80                 var IpArray = configuration.GetSection("Redis:Sentinel").GetChildren();
      81                 foreach (var item in IpArray)
      82                 {
      83                     sentinelOptions.EndPoints.Add(item.Value);
      84                 }
      85                 sentinelOptions.TieBreaker = "";
      86                 sentinelOptions.CommandMap = CommandMap.Sentinel;
      87                 sentinelOptions.AbortOnConnectFail = true;
      88                 // Connect!
      89                 ConnectionMultiplexer sentinelConnection = ConnectionMultiplexer.Connect(sentinelOptions);
      90 
      91                 // Get a connection to the master
      92                 ConfigurationOptions redisServiceOptions = new ConfigurationOptions();
      93                 redisServiceOptions.ServiceName = configuration.GetSection("Redis:ServiceName").Value;   //master名称
      94                 redisServiceOptions.Password = configuration.GetSection("Redis:Password").Value;     //master访问密码
      95                 redisServiceOptions.AbortOnConnectFail = true;
      96                 redisServiceOptions.AllowAdmin = true;
      97                 _connMultiplexer = sentinelConnection.GetSentinelMasterConnection(redisServiceOptions);
      98             }
      99             else
     100             {
     101                 ConnectionString = configuration.GetSection("Redis:ConnectionStrings").Value;
     102                 _connMultiplexer = ConnectionMultiplexer.Connect(ConnectionString);
     103             }
     104             DefaultKey = configuration.GetSection("Redis:DefaultKey").Value;
     105 
     106             AddRegisterEvent();
     107         }
     108 
     109         public RedisHelper(int db = -1)
     110         {
     111             _db = _connMultiplexer.GetDatabase(db);
     112         }
     113 
     114         #endregion 构造函数
     115 
     116         #region String 操作
     117 
     118         /// <summary>
     119         /// 设置 key 并保存字符串(如果 key 已存在,则覆盖值)
     120         /// </summary>
     121         /// <param name="redisKey"></param>
     122         /// <param name="redisValue"></param>
     123         /// <param name="expiry"></param>
     124         /// <returns></returns>
     125         public bool StringSet(string redisKey, string redisValue, TimeSpan? expiry = null)
     126         {
     127             redisKey = AddKeyPrefix(redisKey);
     128             return _db.StringSet(redisKey, redisValue, expiry);
     129         }
     130 
     131         /// <summary>
     132         /// 保存多个 Key-value
     133         /// </summary>
     134         /// <param name="keyValuePairs"></param>
     135         /// <returns></returns>
     136         public bool StringSet(IEnumerable<KeyValuePair<RedisKey, RedisValue>> keyValuePairs)
     137         {
     138             keyValuePairs =
     139                 keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(AddKeyPrefix(x.Key), x.Value));
     140             return _db.StringSet(keyValuePairs.ToArray());
     141         }
     142 
     143         /// <summary>
     144         /// 获取字符串
     145         /// </summary>
     146         /// <param name="redisKey"></param>
     147         /// <param name="expiry"></param>
     148         /// <returns></returns>
     149         public string StringGet(string redisKey, TimeSpan? expiry = null)
     150         {
     151             redisKey = AddKeyPrefix(redisKey);
     152             return _db.StringGet(redisKey);
     153         }
     154 
     155         /// <summary>
     156         /// 存储一个对象(该对象会被序列化保存)
     157         /// </summary>
     158         /// <param name="redisKey"></param>
     159         /// <param name="redisValue"></param>
     160         /// <param name="expiry"></param>
     161         /// <returns></returns>
     162         public bool StringSet<T>(string redisKey, T redisValue, TimeSpan? expiry = null)
     163         {
     164             redisKey = AddKeyPrefix(redisKey);
     165             var json = Serialize(redisValue);
     166             return _db.StringSet(redisKey, json, expiry);
     167         }
     168 
     169         /// <summary>
     170         /// 获取一个对象(会进行反序列化)
     171         /// </summary>
     172         /// <param name="redisKey"></param>
     173         /// <param name="expiry"></param>
     174         /// <returns></returns>
     175         public T StringGet<T>(string redisKey, TimeSpan? expiry = null)
     176         {
     177             redisKey = AddKeyPrefix(redisKey);
     178             return Deserialize<T>(_db.StringGet(redisKey));
     179         }
     180 
     181         #region async
     182 
     183         /// <summary>
     184         /// 保存一个字符串值
     185         /// </summary>
     186         /// <param name="redisKey"></param>
     187         /// <param name="redisValue"></param>
     188         /// <param name="expiry"></param>
     189         /// <returns></returns>
     190         public async Task<bool> StringSetAsync(string redisKey, string redisValue, TimeSpan? expiry = null)
     191         {
     192             redisKey = AddKeyPrefix(redisKey);
     193             return await _db.StringSetAsync(redisKey, redisValue, expiry);
     194         }
     195 
     196         /// <summary>
     197         /// 保存一组字符串值
     198         /// </summary>
     199         /// <param name="keyValuePairs"></param>
     200         /// <returns></returns>
     201         public async Task<bool> StringSetAsync(IEnumerable<KeyValuePair<RedisKey, RedisValue>> keyValuePairs)
     202         {
     203             keyValuePairs =
     204                 keyValuePairs.Select(x => new KeyValuePair<RedisKey, RedisValue>(AddKeyPrefix(x.Key), x.Value));
     205             return await _db.StringSetAsync(keyValuePairs.ToArray());
     206         }
     207 
     208         /// <summary>
     209         /// 获取单个值
     210         /// </summary>
     211         /// <param name="redisKey"></param>
     212         /// <param name="redisValue"></param>
     213         /// <param name="expiry"></param>
     214         /// <returns></returns>
     215         public async Task<string> StringGetAsync(string redisKey, string redisValue, TimeSpan? expiry = null)
     216         {
     217             redisKey = AddKeyPrefix(redisKey);
     218             return await _db.StringGetAsync(redisKey);
     219         }
     220 
     221         /// <summary>
     222         /// 存储一个对象(该对象会被序列化保存)
     223         /// </summary>
     224         /// <param name="redisKey"></param>
     225         /// <param name="redisValue"></param>
     226         /// <param name="expiry"></param>
     227         /// <returns></returns>
     228         public async Task<bool> StringSetAsync<T>(string redisKey, T redisValue, TimeSpan? expiry = null)
     229         {
     230             redisKey = AddKeyPrefix(redisKey);
     231             var json = Serialize(redisValue);
     232             return await _db.StringSetAsync(redisKey, json, expiry);
     233         }
     234 
     235         /// <summary>
     236         /// 获取一个对象(会进行反序列化)
     237         /// </summary>
     238         /// <param name="redisKey"></param>
     239         /// <param name="expiry"></param>
     240         /// <returns></returns>
     241         public async Task<T> StringGetAsync<T>(string redisKey, TimeSpan? expiry = null)
     242         {
     243             redisKey = AddKeyPrefix(redisKey);
     244             return Deserialize<T>(await _db.StringGetAsync(redisKey));
     245         }
     246 
     247         #endregion async
     248 
     249         #endregion String 操作
     250 
     251         #region Hash 操作
     252 
     253         /// <summary>
     254         /// 判断该字段是否存在 hash 中
     255         /// </summary>
     256         /// <param name="redisKey"></param>
     257         /// <param name="hashField"></param>
     258         /// <returns></returns>
     259         public bool HashExists(string redisKey, string hashField)
     260         {
     261             redisKey = AddKeyPrefix(redisKey);
     262             return _db.HashExists(redisKey, hashField);
     263         }
     264 
     265         /// <summary>
     266         /// 从 hash 中移除指定字段
     267         /// </summary>
     268         /// <param name="redisKey"></param>
     269         /// <param name="hashField"></param>
     270         /// <returns></returns>
     271         public bool HashDelete(string redisKey, string hashField)
     272         {
     273             redisKey = AddKeyPrefix(redisKey);
     274             return _db.HashDelete(redisKey, hashField);
     275         }
     276 
     277         /// <summary>
     278         /// 从 hash 中移除指定字段
     279         /// </summary>
     280         /// <param name="redisKey"></param>
     281         /// <param name="hashField"></param>
     282         /// <returns></returns>
     283         public long HashDelete(string redisKey, IEnumerable<RedisValue> hashField)
     284         {
     285             redisKey = AddKeyPrefix(redisKey);
     286             return _db.HashDelete(redisKey, hashField.ToArray());
     287         }
     288 
     289         /// <summary>
     290         /// 在 hash 设定值
     291         /// </summary>
     292         /// <param name="redisKey"></param>
     293         /// <param name="hashField"></param>
     294         /// <param name="value"></param>
     295         /// <returns></returns>
     296         public bool HashSet(string redisKey, string hashField, string value)
     297         {
     298             redisKey = AddKeyPrefix(redisKey);
     299             return _db.HashSet(redisKey, hashField, value);
     300         }
     301 
     302         /// <summary>
     303         /// 在 hash 中设定值
     304         /// </summary>
     305         /// <param name="redisKey"></param>
     306         /// <param name="hashFields"></param>
     307         public void HashSet(string redisKey, IEnumerable<HashEntry> hashFields)
     308         {
     309             redisKey = AddKeyPrefix(redisKey);
     310             _db.HashSet(redisKey, hashFields.ToArray());
     311         }
     312 
     313         /// <summary>
     314         /// 在 hash 中获取值
     315         /// </summary>
     316         /// <param name="redisKey"></param>
     317         /// <param name="hashField"></param>
     318         /// <returns></returns>
     319         public RedisValue HashGet(string redisKey, string hashField)
     320         {
     321             redisKey = AddKeyPrefix(redisKey);
     322             return _db.HashGet(redisKey, hashField);
     323         }
     324 
     325         /// <summary>
     326         /// 在 hash 中获取值
     327         /// </summary>
     328         /// <param name="redisKey"></param>
     329         /// <param name="hashField"></param>
     330         /// <param name="value"></param>
     331         /// <returns></returns>
     332         public RedisValue[] HashGet(string redisKey, RedisValue[] hashField, string value)
     333         {
     334             redisKey = AddKeyPrefix(redisKey);
     335             return _db.HashGet(redisKey, hashField);
     336         }
     337 
     338         /// <summary>
     339         /// 从 hash 返回所有的字段值
     340         /// </summary>
     341         /// <param name="redisKey"></param>
     342         /// <returns></returns>
     343         public IEnumerable<RedisValue> HashKeys(string redisKey)
     344         {
     345             redisKey = AddKeyPrefix(redisKey);
     346             return _db.HashKeys(redisKey);
     347         }
     348 
     349         /// <summary>
     350         /// 返回 hash 中的所有值
     351         /// </summary>
     352         /// <param name="redisKey"></param>
     353         /// <returns></returns>
     354         public RedisValue[] HashValues(string redisKey)
     355         {
     356             redisKey = AddKeyPrefix(redisKey);
     357             return _db.HashValues(redisKey);
     358         }
     359 
     360         /// <summary>
     361         /// 在 hash 设定值(序列化)
     362         /// </summary>
     363         /// <param name="redisKey"></param>
     364         /// <param name="hashField"></param>
     365         /// <param name="value"></param>
     366         /// <returns></returns>
     367         public bool HashSet<T>(string redisKey, string hashField, T value)
     368         {
     369             redisKey = AddKeyPrefix(redisKey);
     370             var json = Serialize(value);
     371             return _db.HashSet(redisKey, hashField, json);
     372         }
     373 
     374         /// <summary>
     375         /// 在 hash 中获取值(反序列化)
     376         /// </summary>
     377         /// <param name="redisKey"></param>
     378         /// <param name="hashField"></param>
     379         /// <returns></returns>
     380         public T HashGet<T>(string redisKey, string hashField)
     381         {
     382             redisKey = AddKeyPrefix(redisKey);
     383             return Deserialize<T>(_db.HashGet(redisKey, hashField));
     384         }
     385 
     386         #region async
     387 
     388         /// <summary>
     389         /// 判断该字段是否存在 hash 中
     390         /// </summary>
     391         /// <param name="redisKey"></param>
     392         /// <param name="hashField"></param>
     393         /// <returns></returns>
     394         public async Task<bool> HashExistsAsync(string redisKey, string hashField)
     395         {
     396             redisKey = AddKeyPrefix(redisKey);
     397             return await _db.HashExistsAsync(redisKey, hashField);
     398         }
     399 
     400         /// <summary>
     401         /// 从 hash 中移除指定字段
     402         /// </summary>
     403         /// <param name="redisKey"></param>
     404         /// <param name="hashField"></param>
     405         /// <returns></returns>
     406         public async Task<bool> HashDeleteAsync(string redisKey, string hashField)
     407         {
     408             redisKey = AddKeyPrefix(redisKey);
     409             return await _db.HashDeleteAsync(redisKey, hashField);
     410         }
     411 
     412         /// <summary>
     413         /// 从 hash 中移除指定字段
     414         /// </summary>
     415         /// <param name="redisKey"></param>
     416         /// <param name="hashField"></param>
     417         /// <returns></returns>
     418         public async Task<long> HashDeleteAsync(string redisKey, IEnumerable<RedisValue> hashField)
     419         {
     420             redisKey = AddKeyPrefix(redisKey);
     421             return await _db.HashDeleteAsync(redisKey, hashField.ToArray());
     422         }
     423 
     424         /// <summary>
     425         /// 在 hash 设定值
     426         /// </summary>
     427         /// <param name="redisKey"></param>
     428         /// <param name="hashField"></param>
     429         /// <param name="value"></param>
     430         /// <returns></returns>
     431         public async Task<bool> HashSetAsync(string redisKey, string hashField, string value)
     432         {
     433             redisKey = AddKeyPrefix(redisKey);
     434             return await _db.HashSetAsync(redisKey, hashField, value);
     435         }
     436 
     437         /// <summary>
     438         /// 在 hash 中设定值
     439         /// </summary>
     440         /// <param name="redisKey"></param>
     441         /// <param name="hashFields"></param>
     442         public async Task HashSetAsync(string redisKey, IEnumerable<HashEntry> hashFields)
     443         {
     444             redisKey = AddKeyPrefix(redisKey);
     445             await _db.HashSetAsync(redisKey, hashFields.ToArray());
     446         }
     447 
     448         /// <summary>
     449         /// 在 hash 中获取值
     450         /// </summary>
     451         /// <param name="redisKey"></param>
     452         /// <param name="hashField"></param>
     453         /// <returns></returns>
     454         public async Task<RedisValue> HashGetAsync(string redisKey, string hashField)
     455         {
     456             redisKey = AddKeyPrefix(redisKey);
     457             return await _db.HashGetAsync(redisKey, hashField);
     458         }
     459 
     460         /// <summary>
     461         /// 在 hash 中获取值
     462         /// </summary>
     463         /// <param name="redisKey"></param>
     464         /// <param name="hashField"></param>
     465         /// <param name="value"></param>
     466         /// <returns></returns>
     467         public async Task<IEnumerable<RedisValue>> HashGetAsync(string redisKey, RedisValue[] hashField, string value)
     468         {
     469             redisKey = AddKeyPrefix(redisKey);
     470             return await _db.HashGetAsync(redisKey, hashField);
     471         }
     472 
     473         /// <summary>
     474         /// 从 hash 返回所有的字段值
     475         /// </summary>
     476         /// <param name="redisKey"></param>
     477         /// <returns></returns>
     478         public async Task<IEnumerable<RedisValue>> HashKeysAsync(string redisKey)
     479         {
     480             redisKey = AddKeyPrefix(redisKey);
     481             return await _db.HashKeysAsync(redisKey);
     482         }
     483 
     484         /// <summary>
     485         /// 返回 hash 中的所有值
     486         /// </summary>
     487         /// <param name="redisKey"></param>
     488         /// <returns></returns>
     489         public async Task<IEnumerable<RedisValue>> HashValuesAsync(string redisKey)
     490         {
     491             redisKey = AddKeyPrefix(redisKey);
     492             return await _db.HashValuesAsync(redisKey);
     493         }
     494 
     495         /// <summary>
     496         /// 在 hash 设定值(序列化)
     497         /// </summary>
     498         /// <param name="redisKey"></param>
     499         /// <param name="hashField"></param>
     500         /// <param name="value"></param>
     501         /// <returns></returns>
     502         public async Task<bool> HashSetAsync<T>(string redisKey, string hashField, T value)
     503         {
     504             redisKey = AddKeyPrefix(redisKey);
     505             var json = Serialize(value);
     506             return await _db.HashSetAsync(redisKey, hashField, json);
     507         }
     508 
     509         /// <summary>
     510         /// 在 hash 中获取值(反序列化)
     511         /// </summary>
     512         /// <param name="redisKey"></param>
     513         /// <param name="hashField"></param>
     514         /// <returns></returns>
     515         public async Task<T> HashGetAsync<T>(string redisKey, string hashField)
     516         {
     517             redisKey = AddKeyPrefix(redisKey);
     518             return Deserialize<T>(await _db.HashGetAsync(redisKey, hashField));
     519         }
     520 
     521         #endregion async
     522 
     523         /// <summary>
     524         /// 在 hash 中获取值(反序列化)
     525         /// </summary>
     526         /// <param name="redisKey"></param>
     527         /// <param name="hashField"></param>
     528         /// <returns></returns>
     529         public HashEntry[] HashGetAll(string redisKey)
     530         {
     531             redisKey = AddKeyPrefix(redisKey);
     532             return _db.HashGetAll(redisKey);
     533         }
     534 
     535         #endregion Hash 操作
     536 
     537         #region List 操作
     538 
     539         /// <summary>
     540         /// 移除并返回存储在该键列表的第一个元素
     541         /// </summary>
     542         /// <param name="redisKey"></param>
     543         /// <returns></returns>
     544         public string ListLeftPop(string redisKey)
     545         {
     546             redisKey = AddKeyPrefix(redisKey);
     547             return _db.ListLeftPop(redisKey);
     548         }
     549 
     550         /// <summary>
     551         /// 移除并返回存储在该键列表的最后一个元素
     552         /// </summary>
     553         /// <param name="redisKey"></param>
     554         /// <returns></returns>
     555         public string ListRightPop(string redisKey)
     556         {
     557             redisKey = AddKeyPrefix(redisKey);
     558             return _db.ListRightPop(redisKey);
     559         }
     560 
     561         /// <summary>
     562         /// 移除列表指定键上与该值相同的元素
     563         /// </summary>
     564         /// <param name="redisKey"></param>
     565         /// <param name="redisValue"></param>
     566         /// <returns></returns>
     567         public long ListRemove(string redisKey, string redisValue)
     568         {
     569             redisKey = AddKeyPrefix(redisKey);
     570             return _db.ListRemove(redisKey, redisValue);
     571         }
     572 
     573         /// <summary>
     574         /// 在列表尾部插入值。如果键不存在,先创建再插入值
     575         /// </summary>
     576         /// <param name="redisKey"></param>
     577         /// <param name="redisValue"></param>
     578         /// <returns></returns>
     579         public long ListRightPush(string redisKey, string redisValue)
     580         {
     581             redisKey = AddKeyPrefix(redisKey);
     582             return _db.ListRightPush(redisKey, redisValue);
     583         }
     584 
     585         /// <summary>
     586         /// 在列表头部插入值。如果键不存在,先创建再插入值
     587         /// </summary>
     588         /// <param name="redisKey"></param>
     589         /// <param name="redisValue"></param>
     590         /// <returns></returns>
     591         public long ListLeftPush(string redisKey, string redisValue)
     592         {
     593             redisKey = AddKeyPrefix(redisKey);
     594             return _db.ListLeftPush(redisKey, redisValue);
     595         }
     596 
     597         /// <summary>
     598         /// 返回列表上该键的长度,如果不存在,返回 0
     599         /// </summary>
     600         /// <param name="redisKey"></param>
     601         /// <returns></returns>
     602         public long ListLength(string redisKey)
     603         {
     604             redisKey = AddKeyPrefix(redisKey);
     605             return _db.ListLength(redisKey);
     606         }
     607 
     608         /// <summary>
     609         /// 返回在该列表上键所对应的元素
     610         /// </summary>
     611         /// <param name="redisKey"></param>
     612         /// <returns></returns>
     613         public IEnumerable<RedisValue> ListRange(string redisKey)
     614         {
     615             redisKey = AddKeyPrefix(redisKey);
     616             return _db.ListRange(redisKey);
     617         }
     618 
     619         /// <summary>
     620         /// 移除并返回存储在该键列表的第一个元素
     621         /// </summary>
     622         /// <param name="redisKey"></param>
     623         /// <returns></returns>
     624         public T ListLeftPop<T>(string redisKey)
     625         {
     626             redisKey = AddKeyPrefix(redisKey);
     627             return Deserialize<T>(_db.ListLeftPop(redisKey));
     628         }
     629 
     630         /// <summary>
     631         /// 移除并返回存储在该键列表的最后一个元素
     632         /// </summary>
     633         /// <param name="redisKey"></param>
     634         /// <returns></returns>
     635         public T ListRightPop<T>(string redisKey)
     636         {
     637             redisKey = AddKeyPrefix(redisKey);
     638             return Deserialize<T>(_db.ListRightPop(redisKey));
     639         }
     640 
     641         /// <summary>
     642         /// 在列表尾部插入值。如果键不存在,先创建再插入值
     643         /// </summary>
     644         /// <param name="redisKey"></param>
     645         /// <param name="redisValue"></param>
     646         /// <returns></returns>
     647         public long ListRightPush<T>(string redisKey, T redisValue)
     648         {
     649             redisKey = AddKeyPrefix(redisKey);
     650             return _db.ListRightPush(redisKey, Serialize(redisValue));
     651         }
     652 
     653         /// <summary>
     654         /// 在列表头部插入值。如果键不存在,先创建再插入值
     655         /// </summary>
     656         /// <param name="redisKey"></param>
     657         /// <param name="redisValue"></param>
     658         /// <returns></returns>
     659         public long ListLeftPush<T>(string redisKey, T redisValue)
     660         {
     661             redisKey = AddKeyPrefix(redisKey);
     662             return _db.ListLeftPush(redisKey, Serialize(redisValue));
     663         }
     664 
     665         #region List-async
     666 
     667         /// <summary>
     668         /// 移除并返回存储在该键列表的第一个元素
     669         /// </summary>
     670         /// <param name="redisKey"></param>
     671         /// <returns></returns>
     672         public async Task<string> ListLeftPopAsync(string redisKey)
     673         {
     674             redisKey = AddKeyPrefix(redisKey);
     675             return await _db.ListLeftPopAsync(redisKey);
     676         }
     677 
     678         /// <summary>
     679         /// 移除并返回存储在该键列表的最后一个元素
     680         /// </summary>
     681         /// <param name="redisKey"></param>
     682         /// <returns></returns>
     683         public async Task<string> ListRightPopAsync(string redisKey)
     684         {
     685             redisKey = AddKeyPrefix(redisKey);
     686             return await _db.ListRightPopAsync(redisKey);
     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> ListRemoveAsync(string redisKey, string redisValue)
     696         {
     697             redisKey = AddKeyPrefix(redisKey);
     698             return await _db.ListRemoveAsync(redisKey, redisValue);
     699         }
     700 
     701         /// <summary>
     702         /// 在列表尾部插入值。如果键不存在,先创建再插入值
     703         /// </summary>
     704         /// <param name="redisKey"></param>
     705         /// <param name="redisValue"></param>
     706         /// <returns></returns>
     707         public async Task<long> ListRightPushAsync(string redisKey, string redisValue)
     708         {
     709             redisKey = AddKeyPrefix(redisKey);
     710             return await _db.ListRightPushAsync(redisKey, redisValue);
     711         }
     712 
     713         /// <summary>
     714         /// 在列表头部插入值。如果键不存在,先创建再插入值
     715         /// </summary>
     716         /// <param name="redisKey"></param>
     717         /// <param name="redisValue"></param>
     718         /// <returns></returns>
     719         public async Task<long> ListLeftPushAsync(string redisKey, string redisValue)
     720         {
     721             redisKey = AddKeyPrefix(redisKey);
     722             return await _db.ListLeftPushAsync(redisKey, redisValue);
     723         }
     724 
     725         /// <summary>
     726         /// 返回列表上该键的长度,如果不存在,返回 0
     727         /// </summary>
     728         /// <param name="redisKey"></param>
     729         /// <returns></returns>
     730         public async Task<long> ListLengthAsync(string redisKey)
     731         {
     732             redisKey = AddKeyPrefix(redisKey);
     733             return await _db.ListLengthAsync(redisKey);
     734         }
     735 
     736         /// <summary>
     737         /// 返回在该列表上键所对应的元素
     738         /// </summary>
     739         /// <param name="redisKey"></param>
     740         /// <returns></returns>
     741         public async Task<IEnumerable<RedisValue>> ListRangeAsync(string redisKey)
     742         {
     743             redisKey = AddKeyPrefix(redisKey);
     744             return await _db.ListRangeAsync(redisKey);
     745         }
     746 
     747         /// <summary>
     748         /// 移除并返回存储在该键列表的第一个元素
     749         /// </summary>
     750         /// <param name="redisKey"></param>
     751         /// <returns></returns>
     752         public async Task<T> ListLeftPopAsync<T>(string redisKey)
     753         {
     754             redisKey = AddKeyPrefix(redisKey);
     755             return Deserialize<T>(await _db.ListLeftPopAsync(redisKey));
     756         }
     757 
     758         /// <summary>
     759         /// 移除并返回存储在该键列表的最后一个元素
     760         /// </summary>
     761         /// <param name="redisKey"></param>
     762         /// <returns></returns>
     763         public async Task<T> ListRightPopAsync<T>(string redisKey)
     764         {
     765             redisKey = AddKeyPrefix(redisKey);
     766             return Deserialize<T>(await _db.ListRightPopAsync(redisKey));
     767         }
     768 
     769         /// <summary>
     770         /// 在列表尾部插入值。如果键不存在,先创建再插入值
     771         /// </summary>
     772         /// <param name="redisKey"></param>
     773         /// <param name="redisValue"></param>
     774         /// <returns></returns>
     775         public async Task<long> ListRightPushAsync<T>(string redisKey, T redisValue)
     776         {
     777             redisKey = AddKeyPrefix(redisKey);
     778             return await _db.ListRightPushAsync(redisKey, Serialize(redisValue));
     779         }
     780 
     781         /// <summary>
     782         /// 在列表头部插入值。如果键不存在,先创建再插入值
     783         /// </summary>
     784         /// <param name="redisKey"></param>
     785         /// <param name="redisValue"></param>
     786         /// <returns></returns>
     787         public async Task<long> ListLeftPushAsync<T>(string redisKey, T redisValue)
     788         {
     789             redisKey = AddKeyPrefix(redisKey);
     790             return await _db.ListLeftPushAsync(redisKey, Serialize(redisValue));
     791         }
     792 
     793         #endregion List-async
     794 
     795         #endregion List 操作
     796 
     797         #region SortedSet 操作
     798 
     799         /// <summary>
     800         /// SortedSet 新增
     801         /// </summary>
     802         /// <param name="redisKey"></param>
     803         /// <param name="member"></param>
     804         /// <param name="score"></param>
     805         /// <returns></returns>
     806         public bool SortedSetAdd(string redisKey, string member, double score)
     807         {
     808             redisKey = AddKeyPrefix(redisKey);
     809             return _db.SortedSetAdd(redisKey, member, score);
     810         }
     811 
     812         /// <summary>
     813         /// 在有序集合中返回指定范围的元素,默认情况下从低到高。
     814         /// </summary>
     815         /// <param name="redisKey"></param>
     816         /// <returns></returns>
     817         public IEnumerable<RedisValue> SortedSetRangeByRank(string redisKey)
     818         {
     819             redisKey = AddKeyPrefix(redisKey);
     820             return _db.SortedSetRangeByRank(redisKey);
     821         }
     822 
     823         /// <summary>
     824         /// 返回有序集合的元素个数
     825         /// </summary>
     826         /// <param name="redisKey"></param>
     827         /// <returns></returns>
     828         public long SortedSetLength(string redisKey)
     829         {
     830             redisKey = AddKeyPrefix(redisKey);
     831             return _db.SortedSetLength(redisKey);
     832         }
     833 
     834         /// <summary>
     835         /// 返回有序集合的元素个数
     836         /// </summary>
     837         /// <param name="redisKey"></param>
     838         /// <param name="memebr"></param>
     839         /// <returns></returns>
     840         public bool SortedSetLength(string redisKey, string memebr)
     841         {
     842             redisKey = AddKeyPrefix(redisKey);
     843             return _db.SortedSetRemove(redisKey, memebr);
     844         }
     845 
     846         /// <summary>
     847         /// SortedSet 新增
     848         /// </summary>
     849         /// <param name="redisKey"></param>
     850         /// <param name="member"></param>
     851         /// <param name="score"></param>
     852         /// <returns></returns>
     853         public bool SortedSetAdd<T>(string redisKey, T member, double score)
     854         {
     855             redisKey = AddKeyPrefix(redisKey);
     856             var json = Serialize(member);
     857 
     858             return _db.SortedSetAdd(redisKey, json, score);
     859         }
     860 
     861         #region SortedSet-Async
     862 
     863         /// <summary>
     864         /// SortedSet 新增
     865         /// </summary>
     866         /// <param name="redisKey"></param>
     867         /// <param name="member"></param>
     868         /// <param name="score"></param>
     869         /// <returns></returns>
     870         public async Task<bool> SortedSetAddAsync(string redisKey, string member, double score)
     871         {
     872             redisKey = AddKeyPrefix(redisKey);
     873             return await _db.SortedSetAddAsync(redisKey, member, score);
     874         }
     875 
     876         /// <summary>
     877         /// 在有序集合中返回指定范围的元素,默认情况下从低到高。
     878         /// </summary>
     879         /// <param name="redisKey"></param>
     880         /// <returns></returns>
     881         public async Task<IEnumerable<RedisValue>> SortedSetRangeByRankAsync(string redisKey)
     882         {
     883             redisKey = AddKeyPrefix(redisKey);
     884             return await _db.SortedSetRangeByRankAsync(redisKey);
     885         }
     886 
     887         /// <summary>
     888         /// 返回有序集合的元素个数
     889         /// </summary>
     890         /// <param name="redisKey"></param>
     891         /// <returns></returns>
     892         public async Task<long> SortedSetLengthAsync(string redisKey)
     893         {
     894             redisKey = AddKeyPrefix(redisKey);
     895             return await _db.SortedSetLengthAsync(redisKey);
     896         }
     897 
     898         /// <summary>
     899         /// 返回有序集合的元素个数
     900         /// </summary>
     901         /// <param name="redisKey"></param>
     902         /// <param name="memebr"></param>
     903         /// <returns></returns>
     904         public async Task<bool> SortedSetRemoveAsync(string redisKey, string memebr)
     905         {
     906             redisKey = AddKeyPrefix(redisKey);
     907             return await _db.SortedSetRemoveAsync(redisKey, memebr);
     908         }
     909 
     910         /// <summary>
     911         /// SortedSet 新增
     912         /// </summary>
     913         /// <param name="redisKey"></param>
     914         /// <param name="member"></param>
     915         /// <param name="score"></param>
     916         /// <returns></returns>
     917         public async Task<bool> SortedSetAddAsync<T>(string redisKey, T member, double score)
     918         {
     919             redisKey = AddKeyPrefix(redisKey);
     920             var json = Serialize(member);
     921 
     922             return await _db.SortedSetAddAsync(redisKey, json, score);
     923         }
     924 
     925         #endregion SortedSet-Async
     926 
     927         #endregion SortedSet 操作
     928 
     929         #region key 操作
     930 
     931         /// <summary>
     932         /// 移除指定 Key
     933         /// </summary>
     934         /// <param name="redisKey"></param>
     935         /// <returns></returns>
     936         public bool KeyDelete(string redisKey)
     937         {
     938             redisKey = AddKeyPrefix(redisKey);
     939             return _db.KeyDelete(redisKey);
     940         }
     941 
     942         /// <summary>
     943         /// 移除指定 Key
     944         /// </summary>
     945         /// <param name="redisKeys"></param>
     946         /// <returns></returns>
     947         public long KeyDelete(IEnumerable<string> redisKeys)
     948         {
     949             var keys = redisKeys.Select(x => (RedisKey)AddKeyPrefix(x));
     950             return _db.KeyDelete(keys.ToArray());
     951         }
     952 
     953         /// <summary>
     954         /// 校验 Key 是否存在
     955         /// </summary>
     956         /// <param name="redisKey"></param>
     957         /// <returns></returns>
     958         public bool KeyExists(string redisKey)
     959         {
     960             redisKey = AddKeyPrefix(redisKey);
     961             return _db.KeyExists(redisKey);
     962         }
     963 
     964         /// <summary>
     965         /// 重命名 Key
     966         /// </summary>
     967         /// <param name="redisKey"></param>
     968         /// <param name="redisNewKey"></param>
     969         /// <returns></returns>
     970         public bool KeyRename(string redisKey, string redisNewKey)
     971         {
     972             redisKey = AddKeyPrefix(redisKey);
     973             return _db.KeyRename(redisKey, redisNewKey);
     974         }
     975 
     976         /// <summary>
     977         /// 设置 Key 的时间
     978         /// </summary>
     979         /// <param name="redisKey"></param>
     980         /// <param name="expiry"></param>
     981         /// <returns></returns>
     982         public bool KeyExpire(string redisKey, TimeSpan? expiry)
     983         {
     984             redisKey = AddKeyPrefix(redisKey);
     985             return _db.KeyExpire(redisKey, expiry);
     986         }
     987 
     988         /// <summary>
     989         /// Get all keys by wildcard
     990         /// </summary>
     991         /// <param name="pattern"></param>
     992         /// <returns></returns>
     993         public List<string> Keys(string pattern)
     994         {
     995             //var endPoint = _connMultiplexer.GetEndPoints()[0];
     996             //IServer _server = _connMultiplexer.GetServer(endPoint); //默认一个服务器
     997             //var keys = _server.Keys(database: _db.Database, pattern: pattern); //StackExchange.Redis 会根据redis版本决定用keys还是 scan
     998             //return keys;
     999             pattern = AddKeyPrefix(pattern);
    1000             var redisResult = _db.ScriptEvaluate(LuaScript.Prepare(
    1001                 " local res=redis.call('KEYS',@keypattern) " +
    1002                 " return res "), new { @keypattern = pattern });
    1003             if (redisResult == null) return null;
    1004 
    1005             var keys = (string[])redisResult;//Morningstar.Appointment.Dev:CSM:WDA-07171
    1006             var list = new List<string>();
    1007             foreach (var item in keys)
    1008             {
    1009                 list.Add(item.Split(DefaultKey + ":")[1]);
    1010             }
    1011             return list;
    1012         }
    1013 
    1014         #region key-async
    1015 
    1016         /// <summary>
    1017         /// 移除指定 Key
    1018         /// </summary>
    1019         /// <param name="redisKey"></param>
    1020         /// <returns></returns>
    1021         public async Task<bool> KeyDeleteAsync(string redisKey)
    1022         {
    1023             redisKey = AddKeyPrefix(redisKey);
    1024             return await _db.KeyDeleteAsync(redisKey);
    1025         }
    1026 
    1027         /// <summary>
    1028         /// 移除指定 Key
    1029         /// </summary>
    1030         /// <param name="redisKeys"></param>
    1031         /// <returns></returns>
    1032         public async Task<long> KeyDeleteAsync(IEnumerable<string> redisKeys)
    1033         {
    1034             var keys = redisKeys.Select(x => (RedisKey)AddKeyPrefix(x));
    1035             return await _db.KeyDeleteAsync(keys.ToArray());
    1036         }
    1037 
    1038         /// <summary>
    1039         /// 校验 Key 是否存在
    1040         /// </summary>
    1041         /// <param name="redisKey"></param>
    1042         /// <returns></returns>
    1043         public async Task<bool> KeyExistsAsync(string redisKey)
    1044         {
    1045             redisKey = AddKeyPrefix(redisKey);
    1046             return await _db.KeyExistsAsync(redisKey);
    1047         }
    1048 
    1049         /// <summary>
    1050         /// 重命名 Key
    1051         /// </summary>
    1052         /// <param name="redisKey"></param>
    1053         /// <param name="redisNewKey"></param>
    1054         /// <returns></returns>
    1055         public async Task<bool> KeyRenameAsync(string redisKey, string redisNewKey)
    1056         {
    1057             redisKey = AddKeyPrefix(redisKey);
    1058             return await _db.KeyRenameAsync(redisKey, redisNewKey);
    1059         }
    1060 
    1061         /// <summary>
    1062         /// 设置 Key 的时间
    1063         /// </summary>
    1064         /// <param name="redisKey"></param>
    1065         /// <param name="expiry"></param>
    1066         /// <returns></returns>
    1067         public async Task<bool> KeyExpireAsync(string redisKey, TimeSpan? expiry)
    1068         {
    1069             redisKey = AddKeyPrefix(redisKey);
    1070             return await _db.KeyExpireAsync(redisKey, expiry);
    1071         }
    1072 
    1073         #endregion key-async
    1074 
    1075         #endregion key 操作
    1076 
    1077         #region 发布订阅
    1078 
    1079         /// <summary>
    1080         /// 订阅
    1081         /// </summary>
    1082         /// <param name="channel"></param>
    1083         /// <param name="handle"></param>
    1084         public void Subscribe(RedisChannel channel, Action<RedisChannel, RedisValue> handle)
    1085         {
    1086             var sub = _connMultiplexer.GetSubscriber();
    1087             sub.Subscribe(channel, handle);
    1088         }
    1089 
    1090         /// <summary>
    1091         /// 发布
    1092         /// </summary>
    1093         /// <param name="channel"></param>
    1094         /// <param name="message"></param>
    1095         /// <returns></returns>
    1096         public long Publish(RedisChannel channel, RedisValue message)
    1097         {
    1098             var sub = _connMultiplexer.GetSubscriber();
    1099             return sub.Publish(channel, message);
    1100         }
    1101 
    1102         /// <summary>
    1103         /// 发布(使用序列化)
    1104         /// </summary>
    1105         /// <typeparam name="T"></typeparam>
    1106         /// <param name="channel"></param>
    1107         /// <param name="message"></param>
    1108         /// <returns></returns>
    1109         public long Publish<T>(RedisChannel channel, T message)
    1110         {
    1111             var sub = _connMultiplexer.GetSubscriber();
    1112             return sub.Publish(channel, Serialize(message));
    1113         }
    1114 
    1115         #region 发布订阅-async
    1116 
    1117         /// <summary>
    1118         /// 订阅
    1119         /// </summary>
    1120         /// <param name="channel"></param>
    1121         /// <param name="handle"></param>
    1122         public async Task SubscribeAsync(RedisChannel channel, Action<RedisChannel, RedisValue> handle)
    1123         {
    1124             var sub = _connMultiplexer.GetSubscriber();
    1125             await sub.SubscribeAsync(channel, handle);
    1126         }
    1127 
    1128         /// <summary>
    1129         /// 发布
    1130         /// </summary>
    1131         /// <param name="channel"></param>
    1132         /// <param name="message"></param>
    1133         /// <returns></returns>
    1134         public async Task<long> PublishAsync(RedisChannel channel, RedisValue message)
    1135         {
    1136             var sub = _connMultiplexer.GetSubscriber();
    1137             return await sub.PublishAsync(channel, message);
    1138         }
    1139 
    1140         /// <summary>
    1141         /// 发布(使用序列化)
    1142         /// </summary>
    1143         /// <typeparam name="T"></typeparam>
    1144         /// <param name="channel"></param>
    1145         /// <param name="message"></param>
    1146         /// <returns></returns>
    1147         public async Task<long> PublishAsync<T>(RedisChannel channel, T message)
    1148         {
    1149             var sub = _connMultiplexer.GetSubscriber();
    1150             return await sub.PublishAsync(channel, Serialize(message));
    1151         }
    1152 
    1153         #endregion 发布订阅-async
    1154 
    1155         #endregion 发布订阅
    1156 
    1157         #region private method
    1158 
    1159         /// <summary>
    1160         /// 添加 Key 的前缀
    1161         /// </summary>
    1162         /// <param name="key"></param>
    1163         /// <returns></returns>
    1164         private static string AddKeyPrefix(string key)
    1165         {
    1166             return $"{DefaultKey}:{key}";
    1167         }
    1168 
    1169         #region 注册事件
    1170 
    1171         /// <summary>
    1172         /// 添加注册事件
    1173         /// </summary>
    1174         private static void AddRegisterEvent()
    1175         {
    1176             _connMultiplexer.ConnectionRestored += ConnMultiplexer_ConnectionRestored;
    1177             _connMultiplexer.ConnectionFailed += ConnMultiplexer_ConnectionFailed;
    1178             _connMultiplexer.ErrorMessage += ConnMultiplexer_ErrorMessage;
    1179             _connMultiplexer.ConfigurationChanged += ConnMultiplexer_ConfigurationChanged;
    1180             _connMultiplexer.HashSlotMoved += ConnMultiplexer_HashSlotMoved;
    1181             _connMultiplexer.InternalError += ConnMultiplexer_InternalError;
    1182             _connMultiplexer.ConfigurationChangedBroadcast += ConnMultiplexer_ConfigurationChangedBroadcast;
    1183         }
    1184 
    1185         /// <summary>
    1186         /// 重新配置广播时(通常意味着主从同步更改)
    1187         /// </summary>
    1188         /// <param name="sender"></param>
    1189         /// <param name="e"></param>
    1190         private static void ConnMultiplexer_ConfigurationChangedBroadcast(object sender, EndPointEventArgs e)
    1191         {
    1192             Console.WriteLine($"{nameof(ConnMultiplexer_ConfigurationChangedBroadcast)}: {e.EndPoint}");
    1193         }
    1194 
    1195         /// <summary>
    1196         /// 发生内部错误时(主要用于调试)
    1197         /// </summary>
    1198         /// <param name="sender"></param>
    1199         /// <param name="e"></param>
    1200         private static void ConnMultiplexer_InternalError(object sender, InternalErrorEventArgs e)
    1201         {
    1202             Console.WriteLine($"{nameof(ConnMultiplexer_InternalError)}: {e.Exception}");
    1203         }
    1204 
    1205         /// <summary>
    1206         /// 更改集群时
    1207         /// </summary>
    1208         /// <param name="sender"></param>
    1209         /// <param name="e"></param>
    1210         private static void ConnMultiplexer_HashSlotMoved(object sender, HashSlotMovedEventArgs e)
    1211         {
    1212             Console.WriteLine(
    1213                 $"{nameof(ConnMultiplexer_HashSlotMoved)}: {nameof(e.OldEndPoint)}-{e.OldEndPoint} To {nameof(e.NewEndPoint)}-{e.NewEndPoint}, ");
    1214         }
    1215 
    1216         /// <summary>
    1217         /// 配置更改时
    1218         /// </summary>
    1219         /// <param name="sender"></param>
    1220         /// <param name="e"></param>
    1221         private static void ConnMultiplexer_ConfigurationChanged(object sender, EndPointEventArgs e)
    1222         {
    1223             Console.WriteLine($"{nameof(ConnMultiplexer_ConfigurationChanged)}: {e.EndPoint}");
    1224         }
    1225 
    1226         /// <summary>
    1227         /// 发生错误时
    1228         /// </summary>
    1229         /// <param name="sender"></param>
    1230         /// <param name="e"></param>
    1231         private static void ConnMultiplexer_ErrorMessage(object sender, RedisErrorEventArgs e)
    1232         {
    1233             Console.WriteLine($"{nameof(ConnMultiplexer_ErrorMessage)}: {e.Message}");
    1234         }
    1235 
    1236         /// <summary>
    1237         /// 物理连接失败时
    1238         /// </summary>
    1239         /// <param name="sender"></param>
    1240         /// <param name="e"></param>
    1241         private static void ConnMultiplexer_ConnectionFailed(object sender, ConnectionFailedEventArgs e)
    1242         {
    1243             Console.WriteLine($"{nameof(ConnMultiplexer_ConnectionFailed)}: {e.Exception}");
    1244         }
    1245 
    1246         /// <summary>
    1247         /// 建立物理连接时
    1248         /// </summary>
    1249         /// <param name="sender"></param>
    1250         /// <param name="e"></param>
    1251         private static void ConnMultiplexer_ConnectionRestored(object sender, ConnectionFailedEventArgs e)
    1252         {
    1253             Console.WriteLine($"{nameof(ConnMultiplexer_ConnectionRestored)}: {e.Exception}");
    1254         }
    1255 
    1256         #endregion 注册事件
    1257 
    1258         /// <summary>
    1259         /// 序列化
    1260         /// </summary>
    1261         /// <param name="obj"></param>
    1262         /// <returns></returns>
    1263         private static byte[] Serialize(object obj)
    1264         {
    1265             if (obj == null)
    1266                 return null;
    1267 
    1268             var binaryFormatter = new BinaryFormatter();
    1269             using (var memoryStream = new MemoryStream())
    1270             {
    1271                 binaryFormatter.Serialize(memoryStream, obj);
    1272                 var data = memoryStream.ToArray();
    1273                 return data;
    1274             }
    1275         }
    1276 
    1277         /// <summary>
    1278         /// 反序列化
    1279         /// </summary>
    1280         /// <typeparam name="T"></typeparam>
    1281         /// <param name="data"></param>
    1282         /// <returns></returns>
    1283         private static T Deserialize<T>(byte[] data)
    1284         {
    1285             if (data == null)
    1286                 return default(T);
    1287 
    1288             var binaryFormatter = new BinaryFormatter();
    1289             using (var memoryStream = new MemoryStream(data))
    1290             {
    1291                 var result = (T)binaryFormatter.Deserialize(memoryStream);
    1292                 return result;
    1293             }
    1294         }
    1295 
    1296         #endregion private method
    1297     }
    1298 }
    RedisHelper.cs

       2,appsettings.json

     1 {
     2   "Redis": {
     3     "ConnectionStrings": "127.0.0.1:6379,password=ms.corpqa.interviewscheduling",
     4     "DefaultKey": "Morningstar.InterviewScheduling.Dev",
     5     "ServiceName": "mymaster",
     6     "Password": "ms.corpqa.interviewscheduling",
     7     "Sentinel": [
     8       "127.0.0.1:26379",
     9       "127.0.0.1:26380",
    10       "127.0.0.1:26381"
    11     ]
    12   },
    13   "ExpireDays": 7, //the unit is day
    14   "HttpProxyConfig": {
    15     "UseProxy": "true",
    16     "ProxyHost": "172.28.104.174",
    17     "ProxyPort": "8080"
    18   }
    19 }
    appsettings.json

      注:StackExchange.Redis请使用最新版本,以上代码使用的是2.2.4版本。

    三,.NET Core 项目中使用

      

     

  • 相关阅读:
    luaPlus
    falagard cegui
    cegui 的透明纹理
    msvcprt.lib(MSVCP90.dll) : error LNK2005:已经在libcpmtd.lib(xmutex.obj) 中定义
    CEGUI
    SameText
    操作 Wave 文件(15): 合并与剪裁 wav 文件
    Delphi 的编码与解码(或叫加密与解密)函数
    操作 Wave 文件(13): waveOutGetVolume、waveOutSetVolume
    操作 Wave 文件(12): 使用 waveOut...重复播放 wav 文件
  • 原文地址:https://www.cnblogs.com/shangec/p/14875139.html
Copyright © 2011-2022 走看看