Jedis实现发布订阅功能

Redis为我们提供了publish/subscribe(发布/订阅)功能。我们可以对某个channel(频道)进行subscribe(订阅),当有人在这个channel上publish(发布)消息时,redis就会通知我们,这样我们可以收到别人发布的消息。
作为Java的redis客户端,Jedis提供了publish/subscribe的接口。本文讲述如何使用Jedis来实现redis的publish/subscribe。

定义Subscriber类

Jedis定义了抽象类JedisPubSub,在这个类中,定义publish/subsribe的回调方法。通过继承JedisPubSub类并重新实现这些回调方法,当publish/subsribe事件发生时,我们可以定制自己的处理逻辑。

在以下例子中,我们定义了Subscriber类,这个类继承了JedisPubSub类,并重新实现了其中的回调方法。

import redis.clients.jedis.JedisPubSub;

public class Subscriber extends JedisPubSub {
    public Subscriber() {
    }

    public void onMessage(String channel, String message) {
        System.out.println(String.format("receive redis published message, channel %s, message %s", channel, message));
    }

    public void onSubscribe(String channel, int subscribedChannels) {
        System.out.println(String.format("subscribe redis channel success, channel %s, subscribedChannels %d",
                channel, subscribedChannels));
    }

    public void onUnsubscribe(String channel, int subscribedChannels) {
        System.out.println(String.format("unsubscribe redis channel, channel %s, subscribedChannels %d",
                channel, subscribedChannels));

    }
}
 

定义SubThread线程类

由于Jedis的subscribe操作是阻塞的,因此,我们另起一个线程来进行subscribe操作。

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

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);
        } catch (Exception e) {
            System.out.println(String.format("subsrcibe channel error, %s", e));
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }
}

在上面的代码中,我们从JedisPool获取一个Jedis实例,并使用这个Jedis实例进行subscribe的操作。
Jedissubscribe的声明如下:

public void subscribe(final JedisPubSub jedisPubSub, final String… channels)

第一个参数接受一个JedisPubSub对象,第二个参数指定对哪个频道进行订阅。上例中,我们把我们定义的Subscriber对象传给subscribe方法。
当publish/subscribe的事件发生时,会自动调用我们Subscriber的方法。

定义Publisher类

Publisher类接受用户的输入,并将输入发布到channel。当用户输入”quit”后,输入结束。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class Publisher {
    private final JedisPool jedisPool;

    public Publisher(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
    }

    public void start() {
        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);
                } else {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
         }
    }
}

定义入口代码

如下是我们的程序入口代码。

import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class PubSubDemo
{
    public static void main( String[] args )
    {
        // 替换成你的reids地址和端口
        String redisIp = "192.168.229.154";
        int reidsPort = 6379;
        JedisPool jedisPool = new JedisPool(new JedisPoolConfig(), redisIp, reidsPort);
        System.out.println(String.format("redis pool is starting, redis ip %s, redis port %d", redisIp, reidsPort));

        SubThread subThread = new SubThread(jedisPool);
        subThread.start();

        Publisher publisher = new Publisher(jedisPool);
        publisher.start();
    }
}

在上面的代码中,我们首先生成了一个JedisPool的redis连接池,这是由于Jedis不是线程安全的,JedisPool是线程安全的。而我们的程序在主线程和订阅线程(SubThread)均需要使用Jedis,故在程序中我们使用JedisPool。具体也可以参考在多线程环境中使用Jedis
由于Jedis的subcribe操作是阻塞的,故我们另起了一个线程来进行subcribe操作。
通过调用Publisher::start()方法,接受用户的输入,并publish到指定的channel。

输出

redis pool is starting, redis ip 192.168.229.154, redis port 6379
subscribe redis, channel mychannel, thread will be blocked
subscribe redis channel success, channel mychannel, subscribedChannels 1

这时输入

hello

控制窗口中输出

receive redis published message, channel mychannel, message hello

参考资料

时间: 2024-10-06 02:24:28

Jedis实现发布订阅功能的相关文章

redis发布订阅功能介绍

redis的发布订阅功能(publish/subscribe): 频道:消息队列 subscribe:订阅一个或多个队列 >help subscribe   #查看subscribe帮助 例:订阅news频道 > subscribe news 注:可以同时订阅多个频道 publish:向频道中发消息 >help @pubsub #查看publish帮助 例:向news频道发送消息 >publish new hello psubscribe:模式订阅-->可以使用正则表达式,一

