客户端可以通过执行 subscribe 命令订阅一个或多个频道,每当有其他客户端向被订阅的频道发送消息时,频道所有的订阅者都会收到这条消息。

客户端还可以通过执行 psubscribe 命令订阅一个或多个模式,消息也会被发送给与频道相匹配模式的订阅者。

频道的订阅与退订

当一个客户端执行 subscribe 命令定于某个频道的时候,就与被订阅频道之间建立起了一种订阅关系。所有频道的订阅关系都保存在服务器状态的 pubsub_channels 字典中,字典的键是被订阅的频道,值是记录了所有订阅这个频道的客户端。

struct redisServer {
// ...
dict *pubsub_channels; /* Map channels to list of subscribed clients */
// ...
}

订阅频道

每当执行订阅命令时,服务器会将客户端与被订阅的频道在 pubsub_channels 字典中进行关联。频道中已经有其他订阅者,将客户端添加到订阅者链表的末尾;如果还没有订阅者,那么程序首先在 pubsub_channels 字典中为频道创建一个键,并为这个键的值设置为空链表,然后再将客户端添加到链表。

退订频道

订阅频道的逆向过程。从链表中删除客户端,如果链表为空了,则删除这个频道。

模式的订阅与退订

模式的订阅关系保存在 pubsub_patterns 链表属性里。

struct redisServer {
// ...
dict *pubsub_channels; /* Map channels to list of subscribed clients */
// ...
}

每个节点都包含着一个 pubsubPattern 结构:

typedef struct pubsubPattern {
redisClient *client;
robj *pattern;
} pubsubPattern;

client 属性记录了订阅模式的客户端,parttern 属性记录了被订阅的模式。

订阅模式

当客户端执行 psubscribe 命令订阅某个模式时,服务器会对每个订阅的模式新建一个 pubsubPattern 结构,将结构的 client 属性设置为订阅模式的客户端, pattern 设置为订阅的模式。然后将pubsubPattern 结构 添加到 pubsub_patterns 链表的表尾。

退订模式

订阅模式的反操作。在 pubsub_patterns 链表中查找并删除指定 pattern 和 client 的pubsubPattern 结构。

发送消息

当一个 Redis 客户端执行 publish channel message 命令发送给频道 channel 的时候,服务器会将消息 发送给 channel 频道的订阅者,然后发送给模式的订阅者。

发送给频道订阅者

在 pubsub_channels 字典里找到频道 channel 的订阅者名单,并将消息依次发送给所有客户端。

发送给模式订阅者

遍历整个 pubsub_patterns 链表,查找与 channel 频道想匹配的模式,并将消息发送给这些模式的客户端。

查看订阅消息

客户端可以通过 pubsub 这个命令查看频道或模式的相关信息,比如某个频道有多少订阅者,某个模式有多少订阅者。它有三个子命令:

pubsub channels

pubsub channels [pattern],用于返回服务器当前被订阅的频道。其中 pattern 是可选参数,不选默认为查询所有。

127.0.0.1:6379> pubsub channels
1) "liushijie"

pubsub numsub

pubsub numsub [channel-1 channel-2 ... channel-n],用于接收任意多个频道作为输入参数并返回这些频道订阅者的数量。必须要有一个频道,否则查出的是空值。

127.0.0.1:6379> pubsub numsub liushijie
1) "liushijie"
2) (integer) 4

pubsub numpat

pubsub numpat 命令用户返回服务器当前被订阅模式的数量。

127.0.0.1:6379> pubsub numpat
(integer) 0

java 实现

// 发布者
import redis.clients.jedis.Jedis; public class Publish {
public static void main(String[] args) throws InterruptedException {
Jedis jedis = new Jedis("127.0.0.1", 6379); while (true) {
jedis.publish("liushijie", System.currentTimeMillis() + "");
Thread.sleep(2000);
} }
} // 订阅者
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub; public class SubScribe {
public static void main(String[] args) { new Thread(new SubscribeRunnable()).start();
new Thread(new SubscribeRunnable()).start();
new Thread(new SubscribeRunnable()).start(); } private static class SubscribeRunnable implements Runnable { @Override
public void run() {
Jedis receiver = new Jedis("127.0.0.1", 6379);
receiver.subscribe(new JedisPubSub() {
@Override
public void onMessage(String channel, String message) {
System.out.println(channel + " got message " + message);
} @Override
public void onPMessage(String pattern, String channel, String message) { } @Override
public void onSubscribe(String channel, int subscribedChannels) { } @Override
public void onUnsubscribe(String channel, int subscribedChannels) { } @Override
public void onPUnsubscribe(String pattern, int subscribedChannels) { } @Override
public void onPSubscribe(String pattern, int subscribedChannels) { }
}, "liushijie");
}
} }

