.NET 中使用redis(四)

Redis 发布订阅及key过期通知!

1,应用场景:
订单过期时间可以通过redis缓存进行存放,然后redis过期之后,处理订单超时可以使用redis 的键过期触发事件通知!
redis在 2.8.0(4.0以后就开始收费了)以后的版本提供了,KeySpace Notification功能,允许客户订阅pub/Sub频道,以便以某种方式接收影响redis数据集事件。
接下来实际操作:
先看看自己的redis版本:
在这里插入图片描述
我这是3.0的版本,是支持这个事件的
2,修改redis的配置文件,怎么看,
在这里插入图片描述
应该很清晰,找到redis的配置文件之后,打开 keySpace Notification 的功能,
先看一下在这里插入图片描述

Elg 这里是组合的命令,以上不多说,重点是我们配置一下:
修改redis.conf 文件,修改notify-keyspace-events Ex
在这里插入图片描述
配置完成, 重启redis服务就可以了
实现:
1,事件通过redis 的订阅与发布功能来进行分发,
所以需要订阅 keyevent@0:expired 通道表示db0 根据自己的dbindex选择合适的数字
开始编码:

 static void Main(string[] args)
        {
            const string MessagePrefix = "Pay_OrderID_";
            const int PublishMessageCount = 5;
        Console.WriteLine("Begin publishing order messages...");
        using (var redisPublisher = new RedisClient(RedisConfig.Host, RedisConfig.Port, RedisConfig.Password, 1))  //redis默认有15个库,这里的1意思是使用 db1,默认是0
        {
            Random random = new Random();
            for (var i = 1; i <= PublishMessageCount; i++)
            {
                var message = MessagePrefix + i;
                int expirySeconds = random.Next(1, 10);
                Console.WriteLine(String.Format("{0} Publishing '{1}' expirySeconds '{2}'", DateTime.Now.ToString(), message, expirySeconds));
                redisPublisher.Set(key: message, value: message + Guid.NewGuid().ToString("N"), expiresIn: TimeSpan.FromSeconds(expirySeconds));
            }
        }
        Console.WriteLine("End publishing order messages...");
        Console.ReadKey();

    }

简单的生成5个key,随机给的过期时间,1-10秒,看看生成者实现了效果没有
在这里插入图片描述
结果是OK的,key我是放在db1里面的,接下里要去订阅一下key 的过期事件,相当于消费:

 static void Main(string[] args)
        {
            //K 键空间通知,所有通知以 keyspace@ 为前缀,这里的event指的是redis中的命令比如del、expired、list、set
            //E 键事件通知,所有通知以 keyevent@ 为前缀,
            // "__keyevent@0__:expired"   0表示db0根据自己的dbindex选择合适的数字。
            //其中必选K或E,比如开启过期通知,“Ex”或者"Kx",两者的区别在于事件名不同,不过我们可以采用模糊订阅的方式,如果开启所有事件则是“AKE”
            //redis默认是关闭这个特性的,因为打开这个特性,会消耗一定的CPU资源。故实际业务场景中我们尽量发布和订阅都约定好指定的Redis dbIndex存储空间。这样就不需要全库(0-16)去检索,否则太浪费性能了。
            //因为 Redis 目前的订阅与发布功能采取的是发送即忘策略, 所以如果你的程序需要可靠事件通知, 那么目前的键空间通知可能并不适合你:当订阅事件的客户端断开连接时,当再次连接上的时候, 它会丢失所有在断开连接期间分发给它的事件。
        /*
          举例:当 del mykey 命令执行时:
               K键空间频道的订阅者将接收到被执行的事件的名字,在这个例子中,就是 del 。
               E键事件频道的订阅者将接收到被执行事件的键的名字,在这个例子中,就是 mykey 。
         */

        //1、以事件为出发点。配置文件修改为:notify-keyspace-events Kx
        //const string ChannelName = "__keyspace@0__:Pay_OrderID_1";//监听Key所操作的事件(命令)
        //const string ChannelName = "__keyspace@0__:expired";//监听Key所操作的事件(命令)

        //2、以Key为出发点。配置文件修改为:notify-keyspace-events Ex
        const string ChannelName = "__keyevent@0__:expired";//监听Key键。但是无法监听到Key所对应的值。

        const string MessagePrefix = "Pay_OrderID_";
        Console.WriteLine("Starting Received order messages...");

        using (var redisConsumer = new RedisClient(RedisConfig.Host, RedisConfig.Port, RedisConfig.Password))
        using (var subscription = redisConsumer.CreateSubscription())
        {
            subscription.OnSubscribe = channel =>
            {
                Console.WriteLine(String.Format("Subscribed to '{0}'", channel));
            };
            subscription.OnUnSubscribe = channel =>
            {
                Console.WriteLine(String.Format("UnSubscribed from '{0}'", channel));
            };
            subscription.OnMessage = (channel, msg) =>
            {
                if (msg.StartsWith(MessagePrefix))//根据具体的业务标识来匹配筛选获取。(由于通知收到的是redis key,value已经过期,无法收到,所以需要在key上标记业务数据。)
                {
                    Console.WriteLine(String.Format(" {0} Received '{1}' from channel '{2}'", DateTime.Now.ToString(), msg, channel));
                }
            };
            subscription.SubscribeToChannels(ChannelName); //blocking
            //subscription.SubscribeToChannels(ChannelName, ChannelName, ChannelName);   // 订阅 subscribe: 订阅具体键名,  支持一次可以订阅多个
        }
    }

暂时写到这,欢迎指点!

猜你喜欢

转载自blog.csdn.net/weixin_42780928/article/details/93380149