【转】redis的发布与订阅

Redis命令中的Pub/Sub

Redis在 2.0之后的版本中 实现了 事件推送的  发布订阅命令

以下是Redis关于发布和订阅提供的相关命令

SUBSCRIBE channel [channel ...]

订阅给定的一个或多个频道的信息。

PSUBSCRIBE pattern [pattern ...]

订阅一个或多个符合给定模式的频道。

PUBLISH channel message

将信息 message 发送到指定的频道 channel 。

PUBSUB <subcommand> [argument [argument ...]]

查看所有活跃的频道

PUNSUBSCRIBE [pattern [pattern ...]]

客户端退订所有订阅的给定模式的频道

UNSUBSCRIBE [channel [channel ...]]

指示客户端退订给定的频道。

这里的频道可以分为两类,一种是指定名称的频道,还有一种是模糊匹配的频道(模式),两种类型的频道 订阅和退订所需要的命令是不同的

下面分别演示下这些命令的基本用法

【转】redis的发布与订阅【转】redis的发布与订阅

上图中左边客户端订阅了msg频道的消息 。 另一个客户端对msg频道发布消息,订阅的客户端成功接收到消息。

我们用pubsub命令来查询所有的活跃频道。当前有一个活跃频道msg

【转】redis的发布与订阅【转】redis的发布与订阅

这里左边的客户端订阅了符合给定模式news.*的模式频道,另一个客户端向news.it 来发送消息,成功接收。

调用pusub查看活跃频道时为空,因为模式频道的订阅不算在活跃频道内

在dos命令下订阅后界面就卡住等待消息了,所以没办法来演示取消订阅的命令。就不贴图了

StackExchange.Redis中的发布和订阅

使用StackExchange.Redis发布和订阅首先需要通过connection获取一个Subscriber,该类实现了ISubscriber 接口,接口中定义了相应的Subscribe,Publish等相关函数。

用法比较简单,直接上代码了

public class RedisSubPub
    {
        public void SubScribe(string cnl)
        {
            Console.WriteLine("主线程:" + Thread.CurrentThread.ManagedThreadId);
            var sub = StackExchangeRedisHelper.Instance.GetSubscriber();
            sub.Subscribe(cnl, SubHandel);
            Console.WriteLine("订阅了一个频道:"+ cnl);
        }
        public void SubHandel(RedisChannel cnl, RedisValue val)
        {
            Console.WriteLine();
            Console.WriteLine("频道:" + cnl + "\t收到消息:" + val); ;
            Console.WriteLine("线程:" + Thread.CurrentThread.ManagedThreadId + ",是否线程池:" + Thread.CurrentThread.IsThreadPoolThread);
            if (val == "close")
                StackExchangeRedisHelper.Instance.GetSubscriber().Unsubscribe(cnl);
            if (val == "closeall")
                StackExchangeRedisHelper.Instance.GetSubscriber().UnsubscribeAll();
        }
    }
static void Main(string[] args)
        {
            RedisSubPub r = new RedisSubPub();
            r.SubScribe("it");
            r.SubScribe("news");
            r.SubScribe("sport");
            r.SubScribe("others*");
            Console.Read();
        }

我用程序中的代码作为订阅者,订阅了四个频道,然后在Dos命令行窗口中向响应的频道来发送消息

【转】redis的发布与订阅【转】redis的发布与订阅

程序运行之后StackExchange.Redis默认订阅了一个__Booksleeve_MasterChanged 频道,这个订阅主要是在Redis集群的主从配置发生改变时会触发,我们忽略掉它

在客户端我订阅了三个频道,以及一个others*模式频道。通过pubsub命令查询到了3个频道

订阅者调用Unsubscribe来取消订阅特定的频道,通过UnsubscribeAll取消订阅所有的频道

Redis是没有提供取消订阅所有频道的命令的,StackExchange.Redis通过把每一个订阅的频道都加到一个字典中,然后取消的时候会从字典中来查询要取消的频道名称。

StackExchange.Redis源代码片段如下

【转】redis的发布与订阅

【转】redis的发布与订阅

这段代码也可以看出来保持订阅频道正确工作的前提是保持一个静态的连接实例!