https://redis.io/topics/pubsub
a multi user high performance web chat.
与观察者模式有一些相似,区别在于消息的发布方不知道订阅方。redis在内部对消息的发布方与订阅方进行了进一步的解耦。具体的做法是:每个订阅方持有一个单独的阻塞进程,并指定一些频道(channel)。发布方通过其他的进程向指定的频道发送消息。发送消息后,订阅方接受到消息。
主要使用的方法
- SUBSCRIBE channel [channel …]
订阅方订阅频道的方法(注意使用后线程会一直处于阻塞状态,直到关闭线程) - PUBLISH channel message
发布方发布消息的方法 - UNSUBSCRIBE [channel [channel …]]
退订消息的方法(暂时不知道要怎么使用。因为订阅之后线程阻塞无法输入命令,只能退出。退出之后,那之前的订阅其实是属于别人的。应该是在更复杂一些的情况下使用吧)
其中SUBSCRIBE 与 UNSUBSCRIBE 命令在前面加上P,也就是PSUBSCRIBE、PUNSUBSCRIBE,允许使用模式匹配(就是正则表达式)来指定频道。
- PSUBSCRIBE pattern [pattern …]
- PUNSUBSCRIBE [pattern [pattern …]]
举个例子
PSUBSCRIBE aaa*
将会订阅所有以aaa开头的频道。
示例 dos
- 订阅者
- 发布者
返回值为订阅者的数量。
这时所有订阅ch1的接受者会收到消息
示例 java
主要使用了JedisPubSub类。使用时需要继承这个类,并实现一些需要的方法。比如
JedisPubSub sub = new JedisPubSub() {
@Override
public void onMessage(String channel, String message) {
// TODO Auto-generated method stub
System.out.println("channel : " + channel + " message : " + message);
super.onMessage(channel, message);
}
};
onMessage方法会在接收到消息是触发。
完整示例
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
public class TestRedisSub {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Jedis jd = new Jedis("localhost", 6379);
JedisPubSub sub = new JedisPubSub() {
@Override
public void onMessage(String channel, String message) {
// TODO Auto-generated method stub
System.out.println("channel : " + channel + ", message : " + message);
super.onMessage(channel, message);
}
};
new Thread(){
@Override
public void run() {
Jedis pub = new Jedis("localhost", 6379);
try {
super.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
pub.publish("ch1", "test message");
pub.close();
}
}.start();
jd.subscribe(sub, "ch1");
}
}