• StackExchange.Redis学习笔记(一) Redis的使用初探


    Redis

    • Redis将其数据库完全保存在内存中,仅使用磁盘进行持久化。
    • 与其它键值数据存储相比,Redis有一组相对丰富的数据类型。
    • Redis可以将数据复制到任意数量的从机中

    Redis的安装

      官网只提供了linux的安装包,我win10 的系统,在github上下载的windows安装包 3.0.504最新稳定版的

      github地址:https://github.com/MicrosoftArchive/redis/releases   
      官网下载地址:https://redis.io/download   

      将压缩包解压到文件夹后,双击“redis-server.exe”即可启动redis服务,也可以在环境变量中配置之后,用redis-server 命令来开启服务,以下是服务启动成功界面

      

    Redis的使用

      C#可选用ServiceStack.Redis或者StackExchange.Redis等客户端程序操作redis,由于ServiceStack.Redis已经收费了,我这里用的是StackExchange.Redis,通过Nuget安装到项目中

    接下来我们创建一个操作redis的帮助类:

      1    public static class StackExchangeRedisHelper
      2     {
      3         private static readonly string Coonstr = ConfigurationManager.ConnectionStrings["RedisExchangeHosts"].ConnectionString;//
      4         private static object _locker = new Object();
      5         private static ConnectionMultiplexer _instance = null;
      6         /// <summary>
      7         /// 使用一个静态属性来返回已连接的实例,如下列中所示。这样,一旦 ConnectionMultiplexer 断开连接,便可以初始化新的连接实例。
      8         /// </summary>
      9         public static ConnectionMultiplexer Instance
     10         {
     11             get
     12             {
     13                 if (_instance == null)
     14                 {
     15                     lock (_locker)
     16                     {
     17                         if (_instance == null || !_instance.IsConnected)
     18                         {
     19                             _instance = ConnectionMultiplexer.Connect(Coonstr);
     20                         }
     21                     }
     22                 }
     23                 //注册如下事件
     24                 _instance.ConnectionFailed += MuxerConnectionFailed;
     25                 _instance.ConnectionRestored += MuxerConnectionRestored;
     26                 _instance.ErrorMessage += MuxerErrorMessage;
     27                 _instance.ConfigurationChanged += MuxerConfigurationChanged;
     28                 _instance.HashSlotMoved += MuxerHashSlotMoved;
     29                 _instance.InternalError += MuxerInternalError;
     30                 return _instance;
     31             }
     32         }
     33 
     34 
     35         static StackExchangeRedisHelper()
     36         {
     37         }
     38 
     39         /// <summary>
     40         /// 
     41         /// </summary>
     42         /// <returns></returns>
     43         public static IDatabase GetDatabase()
     44         {
     45             return Instance.GetDatabase();
     46         }
     47 
     48         /// <summary>
     49         /// 这里的 MergeKey 用来拼接 Key 的前缀,具体不同的业务模块使用不同的前缀。
     50         /// </summary>
     51         /// <param name="key"></param>
     52         /// <returns></returns>
     53         private static string MergeKey(string key)
     54         {
     55             return BaseSystemInfo.SystemCode + key;
     56         }
     57         /// <summary>
     58         /// 根据key获取缓存对象
     59         /// </summary>
     60         /// <typeparam name="T"></typeparam>
     61         /// <param name="key"></param>
     62         /// <returns></returns>
     63         public static T Get<T>(string key)
     64         {
     65             key = MergeKey(key);
     66             return Deserialize<T>(GetDatabase().StringGet(key));
     67         }
     68         /// <summary>
     69         /// 根据key获取缓存对象
     70         /// </summary>
     71         /// <param name="key"></param>
     72         /// <returns></returns>
     73         public static object Get(string key)
     74         {
     75             key = MergeKey(key);
     76             return Deserialize<object>(GetDatabase().StringGet(key));
     77         }
     78 
     79         /// <summary>
     80         /// 设置缓存
     81         /// </summary>
     82         /// <param name="key"></param>
     83         /// <param name="value"></param>
     84         public static void Set(string key, object value, TimeSpan? expiry = default(TimeSpan?), When when = When.Always, CommandFlags flags = CommandFlags.None)
     85         {
     86             key = MergeKey(key);
     87             GetDatabase().StringSet(key, Serialize(value), expiry, when, flags);
     88         }
     89 
     90         /// <summary>
     91         /// 判断在缓存中是否存在该key的缓存数据
     92         /// </summary>
     93         /// <param name="key"></param>
     94         /// <returns></returns>
     95         public static bool Exists(string key)
     96         {
     97             key = MergeKey(key);
     98             return GetDatabase().KeyExists(key);  //可直接调用
     99         }
    100 
    101         /// <summary>
    102         /// 移除指定key的缓存
    103         /// </summary>
    104         /// <param name="key"></param>
    105         /// <returns></returns>
    106         public static bool Remove(string key)
    107         {
    108             key = MergeKey(key);
    109             return GetDatabase().KeyDelete(key);
    110         }
    111 
    112         /// <summary>
    113         /// 异步设置
    114         /// </summary>
    115         /// <param name="key"></param>
    116         /// <param name="value"></param>
    117         public static async Task SetAsync(string key, object value)
    118         {
    119             key = MergeKey(key);
    120             await GetDatabase().StringSetAsync(key, Serialize(value));
    121         }
    122 
    123         /// <summary>
    124         /// 根据key获取缓存对象
    125         /// </summary>
    126         /// <param name="key"></param>
    127         /// <returns></returns>
    128         public static async Task<object> GetAsync(string key)
    129         {
    130             key = MergeKey(key);
    131             object value = await GetDatabase().StringGetAsync(key);
    132             return value;
    133         }
    134 
    135         /// <summary>
    136         /// 实现递增
    137         /// </summary>
    138         /// <param name="key"></param>
    139         /// <returns></returns>
    140         public static long Increment(string key)
    141         {
    142             key = MergeKey(key);
    143             //三种命令模式
    144             //Sync,同步模式会直接阻塞调用者,但是显然不会阻塞其他线程。
    145             //Async,异步模式直接走的是Task模型。
    146             //Fire - and - Forget,就是发送命令,然后完全不关心最终什么时候完成命令操作。
    147             //即发即弃:通过配置 CommandFlags 来实现即发即弃功能,在该实例中该方法会立即返回,如果是string则返回null 如果是int则返回0.这个操作将会继续在后台运行,一个典型的用法页面计数器的实现:
    148             return GetDatabase().StringIncrement(key, flags: CommandFlags.FireAndForget);
    149         }
    150 
    151         /// <summary>
    152         /// 实现递减
    153         /// </summary>
    154         /// <param name="key"></param>
    155         /// <param name="value"></param>
    156         /// <returns></returns>
    157         public static long Decrement(string key, string value)
    158         {
    159             key = MergeKey(key);
    160             return GetDatabase().HashDecrement(key, value, flags: CommandFlags.FireAndForget);
    161         }
    162 
    163         /// <summary>
    164         /// 序列化对象
    165         /// </summary>
    166         /// <param name="o"></param>
    167         /// <returns></returns>
    168         static byte[] Serialize(object o)
    169         {
    170             if (o == null)
    171             {
    172                 return null;
    173             }
    174             BinaryFormatter binaryFormatter = new BinaryFormatter();
    175             using (MemoryStream memoryStream = new MemoryStream())
    176             {
    177                 binaryFormatter.Serialize(memoryStream, o);
    178                 byte[] objectDataAsStream = memoryStream.ToArray();
    179                 return objectDataAsStream;
    180             }
    181         }
    182 
    183         /// <summary>
    184         /// 反序列化对象
    185         /// </summary>
    186         /// <typeparam name="T"></typeparam>
    187         /// <param name="stream"></param>
    188         /// <returns></returns>
    189         static T Deserialize<T>(byte[] stream)
    190         {
    191             if (stream == null)
    192             {
    193                 return default(T);
    194             }
    195             BinaryFormatter binaryFormatter = new BinaryFormatter();
    196             using (MemoryStream memoryStream = new MemoryStream(stream))
    197             {
    198                 T result = (T)binaryFormatter.Deserialize(memoryStream);
    199                 return result;
    200             }
    201         }
    202         /// <summary>
    203         /// 配置更改时
    204         /// </summary>
    205         /// <param name="sender"></param>
    206         /// <param name="e"></param>
    207         private static void MuxerConfigurationChanged(object sender, EndPointEventArgs e)
    208         {
    209             LogHelper.WriteInfoLog("Configuration changed: " + e.EndPoint);
    210         }
    211         /// <summary>
    212         /// 发生错误时
    213         /// </summary>
    214         /// <param name="sender"></param>
    215         /// <param name="e"></param>
    216         private static void MuxerErrorMessage(object sender, RedisErrorEventArgs e)
    217         {
    218             LogHelper.WriteInfoLog("ErrorMessage: " + e.Message);
    219         }
    220         /// <summary>
    221         /// 重新建立连接之前的错误
    222         /// </summary>
    223         /// <param name="sender"></param>
    224         /// <param name="e"></param>
    225         private static void MuxerConnectionRestored(object sender, ConnectionFailedEventArgs e)
    226         {
    227             LogHelper.WriteInfoLog("ConnectionRestored: " + e.EndPoint);
    228         }
    229         /// <summary>
    230         /// 连接失败 , 如果重新连接成功你将不会收到这个通知
    231         /// </summary>
    232         /// <param name="sender"></param>
    233         /// <param name="e"></param>
    234         private static void MuxerConnectionFailed(object sender, ConnectionFailedEventArgs e)
    235         {
    236             LogHelper.WriteInfoLog("重新连接:Endpoint failed: " + e.EndPoint + ", " + e.FailureType + (e.Exception == null ? "" : (", " + e.Exception.Message)));
    237         }
    238         /// <summary>
    239         /// 更改集群
    240         /// </summary>
    241         /// <param name="sender"></param>
    242         /// <param name="e"></param>
    243         private static void MuxerHashSlotMoved(object sender, HashSlotMovedEventArgs e)
    244         {
    245             LogHelper.WriteInfoLog("HashSlotMoved:NewEndPoint" + e.NewEndPoint + ", OldEndPoint" + e.OldEndPoint);
    246         }
    247         /// <summary>
    248         /// redis类库错误
    249         /// </summary>
    250         /// <param name="sender"></param>
    251         /// <param name="e"></param>
    252         private static void MuxerInternalError(object sender, InternalErrorEventArgs e)
    253         {
    254             LogHelper.WriteInfoLog("InternalError:Message" + e.Exception.Message);
    255         }
    256 
    257         //场景不一样,选择的模式便会不一样,大家可以按照自己系统架构情况合理选择长连接还是Lazy。
    258         //建立连接后,通过调用ConnectionMultiplexer.GetDatabase 方法返回对 Redis Cache 数据库的引用。从 GetDatabase 方法返回的对象是一个轻量级直通对象,不需要进行存储。
    259 
    260         /// <summary>
    261         /// 使用的是Lazy,在真正需要连接时创建连接。
    262         /// 延迟加载技术
    263         /// 微软azure中的配置 连接模板
    264         /// </summary>
    265         //private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
    266         //{
    267         //    //var options = ConfigurationOptions.Parse(constr);
    268         //    ////options.ClientName = GetAppName(); // only known at runtime
    269         //    //options.AllowAdmin = true;
    270         //    //return ConnectionMultiplexer.Connect(options);
    271         //    ConnectionMultiplexer muxer = ConnectionMultiplexer.Connect(Coonstr);
    272         //    muxer.ConnectionFailed += MuxerConnectionFailed;
    273         //    muxer.ConnectionRestored += MuxerConnectionRestored;
    274         //    muxer.ErrorMessage += MuxerErrorMessage;
    275         //    muxer.ConfigurationChanged += MuxerConfigurationChanged;
    276         //    muxer.HashSlotMoved += MuxerHashSlotMoved;
    277         //    muxer.InternalError += MuxerInternalError;
    278         //    return muxer;
    279         //});
    280 
    281 
    282         #region  当作消息代理中间件使用 一般使用更专业的消息队列来处理这种业务场景
    283         /// <summary>
    284         /// 当作消息代理中间件使用
    285         /// 消息组建中,重要的概念便是生产者,消费者,消息中间件。
    286         /// </summary>
    287         /// <param name="channel"></param>
    288         /// <param name="message"></param>
    289         /// <returns></returns>
    290         public static long Publish(string channel, string message)
    291         {
    292             ISubscriber sub = Instance.GetSubscriber();
    293             //return sub.Publish("messages", "hello");
    294             return sub.Publish(channel, message);
    295         }
    296 
    297         /// <summary>
    298         /// 在消费者端得到该消息并输出
    299         /// </summary>
    300         /// <param name="channelFrom"></param>
    301         /// <returns></returns>
    302         public static void Subscribe(string channelFrom)
    303         {
    304             ISubscriber sub = Instance.GetSubscriber();
    305             sub.Subscribe(channelFrom, (channel, message) =>
    306             {
    307                 Console.WriteLine((string)message);
    308             });
    309         }
    310         #endregion
    311 
    312         /// <summary>
    313         /// GetServer方法会接收一个EndPoint类或者一个唯一标识一台服务器的键值对
    314         /// 有时候需要为单个服务器指定特定的命令
    315         /// 使用IServer可以使用所有的shell命令,比如:
    316         /// DateTime lastSave = server.LastSave();
    317         /// ClientInfo[] clients = server.ClientList();
    318         /// 如果报错在连接字符串后加 ,allowAdmin=true;
    319         /// </summary>
    320         /// <returns></returns>
    321         public static IServer GetServer(string host, int port)
    322         {
    323             IServer server = Instance.GetServer(host, port);
    324             return server;
    325         }
    326 
    327         /// <summary>
    328         /// 获取全部终结点
    329         /// </summary>
    330         /// <returns></returns>
    331         public static EndPoint[] GetEndPoints()
    332         {
    333             EndPoint[] endpoints = Instance.GetEndPoints();
    334             return endpoints;
    335         }
    336 
    337     }
    338 
    339     internal class BaseSystemInfo
    340     {
    341         internal static readonly string SystemCode="000A";
    342     }
    View Code

    测试代码

     1  static void Main(string[] args)
     2         {
     3             RedisTest();
     4         }
     5         public static void RedisTest()
     6         {
     7             Console.WriteLine("Redis写入缓存:Name:张三丰");
     8             StackExchangeRedisHelper.Set("Name", "张三丰", new TimeSpan(0, 0, 0, 0, 1000));
     9             Console.WriteLine("Redis获取缓存:Name:" + StackExchangeRedisHelper.Get("Name").ToString());
    10             Thread.Sleep(1000);
    11             Console.WriteLine("一秒后Redis获取缓存:Name:" + StackExchangeRedisHelper.Get("Name")??"");
    12             Console.ReadKey();
    13         }

     

     也可以通过Execute来直接运行redis命令

    Redis加入Windows服务

    由于关闭控制台redis就自动关闭了,所以把redis加入windows服务更好一些

    切换到redis目录下运行命令:redis-server --service-install redis.windows-service.conf --loglevel verbose

    移除服务:--service-uninstal

    开启服务:redis-server --service-start

    关闭服务:redis-server --service-stop

    在开启Redis服务时遇到一些坑,

      redis.windows-service.conf中配置:

      1. logfile "Logs/redis_log.txt"需要有对应的目录

      2.将bind 127.0.0.1注释去掉

      3.依然有问题,后参考一篇文章 http://blog.csdn.net/fengzhihen2007/article/details/52211048

    直到出现successfully started服务启动成功

  • 相关阅读:
    信息化与信息系统4
    信息化与信息系统3
    信息化与信息系统2
    信息化与信息系统1
    ASP.NET Core教程:ASP.NET Core 程序部署到Windows系统
    C#几种单例模式
    SQL查询优化
    动态类型dynamic(ExpandoObject)
    PV(访问量)、UV(独立访客)、IP(独立IP)
    Spring Boot 2.配置
  • 原文地址:https://www.cnblogs.com/bluesummer/p/7677468.html
Copyright © 2020-2023  润新知