Redis学习笔记四:独立功能之发布与订阅的更多相关文章

  1. Redis学习笔记(十九) 发布订阅(上)

    Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息,它的发布与订阅功能由PUBLISH.SUBSCRIBE.PSUBSCRIBE等命令组成. ...

  2. StackExchange.Redis学习笔记(四) 事务控制和Batch批量操作

    Redis事物 Redis命令实现事务 Redis的事物包含在multi和exec(执行)或者discard(回滚)命令中 和sql事务不同的是,Redis调用Exec只是将所有的命令变成一个单元一起 ...

  3. JavaScript学习笔记(四)——jQuery插件开发与发布

    jQuery插件就是以jQuery库为基础衍生出来的库,jQuery插件的好处是封装功能,提高了代码的复用性,加快了开发速度,现在网络上开源的jQuery插件非常多,随着版本的不停迭代越来越稳定好用, ...

  4. Redis学习笔记(二十) 发布订阅(下)

    当一个客户端执行SUBSCRIBE命令订阅某个或某些频道时,这个客户端与被订阅频道之间就建立起了一种订阅关系. Redis将所有频道的订阅关系保存在服务器状态的pubsub_channels字典里面, ...

  5. Redis 学习笔记四 Mysql 与Redis的同步实践

    一.测试环境在Ubuntu kylin 14.04 64bit 已经安装Mysql.Redis.php.lib_mysqludf_json.so.Gearman. 点击这里查看测试数据库及表参考 本文 ...

  6. redis学习笔记(详细)——高级篇

    redis学习笔记(详细)--初级篇 redis学习笔记(详细)--高级篇 redis配置文件介绍 linux环境下配置大于编程 redis 的配置文件位于 Redis 安装目录下,文件名为 redi ...

  7. redis 学习笔记(6)-cluster集群搭建

    上次写redis的学习笔记还是2014年,一转眼已经快2年过去了,在段时间里,redis最大的变化之一就是cluster功能的正式发布,以前要搞redis集群,得借助一致性hash来自己搞shardi ...

  8. Redis学习笔记4-Redis配置详解

    在Redis中直接启动redis-server服务时, 采用的是默认的配置文件.采用redis-server   xxx.conf 这样的方式可以按照指定的配置文件来运行Redis服务.按照本Redi ...

  9. Redis学习笔记(1)——Redis简介

    一.Redis是什么? Remote Dictionary Server(Redis) 是一个开源的使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化的日志型.Key-Value ...

随机推荐

  1. 问题导向VS目标导向:领导者要倾向哪种?

    人类进步的驱动: 问题驱动:目标驱动: 两者相互影响: 问题驱动是起点,并且在很多杂乱的问题中只有少数可以转化为目标,从而成为进步的动力:多数问题只是以干扰的形式出现. 问题驱动是被动的,并且常常干扰 ...

  2. HTML5预学习 长期更新

    HTML5 仍处于完善之中. 为 HTML5 建立的一些规则:          新特性应该基于 HTML.CSS.DOM 以及 JavaScript.          减少对外部插件的需求(比如 ...

  3. 日志分析 第六章 安装elasticsearch

    在这里,以两台es集群为例. es集群健康状况有三种状态,这里我们搭建的es集群,只要两台不同时挂掉,数据不会丢失. green 所有主要分片和复制分片都可用 yellow 所有主要分片可用,但不是所 ...

  4. 分页探究--Filter+JSTL

    最近卡了一个功能就是分页,查了很多资料,分页大概是两种类型:一种是把数据库的东西全部查出来然后放在session里,用list一页一页传到页面,这样的消耗比较大;另一种就是使用sql语句的limit来 ...

  5. Eclipse Maven Web工程报错:java.lang.ClassNotFoundException: ContextLoaderListener

    原因:打包项目时没有把相关Maven依赖包打到WEB-INF/lib下,正常情况下,会生成lib目录并把工程的所有依赖jar包都部署到该目录下. 解决:右键点击项目--选择Properties,选择D ...

  6. Maven打包可执行jar

    参考文献:http://blog.csdn.net/xiao__gui/article/details/47341385 方法:使用assembly插件,生成的jar包名为xxx-jar-with-d ...

  7. VIM辅导:视频教程,文档资料,经典插件

    VIM辅导:25个vim视频' 教程 '资源   转自: http://blog.jobbole.com/10250/ 编注:@程序员的那些事 12月14日在新浪微博发起的<你最常用哪些文本编辑 ...

  8. CSS3 让图片镜像对称

    1.HTML代码 <!DOCTYPE html> <html> <head> <title>test</title> </head&g ...

  9. ILMerge

    ILMerge http://www.microsoft.com/en-hk/download/details.aspx?id=17630 ILMerge 下载地址:http://www.micros ...

  10. HTTP 学习

    *** *** http://www.w3school.com.cn/xml/xml_http.asp *** *** http://www.cnblogs.com/shenliang123/arch ...