本文Redis所在系统:Linux

  本文运用程序所在系统:windows7

一 win7 CRT下 redis的常用命令:

  1 启动redis 服务端:redis-server

  2 启动redis 客户端:redis-cli

  3 关闭redis 服务端:redis-cli -a 123456 shutdown (-a 123456在redis设置了密码的情况下使用)

  4 设置redis连接密码:config set requirepass 123456 (123456 是设置的密码,关闭服务器后密码会失效,需要重新设置

  5 授权登入:auth 123456  (123456 是设置的密码,当redis设置了密码时,真正使用redis设置或读取数据需要密码授权)

  6  订阅redis消息频道:SUBSCRIBE china (china是频道名称,可以同时订阅多个频道,以空格隔开)

   

redis的订阅发布 redis订阅发布,接收方法报错_redis的订阅发布

  7 redis频道上发布信息:publish china hello (china是频道名称,hello是消息内容)

   

redis的订阅发布 redis订阅发布,接收方法报错_linux_02

 显示2表示当前频道被订阅的数量有2个,本机Java程序也同时订阅了china频道

 

 二  Java运用程序连接远程Linux环境下redis的常见错误

  显示连接被拒绝

Caused by: redis.clients.jedis.exceptions.JedisConnectionException: java.net.ConnectException: Connection refused: connect

 分析原因:查看redis.conf文件内容可以看出,redis默认只运行本机连接

redis的订阅发布 redis订阅发布,接收方法报错_消息发布订阅_03

  解决方法:找到如上图的bind 127.0.0.1,改为bind 0.0.0.0,然后重启redis 服务器即可

  2 缺乏授权

redis.clients.jedis.exceptions.JedisDataException: DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections are only accepted f....

  分析原因:出现授权的问题一般来说连接登入可能出现需要密码的问题,或者需要取消保护模式的问题,查看redis.conf文件内容可以看出模式是保护的模式

redis的订阅发布 redis订阅发布,接收方法报错_redis_04

 解决方法1:找到 如上图的protected-mode yes,改为protected-mode no,,然后重启redis 服务器即可

 解决方法2:设置redis密码,此时java运用程序连接也需要使用密码连接

    最常见的Linux端口对外开放的问题

         因为redis服务器部署在Linux上,肯定会出现开放端口的常见问题

    开放端口的解决方法:

方法一:命令行方式
               1. 开放端口命令: /sbin/iptables -I INPUT -p tcp --dport 8080 -j ACCEPT
               2.保存:/etc/rc.d/init.d/iptables save
               3.重启服务:/etc/init.d/iptables restart
               4.查看端口是否开放:/sbin/iptables -L -n
    

 方法二:直接编辑/etc/sysconfig/iptables文件
               1.编辑/etc/sysconfig/iptables文件:vi /etc/sysconfig/iptables
                   加入内容并保存:-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8080 -j ACCEPT
               2.重启服务:/etc/init.d/iptables restart
               3.查看端口是否开放:/sbin/iptables -L -n

 三 Java消息订阅发布的运用程序案例

  依赖的jar:

redis的订阅发布 redis订阅发布,接收方法报错_redis的订阅发布_05

 1  消息订阅的程序片段

import org.apache.log4j.Logger;
import redis.clients.jedis.JedisPubSub;

/**
 * 订阅者
 */
public class Subscriber extends JedisPubSub {//注意这里继承了抽象类JedisPubSub

    private static final Logger LOGGER = Logger.getLogger(Subscriber.class);

    @Override
    public void onMessage(String channel, String message) {
        LOGGER.info(String.format("onMessage 接收消息 Message. Channel: %s, Msg: %s", channel, message));
    }

    @Override
    public void onPMessage(String pattern, String channel, String message) {
    	LOGGER.info(String.format("onPMessage 接收消息 PMessage. Pattern: %s, Channel: %s, Msg: %s",
    	    pattern, channel, message));
    }

    @Override
    public void onSubscribe(String channel, int subscribedChannels) {

        LOGGER.info("onSubscribe 订阅  channel:"+channel+" ;subscribedChannels:"+subscribedChannels);
    }

    @Override
    public void onUnsubscribe(String channel, int subscribedChannels) {

        LOGGER.info("onUnsubscribe 取消订阅 channel:"+channel+" ;subscribedChannels:"+subscribedChannels);
    }

    @Override
    public void onPUnsubscribe(String pattern, int subscribedChannels) {

        LOGGER.info("onPUnsubscribe 取消订阅 channel:"+pattern+" ;subscribedChannels:"+subscribedChannels);
    }

    @Override
    public void onPSubscribe(String pattern, int subscribedChannels) {

        LOGGER.info("onPSubscribe 订阅  channel:"+pattern+" ;subscribedChannels:"+subscribedChannels);
    }
}

  2 消息发布的程序片段

import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;

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

/**
 * 发布者
 */
public class Publisher {

    private static final Logger LOGGER = Logger.getLogger(Publisher.class);
    private final Jedis publisherJedis;
    private final String channel;

    public Publisher(Jedis publisherJedis, String channel) {
        this.publisherJedis = publisherJedis;
        this.channel = channel;
    }

    /**
     * 不停的读取输入,然后发布到channel上面,遇到quit则停止发布。
     */
    public void startPublish() {
        LOGGER.info("Type your message (quit for terminate)");
        try {
            publisherJedis.publish(channel, "先发一条初始信息aaaaaaaaaaaaaa");
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            while (true) {
                String line = reader.readLine();
                if (!"quit".equals(line)) {
                    publisherJedis.publish(channel, line);
                } else {
                    break;
                }
            }
        } catch (IOException e) {
            LOGGER.error("IO failure while reading input", e);
        }
    }
}

3 主函数

public class MainClass {

    public static final String CHANNEL_NAME = "china";//频道
    public static final String REDIS_HOST = "192.168.1.11";
    public static final int REDIS_PORT = 6379;

    private final static Logger LOGGER = Logger.getLogger(MainClass.class);
    private final static JedisPoolConfig POOL_CONFIG = new JedisPoolConfig();
    //private final static JedisPool JEDIS_POOL = new JedisPool(POOL_CONFIG, REDIS_HOST, REDIS_PORT, 10000);
    private final static JedisPool JEDIS_POOL = new JedisPool(POOL_CONFIG, REDIS_HOST, REDIS_PORT, 10000,"123456");

    public static void main(String[] args) throws Exception {
        final Jedis subscriberJedis = JEDIS_POOL.getResource();
        final Jedis publisherJedis = JEDIS_POOL.getResource();
        final Subscriber subscriber = new Subscriber();
        //订阅线程:接收消息
        new Thread(new Runnable() {
            public void run() {
                try {
                    LOGGER.info("Subscribing to \"MyChannel\". This thread will be blocked.");
                    //使用subscriber订阅CHANNEL_NAME上的消息,这一句之后,线程进入订阅模式,阻塞。
                    subscriberJedis.subscribe(subscriber, CHANNEL_NAME);//订阅

                    LOGGER.info("Subscription ended.");
                } catch (Exception e) {
                    LOGGER.error("Subscribing failed.", e);
                }
            }
        }).start();

        Thread.sleep(2000);

        //主线程:发布消息到CHANNEL_NAME频道上
        new Publisher(publisherJedis, CHANNEL_NAME).startPublish();//进入发布消息程序
        publisherJedis.close();

        //Unsubscribe
        subscriber.unsubscribe(); //取消订阅
        subscriberJedis.close();
    }
}

  注:命令窗口的消息发布和订阅会与程序中的同步