SQL Server发布订阅功能研究

前提:发布订阅只能是同一个内网的机器上才能使用,其实这个可以用配置管理器的别名功能设置之后就可以了,外网的也能通过这样的方式来搞. 配置过程参考老D的文章:http://www.cnblogs.com/daizhj/archive/2009/11/18/1605293.html SQL Server发布订阅功能测试: (我发觉这个功能很不行,为什么不行,我下面其中一台设置错误了就要全部重来,那么如果我下面有几百台机器,怎么重来?) 1.采用发布订阅机制只能是读写分离的方案,也就是说A发布B订阅,

关于SQL SERVER 2008 R2发布订阅功能

实现功能:主服务器维护数据的变更,从服务器需要时同步主服务器的数据. 配置:主从服务器均为SQL SERVER 2008 R2. 实现方法: 预备: 1.主从服务器需建立同一账户名及密码的账户(当时我认为是权限问题,只要设置好文件夹的权限即可,但后来发现貌似不是这么回事,从服务器实现同步的时候需要调用主服务器的SQLSERVER代理服务,所以需要使用其用户账户及密码),不需要管理员权限,将主从服务器上的SQLSERVER代理服务的用户更改成新建的用户. 2.在主服务器上建立一个共享文件夹,确保刚

利用reids实现发布订阅的功能

redis现在比较长用做缓存服务器,nosql数据库,同时它还具有实现消息的发布订阅的功能.本篇文章将会实现一个用redis实现发布订阅功能的一个demo 首先用一个实体对象 package com.wtf.demo.redis; import java.io.Serializable; public class UserBean implements Serializable {    private String username;    private String address;   

发布-订阅模式

1.什么是发布订阅模式 发布订阅模式 又叫观察者模式,他是定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变,所有依赖他的对象都将得到通知. 在javascript开发中,我们一般用事件模型来替代传统的发布-订阅模式. 2.Dom事件 实际上,只要我们曾经在dom节点上绑定过事件函数,那么我们就曾经使用过发布-订阅模式. document.getElementById('test').addEventListener('click',function(){ alert(2)},fasle

JavaScript设计模式与开发实践---读书笔记(8) 发布-订阅模式

发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 发布-订阅模式可以广泛应用于异步编程中,这是一种替代传递回调函数的方案. 可以取代对象之间硬编码的通知机制,一个对象不用再显式地调用另外一个对象的某个接口. 自定义事件 首先要指定好谁充当发布者: 然后给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者: 最后发布消息时,发布者会遍历这个缓存列表,依次触发里面存放的订阅者回调函数. 另外,我们还可以往回调函数里填入

StackExchange.Redis 使用-发布订阅 (二)

使用Redis的发布订阅功能 redis另一个常见的用途是发布订阅功能 . 它非常的简单 ,当连接失败时 ConnectionMultiplexer 会自动重新进行订阅 . ISubscriber sub = redis.GetSubscriber(); GetSubscriber 方法返回一个 ISubscriber 类型的实例 .发布订阅功能没有数据库的概念,我们可以为其提供一个 async-state .所有的订阅都是全局的:ISubscriber 实例不是他们的生命周期 , 发布订阅的特

Javascript中理解发布--订阅模式

阅读目录 发布订阅模式介绍 如何实现发布--订阅模式? 发布---订阅模式的代码封装 如何取消订阅事件? 全局--发布订阅对象代码封装 理解模块间通信 回到顶部 发布订阅模式介绍 发布---订阅模式又叫观察者模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知. 现实生活中的发布-订阅模式: 比如小红最近在淘宝网上看上一双鞋子,但是呢 联系到卖家后,才发现这双鞋卖光了,但是小红对这双鞋又非常喜欢,所以呢联系卖家,问卖

sql server 主从数据库同步 利用发布 订阅是实现

发布订阅功能自SQL 2005之后就有了 配置方法可参考:http://blog.csdn.net/wanmdb/article/details/7515277 遇到问题: 1. 如果代理无法启动 ,请执行下图配置 2. sql server2008复制报错由于出现操作系统错误 3,进程无法读取文件“D:\Program Files (x86)\sql server\ReplData\ 2014年03月04日 ⁄ Sql Server ⁄ 共 625字 ⁄ 字号 小 中 大 ⁄ 暂无评论 ⁄ 阅