Redis應用場景不少,如今介紹一下它的幾大特性之一 發佈訂閱(pub/sub) redis
特性介紹: 設計模式
什麼是redis的發佈訂閱(pub/sub)? Pub/Sub功能(means Publish, Subscribe)即發佈及訂閱功能。基於事件的系統中,Pub/Sub是目前普遍使用的通訊模型,它採用事件做爲基本的通訊機制,提供大規模系統所要求的鬆散耦合的交互模式:訂閱者(如客戶端)以事件訂閱的方式表達出它有興趣接收的一個事件或一類事件;發佈者(如服務器)可將訂閱者感興趣的事件隨時通知相關訂閱者。熟悉設計模式的朋友應該瞭解這與23種設計模式中的觀察者模式極爲類似。 api
一樣,Redis的pub/sub是一種消息通訊模式,主要的目的是解除消息發佈者和消息訂閱者之間的耦合, Redis做爲一個pub/sub的server, 在訂閱者和發佈者之間起到了消息路由的功能。 服務器
上面的都是概念,不知道不要緊,其實我也看不懂。 ide
簡單來說,這裏面還有個channel的概念,這裏就是頻道的意思,好比你訂閱了銀行的頻道,當你的資金髮生變更時,銀行就會經過它的頻道給你發送信息,在這裏,你是屬於被動接收的,而不是向銀行索要信息,這個例子中,你就是sub(訂閱者),而銀行就是pub(發佈者)。 測試
代碼: ui
先引入依賴 this
-
<dependency>
-
<groupId>redis.clients</groupId>
-
<artifactId>jedis</artifactId>
-
<version>2.9.0</version>
-
</dependency>
新建一個發佈者 spa
-
public class Publisher extends Thread{
-
private final JedisPool jedisPool;
-
-
public Publisher(JedisPool jedisPool) {
-
this.jedisPool = jedisPool;
-
}
-
-
@Override
-
public void run() {
-
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
-
Jedis jedis = jedisPool.getResource(); //鏈接池中取出一個鏈接
-
while (true) {
-
String line = null;
-
try {
-
line = reader.readLine();
-
if (!"quit".equals(line)) {
-
jedis.publish("mychannel", line); //從 mychannel 的頻道上推送消息
-
} else {
-
break;
-
}
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
-
}
-
}
新建一個訂閱者 設計
-
public class Subscriber extends JedisPubSub {
-
-
public Subscriber(){}
-
@Override
-
public void onMessage(String channel, String message) { //收到消息會調用
-
System.out.println(String.format("receive redis published message, channel %s, message %s", channel, message));
-
}
-
@Override
-
public void onSubscribe(String channel, int subscribedChannels) { //訂閱了頻道會調用
-
System.out.println(String.format("subscribe redis channel success, channel %s, subscribedChannels %d",
-
channel, subscribedChannels));
-
}
-
@Override
-
public void onUnsubscribe(String channel, int subscribedChannels) { //取消訂閱 會調用
-
System.out.println(String.format("unsubscribe redis channel, channel %s, subscribedChannels %d",
-
channel, subscribedChannels));
-
-
}
-
}
訂閱頻道
-
public class SubThread extends Thread {
-
private final JedisPool jedisPool;
-
private final Subscriber subscriber = new Subscriber();
-
-
private final String channel = "mychannel";
-
-
public SubThread(JedisPool jedisPool) {
-
super("SubThread");
-
this.jedisPool = jedisPool;
-
}
-
-
@Override
-
public void run() {
-
System.out.println(String.format("subscribe redis, channel %s, thread will be blocked", channel));
-
Jedis jedis = null;
-
try {
-
jedis = jedisPool.getResource(); //取出一個鏈接
-
jedis.subscribe(subscriber, channel); //經過subscribe 的api去訂閱,入參是訂閱者和頻道名
-
} catch (Exception e) {
-
System.out.println(String.format("subsrcibe channel error, %s", e));
-
} finally {
-
if (jedis != null) {
-
jedis.close();
-
}
-
}
-
}
-
}
-
測試下
-
public class PubSubDemo {
-
public static void main( String[] args )
-
{
-
// 鏈接redis服務端
-
JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), "172.31.12.18", 7379);
-
-
System.out.println(String.format("redis pool is starting, redis ip %s, redis port %d", "127.0.0.1", 7379));
-
-
SubThread subThread = new SubThread(jedisPool); //訂閱者
-
subThread.start();
-
-
Publisher publisher = new Publisher(jedisPool); //發佈者
-
publisher.start();
-
}
-
}
打印信息
