redis 的发布/订阅模式

使用redis客户端实现

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。一个redis客户端可以订阅任意多大频道channel,一个频道也可以被多个客户端订阅。 1.创建并监听频道

  • 通过指令SUBSCRIBE订阅一个频道,如果频道不存在时则新建一个频道,以下语句创建一个名称为mySubscribe的频道:
127.0.0.1:6379> SUBSCRIBE mySubscribe
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "mySubscribe"
3) (integer) 1

复制代码
  • 此时创建了该频道的redis客户端监听了此频道,相当于一个订阅者。

2.向创建的频道发送一条消息

  • 指令PUBLISH channel message 负责向一个频道发送一条消息;打开一个新的redis客户端,向刚才创建的频道发送消息。
127.0.0.1:6379> publish mySubscribe  "Redis is a great caching technique"
(integer) 1

复制代码
  • 第一个redis客户端(创建并监听了频道mySubscribe)将会受到刚发布的这条消息
127.0.0.1:6379> SUBSCRIBE mySubscribe
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "mySubscribe"
3) (integer) 1
1) "message"
2) "mySubscribe"
3) "Redis is a great caching technique"
复制代码

Java使用Jedis实现redis的发布/订阅功能

同样实现上一篇文章中的例子

1.订阅者需要继承抽象类JedisPubSub;重写方法onMessage接收发布者发送的消息,

public class Farmer extends JedisPubSub{
    private static final Logger logger = Logger.getLogger(pubsub.Farmer.class);

    @Override
    public void onMessage(String channel, String message) {
        logger.info(String.format("client: FARMER. Message. Channel: %s, Msg: %s", channel, message));
        if("rain".equals(message)){
            logger.info("FARMER : a satisfied day!!!");
        }else if("sunny".equals(message)){
            logger.info("FARMER : a terrible day!!!");
        }else {
            logger.info("FARMER : Spam messages");
        }
    }
}


public class Worker extends JedisPubSub {
    private static final Logger logger = Logger.getLogger(pubsub.Farmer.class);

    @Override
    public void onMessage(String channel, String message) {
        logger.info(String.format("client: WORKER. Message. Channel: %s, Msg: %s", channel, message));
        if("rain".equals(message)){
            logger.info("WORKER : a satisfied day!!!");
        }else if("sunny".equals(message)){
            logger.info("WORKER : a terrible day!!!");
        }else {
            logger.info("WORKER : Spam messages");
        }
    }

}

public class Programmer extends JedisPubSub {

    private static final Logger logger = Logger.getLogger(pubsub.Farmer.class);

    @Override
    public void onMessage(String channel, String message) {
        logger.info(String.format("client: PROGRAMMER. Message. Channel: %s, Msg: %s", channel, message));
        if("rain".equals(message)){
            logger.info("PROGRAMMER : a satisfied day!!!");
        }else if("sunny".equals(message)){
            logger.info("PROGRAMMER : a terrible day!!!");
        }else {
            logger.info("PROGRAMMER : Spam messages");
        }
    }

}

复制代码

2.定义发布者

public class WeatherServer{

    public void publishMessage(Jedis jedis,String channel,String msg) {
        jedis.publish(channel,msg);
    }
}

复制代码

3.测试类

public class Main {
    public static final String CHANNEL_NAME = "MyChannel";
    public static final String REDIS_HOST = "localhost";
    public static final int REDIS_PORT = 6379;

    private final static Logger logger = Logger.getLogger(Main.class);
    private final static JedisPoolConfig POOL_CONFIG = new JedisPoolConfig();
    private final static JedisPool JEDIS_POOL =
            new JedisPool(POOL_CONFIG, REDIS_HOST, REDIS_PORT, 0);

    public static void main(String[] args) throws Exception {

        PropertyConfigurator.configure("src/log4j.properties");
        /*订阅者redis客户端*/
        final Jedis farmerJedis = JEDIS_POOL.getResource();
        final Jedis workerJedis = JEDIS_POOL.getResource();
        final Jedis programmerJedis = JEDIS_POOL.getResource();

        /*发布者redis*/
        final Jedis publisherJedis = JEDIS_POOL.getResource();

        final Farmer farmer = new Farmer();
        final Worker worker = new Worker();
        final Programmer programmer  = new Programmer();

        //订阅线程:接收消息,因为Jedis是以阻塞的方式等待发布者消息的,所以每个Jedis客户端必须对应一个独立的线程。不然只会有第一个Jedis接受到消息。
        new Thread(new Runnable() {
            public void run() {
                try {
                    farmerJedis.subscribe(farmer,CHANNEL_NAME);
                    logger.info("Subscription ended.");
                } catch (Exception e) {
                    logger.error("Subscribing failed.", e);
                }
            }
        }).start();

        new Thread(new Runnable() {
            public void run() {
                try {
                    workerJedis.subscribe(worker,CHANNEL_NAME);
                    logger.info("Subscription ended.");
                } catch (Exception e) {
                    logger.error("Subscribing failed.", e);
                }
            }
        }).start();

        new Thread(new Runnable() {
            public void run() {
                try {
                    programmerJedis.subscribe(programmer,CHANNEL_NAME);
                    logger.info("Subscription ended.");
                } catch (Exception e) {
                    logger.error("Subscribing failed.", e);
                }
            }
        }).start();

        //主线程:发布消息到CHANNEL_NAME频道上
        WeatherServer weatherServer = new WeatherServer();
        weatherServer.publishMessage(publisherJedis,CHANNEL_NAME,"rain");
        
        farmerJedis.close();
        workerJedis.close();
        programmerJedis.close();
    }
}

复制代码

订阅者是根据channel的名字接收发布者发布的消息的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值