Jedis发布订阅

原文:https://www.jianshu.com/p/92b331355b8d
订单超时未支付自动关闭实现的几种方式:
1,Quartz 任务调度框架,更适合周期性的执行任务,对于订单超时未支付,只能采用5分钟一轮询数据库的形式实现
2,Timer java原生定时工具,可少量使用,当数据量大时,性能不好控制
3,Quartz + Timer 周期轮询(5分钟)数据库,查询出5分钟之内将要超时的订单,然后多线程创建timer完成订单的定时,这种实现方式比较复杂,但是可以在性能和功能方面,是可以实现的
4,reids 键空间通知
以下将介绍此种方式
(其实用的是Spring-data的方式,不过网上能找到的就只有这种了好像)
redis 键空间通知实现
过期事件通过Redis的订阅与发布功能(pub/sub)来进行分发。
redis服务端配置
超时的监听,并不需要自己发布,只有修改配置文件redis.conf中的:
notify-keyspace-events Ex,默认为notify-keyspace-events “”
E:启用keyevent键事件通知,客户端可以使用keyevent@为前缀的格式使用订阅功能;
x:启用对过期事件的监控;

Spring-mybatis.xml中的配置

<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
		  p:host-name="${redis.host}" p:port="${redis.port}"
		  p:password="${redis.pass}"  p:pool-config-ref="jedisPoolConfig" />

	<bean id="messageListener"
		  class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter">
		<constructor-arg>
			<bean class="com.wjh.listener.MyRedisKeyExpiredMessageDelegate" />
		</constructor-arg>
	</bean>

	<bean id="redisContainer" class="org.springframework.data.redis.listener.RedisMessageListenerContainer">
		<property name="connectionFactory" ref="connectionFactory" />
		<property name="messageListeners">
			<map>
				<entry key-ref="messageListener">
					<list>
						<bean class="org.springframework.data.redis.listener.ChannelTopic">
							<constructor-arg value="__keyevent@0__:expired" />
						</bean>
					</list>
				</entry>
			</map>
		</property>
	</bean>

在这里插入图片描述

package com.wjh.listener;

import java.io.Serializable;
import java.util.Map;

/**
 * Author:   17976
 * Date:     2019/2/23 21:41
 * Description:
 */
public interface MyMessageDelegate {
    void handleMessage(String message);
    void handleMessage(Map message);
    void handleMessage(byte[] message);
    void handleMessage(Serializable message);
    // pass the channel/pattern as well
    void handleMessage(Serializable message, String channel);
}

package com.wjh.listener;

import java.io.Serializable;
import java.util.Map;

/**
 * Author:   17976
 * Date:     2019/2/23 21:42
 * Description:
 */
public class MyRedisKeyExpiredMessageDelegate implements MyMessageDelegate {

    @Override
    public void handleMessage(String message) {

    }

    @Override
    public void handleMessage(Map message) {

    }

    @Override
    public void handleMessage(byte[] message) {

    }

    @Override
    public void handleMessage(Serializable message) {

    }

    @Override
    public void handleMessage(Serializable message, String channel) {

    }
}

package com.wjh.listener;

import redis.clients.jedis.JedisPubSub;

/**
 * Author:   17976
 * Date:     2019/2/23 21:34
 * Description: 监听redis key是否过期
 */
public class KeyExpiredListener extends JedisPubSub {
    @Override
    public void onPSubscribe(String pattern, int subscribedChannels) {
//        super.onPSubscribe(pattern, subscribedChannels);
        System.out.println("onPSubscribe " + pattern + " " + subscribedChannels);
    }

    @Override
    public void onPMessage(String pattern, String channel, String message) {
        System.out.println("onPMessage pattern -->" + pattern + "-->channel: " + channel + "message--> " + message);
    }
}

package com.wjh.listener;

import com.wjh.dao.RedisDao;
import com.wjh.dao.impl.RedisDaoImpl;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.List;

/**
 * Author:   17976
 * Date:     2019/2/23 22:29
 * Description: redis订阅程序
 */
public class Subscriber {
    public static void main(String[] args) {
        JedisPool pool = new JedisPool(new JedisPoolConfig(), "116.62.140.147",6379);
        Jedis jedis = pool.getResource();
        jedis.auth("flower");
        config(jedis);
        //只订阅patten匹配在超时事件
        jedis.psubscribe(new KeyExpiredListener(), "__key*@0__:expired");
    }
    private static void config(Jedis jedis) {
        String parameter = "notify-keyspace-events";
        List<String> notify = jedis.configGet(parameter);
        if (notify.get(1).equals("")) {
            jedis.configSet(parameter, "Ex"); //过期事件
        }
    }

}

package com.wjh.listener;

/**
 * Author:   17976
 * Date:     2019/2/23 22:26
 * Description: 测试redis key超时
 */
import com.wjh.dao.RedisDao;
import org.springframework.beans.factory.annotation.Autowired;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisListenerTest {

    public static void main(String[] args){
        JedisPool pool = new JedisPool(new JedisPoolConfig(), "116.62.140.147",6379);
        Jedis jedis = pool.getResource();
        jedis.auth("flower");
        jedis.select(0);
        jedis.set("notify", "你还在吗");
        jedis.expire("notify", 5);

        jedis.select(1);
        jedis.set("test","test");
        jedis.expire("test", 10);
    }
}

先运行订阅程序Subscriber

onPSubscribe __key*@0__:expired 1

再运行测试程序RedisListenerTest,在0库和1库分别放入两个String值,并设置过期时间
这时Subscriber应该输出

onPMessage pattern -->__key*@0__:expired-->channel: __keyevent@0__:expiredmessage--> notify

但是我的没有输出啊,KeyExpiredListener中的onPMessage没有回调成功。
解决办法:
https://blog.csdn.net/liuhaiabc/article/details/80825426
修改Subscriber判断redis配置文件中是否设置了notify-keyspace-events EX,如果设置没有生效就手动设置。
(不知道是不是应该修改完之后把redis重启一下呢,这次设置了之后我把这个conf方法给去掉了,这下又可以了。)

public class Subscriber {
    public static void main(String[] args) {
        JedisPool pool = new JedisPool(new JedisPoolConfig(), "116.62.140.147",6379);
        Jedis jedis = pool.getResource();
        jedis.auth("flower");
        config(jedis);
        //只订阅patten匹配在超时事件
        jedis.psubscribe(new KeyExpiredListener(), "__key*@0__:expired");
    }
    private static void config(Jedis jedis) {
        String parameter = "notify-keyspace-events";
        List<String> notify = jedis.configGet(parameter);
        if (notify.get(1).equals("")) {
            jedis.configSet(parameter, "Ex"); //过期事件
        }
    }

在这里插入图片描述
哈哈,myorder是我三个小时之前设置的,刚好这会儿过期了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值