当前位置: 移动技术网 > IT编程>数据库>MongoDB > Redis学习笔记:Redis在C#中的使用

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

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

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

    2、在nuget中安装stackexchange.redis。

    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、运行结果:

 

    参考自:

    

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网