欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Redis学习笔记:Redis在C#中的使用

程序员文章站 2022-03-10 18:37:50
1、新建一个WinForm窗体,命名为Main: 2、在NuGet中安装StackExchange.Redis。 3、添加一个类,命名为RedisHelper。 public static class RedisHelper { private static string Constr = ""; ......

    1、新建一个winform窗体,命名为main:

Redis学习笔记:Redis在C#中的使用

    2、在nuget中安装stackexchange.redis。

Redis学习笔记:Redis在C#中的使用

    3、添加一个类,命名为redishelper。

    public static class redishelper
    {
        private static string constr = "";
        private static readonly object _locker = new object();
        private static connectionmultiplexer _instance = null;

        /// <summary>
        /// 使用一个静态属性来返回已连接的实例,如下列中所示。这样,一旦 connectionmultiplexer 断开连接,便可以初始化新的连接实例。
        /// </summary>
        public static connectionmultiplexer instance
        {
            get
            {
                if (constr.length == 0)
                {
                    throw new exception("连接字符串未设置!");
                }
                if (_instance == null)
                {
                    lock (_locker)
                    {
                        if (_instance == null || !_instance.isconnected)
                        {
                            _instance = connectionmultiplexer.connect(constr);
                        }
                    }
                }
                //注册如下事件
                _instance.connectionfailed += muxerconnectionfailed;
                _instance.connectionrestored += muxerconnectionrestored;
                _instance.errormessage += muxererrormessage;
                _instance.configurationchanged += muxerconfigurationchanged;
                _instance.hashslotmoved += muxerhashslotmoved;
                _instance.internalerror += muxerinternalerror;
                return _instance;
            }
        }

        static redishelper()
        {
        }

        public static void setcon(string config)
        {
            constr = config;
        }

        public static idatabase getdatabase()
        {
            return instance.getdatabase();
        }

        /// <summary>
        /// 这里的 mergekey 用来拼接 key 的前缀,具体不同的业务模块使用不同的前缀。
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private static string mergekey(string key)
        {
            return key;
            //return basesysteminfo.systemcode + key;
        }

        /// <summary>
        /// 根据key获取缓存对象
        /// </summary>
        /// <typeparam name="t"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        public static t get<t>(string key)
        {
            key = mergekey(key);
            return deserialize<t>(getdatabase().stringget(key));
        }

        /// <summary>
        /// 根据key获取缓存对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static object get(string key)
        {
            key = mergekey(key);
            return deserialize<object>(getdatabase().stringget(key));
        }

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expireminutes"></param>
        public static void set(string key, object value, int expireminutes = 0)
        {
            key = mergekey(key);
            if (expireminutes > 0)
            {
                getdatabase().stringset(key, serialize(value), timespan.fromminutes(expireminutes));
            }
            else
            {
                getdatabase().stringset(key, serialize(value));
            }
        }

        /// <summary>
        /// 判断在缓存中是否存在该key的缓存数据
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool exists(string key)
        {
            key = mergekey(key);
            return getdatabase().keyexists(key); //可直接调用
        }

        /// <summary>
        /// 移除指定key的缓存
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool remove(string key)
        {
            key = mergekey(key);
            return getdatabase().keydelete(key);
        }

        /// <summary>
        /// 异步设置
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static async task setasync(string key, object value)
        {
            key = mergekey(key);
            await getdatabase().stringsetasync(key, serialize(value));
        }

        /// <summary>
        /// 根据key获取缓存对象
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static async task<object> getasync(string key)
        {
            key = mergekey(key);
            object value = await getdatabase().stringgetasync(key);
            return value;
        }

        /// <summary>
        /// 实现递增
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static long increment(string key)
        {
            key = mergekey(key);
            //三种命令模式
            //sync,同步模式会直接阻塞调用者,但是显然不会阻塞其他线程。
            //async,异步模式直接走的是task模型。
            //fire - and - forget,就是发送命令,然后完全不关心最终什么时候完成命令操作。
            //即发即弃:通过配置 commandflags 来实现即发即弃功能,在该实例中该方法会立即返回,如果是string则返回null 如果是int则返回0.这个操作将会继续在后台运行,一个典型的用法页面计数器的实现:
            return getdatabase().stringincrement(key, flags: commandflags.fireandforget);
        }

        /// <summary>
        /// 实现递减
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static long decrement(string key, string value)
        {
            key = mergekey(key);
            return getdatabase().hashdecrement(key, value, flags: commandflags.fireandforget);
        }

        /// <summary>
        /// 序列化对象
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        private static byte[] serialize(object o)
        {
            if (o == null)
            {
                return null;
            }
            binaryformatter binaryformatter = new binaryformatter();
            using (memorystream memorystream = new memorystream())
            {
                binaryformatter.serialize(memorystream, o);
                byte[] objectdataasstream = memorystream.toarray();
                return objectdataasstream;
            }
        }

        /// <summary>
        /// 反序列化对象
        /// </summary>
        /// <typeparam name="t"></typeparam>
        /// <param name="stream"></param>
        /// <returns></returns>
        private static t deserialize<t>(byte[] stream)
        {
            if (stream == null)
            {
                return default(t);
            }
            binaryformatter binaryformatter = new binaryformatter();
            using (memorystream memorystream = new memorystream(stream))
            {
                t result = (t)binaryformatter.deserialize(memorystream);
                return result;
            }
        }

        /// <summary>
        /// 配置更改时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void muxerconfigurationchanged(object sender, endpointeventargs e)
        {
            //loghelper.safelogmessage("configuration changed: " + e.endpoint);
        }

        /// <summary>
        /// 发生错误时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void muxererrormessage(object sender, rediserroreventargs e)
        {
            //loghelper.safelogmessage("errormessage: " + e.message);
        }

        /// <summary>
        /// 重新建立连接之前的错误
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void muxerconnectionrestored(object sender, connectionfailedeventargs e)
        {
            //loghelper.safelogmessage("connectionrestored: " + e.endpoint);
        }

        /// <summary>
        /// 连接失败,如果重新连接成功你将不会收到这个通知。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void muxerconnectionfailed(object sender, connectionfailedeventargs e)
        {
            //loghelper.safelogmessage("重新连接:endpoint failed: " + e.endpoint + ", " + e.failuretype +(e.exception == null ? "" : (", " + e.exception.message)));
        }

        /// <summary>
        /// 更改集群
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void muxerhashslotmoved(object sender, hashslotmovedeventargs e)
        {
            //loghelper.safelogmessage("hashslotmoved:newendpoint" + e.newendpoint + ", oldendpoint" + e.oldendpoint);
        }

        /// <summary>
        /// redis类库错误
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void muxerinternalerror(object sender, internalerroreventargs e)
        {
            //loghelper.safelogmessage("internalerror:message" + e.exception.message);
        }

        //场景不一样,选择的模式便会不一样,大家可以按照自己系统架构情况合理选择长连接还是lazy。
        //建立连接后,通过调用connectionmultiplexer.getdatabase 方法返回对 redis cache 数据库的引用。从 getdatabase 方法返回的对象是一个轻量级直通对象,不需要进行存储。

        /// <summary>
        /// 使用的是lazy,在真正需要连接时创建连接。
        /// 延迟加载技术
        /// 微软azure中的配置 连接模板
        /// </summary>
        //private static lazy<connectionmultiplexer> lazyconnection = new lazy<connectionmultiplexer>(() =>
        //{
        //    //var options = configurationoptions.parse(constr);
        //    ////options.clientname = getappname(); // only known at runtime
        //    //options.allowadmin = true;
        //    //return connectionmultiplexer.connect(options);
        //    connectionmultiplexer muxer = connectionmultiplexer.connect(coonstr);
        //    muxer.connectionfailed += muxerconnectionfailed;
        //    muxer.connectionrestored += muxerconnectionrestored;
        //    muxer.errormessage += muxererrormessage;
        //    muxer.configurationchanged += muxerconfigurationchanged;
        //    muxer.hashslotmoved += muxerhashslotmoved;
        //    muxer.internalerror += muxerinternalerror;
        //    return muxer;
        //});


        #region  当作消息代理中间件使用 一般使用更专业的消息队列来处理这种业务场景

        /// <summary>
        /// 当作消息代理中间件使用
        /// 消息组建中,重要的概念便是生产者、消费者、消息中间件。
        /// </summary>
        /// <param name="channel"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public static long publish(string channel, string message)
        {
            isubscriber sub = instance.getsubscriber();
            //return sub.publish("messages", "hello");
            return sub.publish(channel, message);
        }

        /// <summary>
        /// 在消费者端得到该消息并输出
        /// </summary>
        /// <param name="channelfrom"></param>
        /// <returns></returns>
        public static void subscribe(string channelfrom)
        {
            isubscriber sub = instance.getsubscriber();
            sub.subscribe(channelfrom, (channel, message) =>
            {
                console.writeline(message);
            });
        }

        #endregion

        /// <summary>
        /// getserver方法会接收一个endpoint类或者一个唯一标识一台服务器的键值对
        /// 有时候需要为单个服务器指定特定的命令
        /// 使用iserver可以使用所有的shell命令,比如:
        /// datetime lastsave = server.lastsave();
        /// clientinfo[] clients = server.clientlist();
        /// 如果报错在连接字符串后加 ,allowadmin=true;
        /// </summary>
        /// <returns></returns>
        public static iserver getserver(string host, int port)
        {
            iserver server = instance.getserver(host, port);
            return server;
        }

        /// <summary>
        /// 获取全部终结点
        /// </summary>
        /// <returns></returns>
        public static endpoint[] getendpoints()
        {
            endpoint[] endpoints = instance.getendpoints();
            return endpoints;
        }
    }

    4、main窗体代码:

    public partial class main : form
    {
        public main()
        {
            initializecomponent();

            try
            {
                string redisconf = "127.0.0.1:6379,password=12345,defaultdatabase=0";
                redishelper.setcon(redisconf);
            }
            catch (exception ex)
            {
                messagebox.show(ex.message, "提示", messageboxbuttons.ok, messageboxicon.information);
            }
        }

        /// <summary>
        /// 设置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_click(object sender, eventargs e)
        {
            if (string.isnullorempty(textbox1.text))
            {
                textbox4.text = "请填写键";
                return;
            }
            if (string.isnullorempty(textbox2.text))
            {
                textbox4.text = "请填写值";
                return;
            }
            if (string.isnullorempty(textbox3.text))
            {
                textbox4.text = "请填写过期时间";
                return;
            }

            //键、值、过期时间
            redishelper.set(textbox1.text, textbox2.text, int.parse(textbox3.text));
            textbox4.text = "添加成功";
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_click(object sender, eventargs e)
        {
            if (!string.isnullorempty(textbox1.text))
            {
                if (redishelper.exists(textbox1.text))
                {
                    redishelper.remove(textbox1.text).tostring();
                    textbox4.text = "删除成功";
                }
                else
                {
                    textbox4.text = "已过期或不存在";
                }
            }
            else
            {
                textbox4.text = "请填写键";
            }
        }

        /// <summary>
        /// 获取
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_click(object sender, eventargs e)
        {
            if (!string.isnullorempty(textbox1.text))
            {
                if (redishelper.exists(textbox1.text))
                {
                    textbox4.text = redishelper.get(textbox1.text).tostring();
                }
                else
                {
                    textbox4.text = "已过期或不存在";
                }
            }
            else
            {
                textbox4.text = "请填写键";
            }
        }

        /// <summary>
        /// 分钟数--非backspace键或数字时处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textbox3_keypress(object sender, keypresseventargs e)
        {
            if (e.keychar != 8 && !char.isdigit(e.keychar))
            {
                e.handled = true;
            }
        }
    }

    5、运行结果:

Redis学习笔记:Redis在C#中的使用

 

    参考自: