SpringBoot如何监听redis Key变化事件案例详解

目录
  • 一 、功能概览
  • 二、事件类型
  • 三、配置
  • 三、案例
  • 代码
    • 新增和修改都是set指令
    • 删除
    • 过期
  • 总结

键空间通知(keyspace notification)

一 、功能概览

键空间通知使得客户端可以通过订阅频道或模式, 来接收那些以某种方式改动了 Redis key变化的事件。

所有修改key键的命令。

所有接收到 LPUSH key value [value …] 命令的键。

db数据库中所有已过期的键。

事件通过 Redis 的订阅与发布功能(pub/sub)来进行分发, 因此所有支持订阅与发布功能的客户端都可以在无须做任何修改的情况下, 直接使用键空间通知功能。

因为 Redis 目前的订阅与发布功能采取的是发送即忘(fire and forget)策略, 所以如果你的程序需要可靠事件通知(reliable notification of events), 那么目前的键空间通知可能并不适合你: 当订阅事件的客户端断线时, 它会丢失所有在断线期间分发给它的事件。

未来将会支持更可靠的事件分发, 这种支持可能会通过让订阅与发布功能本身变得更可靠来实现, 也可能会在 Lua 脚本中对消息(message)的订阅与发布进行监听, 从而实现类似将事件推入到列表这样的操作。

二、事件类型

对于每个修改数据库的操作,键空间通知都会发送两种不同类型的事件。

比如说,对 0 号数据库的键 mykey 执行 DEL key [key …]命令时, 系统将分发两条消息, 相当于执行以下两个 PUBLISH channel message 命令:

PUBLISH __keyspace@0__:mykey del
PUBLISH __keyevent@0__:del mykey

订阅第一个频道 __keyspace@0__:mykey 可以接收 0 号数据库中所有修改键 mykey 的事件, 而订阅第二个频道 __keyevent@0__:del则可以接收 0 号数据库中所有执行 del 命令的键。

以 keyspace 为前缀的频道被称为键空间通知(key-space notification), 而以 keyevent 为前缀的频道则被称为键事件通知(key-event notification)。

当 del mykey 命令执行时:

  • 键空间频道的订阅者将接收到被执行的事件的名字,在这个例子中,就是 del 。
  • 键事件频道的订阅者将接收到被执行事件的键的名字,在这个例子中,就是 mykey 。

三、配置

因为开启键空间通知功能需要消耗一些 CPU , 所以在默认配置下, 该功能处于关闭状态。

可以通过修改 redis.conf 文件, 或者直接使用 CONFIG SET 命令来开启或关闭键空间通知功能:

当 notify-keyspace-events 选项的参数为空字符串时,功能关闭。

另一方面,当参数不是空字符串时,功能开启。

notify-keyspace-events 的参数可以是以下字符的任意组合, 它指定了服务器该发送哪些类型的通知:

输入的参数中至少要有一个 K或者 E , 否则的话, 不管其余的参数是什么, 都不会有任何通知被分发。

举个例子, 如果只想订阅键空间中和列表相关的通知, 那么参数就应该设为 Kl , 诸如此类。

将参数设为字符串"AKE" 表示发送所有类型的通知。

每当一个键因为过期而被删除时,产生一个 expired 通知。

每当一个键因为maxmemory政策而被删除以回收内存时,产生一个 evicted 通知。

所有命令都只在键真的被改动了之后,才会产生通知。

比如说,当 SREM key member [member …]试图删除不存在于集合的元素时,删除操作会执行失败,因为没有真正的改动键,所以这一操作不会发送通知。

如果对命令所产生的通知有疑问, 最好还是使用以下命令, 自己来验证一下:

Redis 使用以下两种方式删除过期的键:

当一个键被访问时,程序会对这个键进行检查,如果键已经过期,那么该键将被删除。

底层系统会在后台渐进地查找并删除那些过期的键,从而处理那些已经过期、但是不会被访问到的键。
当过期键被以上两个程序的任意一个发现、 并且将键从数据库中删除时, Redis 会产生一个 expired 通知。

Redis 并不保证生存时间(TTL)变为 0 的键会立即被删除: 如果程序没有访问这个过期键, 或者带有生存时间的键非常多的话, 那么在键的生存时间变为 0 , 直到键真正被删除这中间, 可能会有一段比较显著的时间间隔。

因此, Redis 产生expired通知的时间为过期键被删除的时候, 而不是键的生存时间变为 0 的时候。

三、案例

按上文内容,我们先将redis的键空间通知开启,我们开启所有的通知,在可以端中测试后没问题再到代码中测试。

连接到redis 输入一下命令

config set notify-keyspace-events KEA

订阅键空间和键事件的主题

psubscribe '__key*__:*'#对所有库键空间通知

psubscribe '__keyspace@2__:*' #是对db2数据库键空间通知

psubscribe '__keyspace@2__:order*' #是对db2数据库,key前缀为order所有键的键空间通知

创建一个 key :name valus:zhangsan

set name wsl

观察订阅的窗口 会受到两个消息,第一个是:键空间 第二个是键事件,键空间是内容是操作指令,主题中包含有key,键事件主题中包含了指令,内容是key。

到这里说明已经开启了键空间通知

代码

以下代码采用string类型演示

在配置一下MessageListenerContainer类,将我们写好的监听类添加到该类中即可,删除和过期都是需要添加,我这里就一起添加了后面就不做演示。

@Configuration
public class RedisConfig {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedisUpdateAndAddListener redisUpdateAndAddListener;

    @Autowired
    private RedisDeleteListener redisDeleteListener;

    @Autowired
    private RedisExpiredListener redisExpiredListener;

    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        //监听所有的key的set事件
        container.addMessageListener(redisUpdateAndAddListener, redisUpdateAndAddListener.getTopic());
        //监听所有key的删除事件
        container.addMessageListener(redisDeleteListener,redisDeleteListener.getTopic());
        //监听所有key的过期事件
        container.addMessageListener(redisExpiredListener,redisExpiredListener.getTopic());
        return container;
    }

}

新增和修改都是set指令

所以监听的主题都一样,实现MessageListener接口,重写onMessage这里就是收到消息的处理逻辑

@Component
@Data
public class RedisUpdateAndAddListener implements MessageListener {
	//监听的主题
    private  final PatternTopic topic = new PatternTopic("__keyevent@*__:set");

    @Override
    public void onMessage(Message message,byte[] pattern){
        String topic = new String(pattern);
        String msg = new String(message.getBody());
        System.out.println("收到key更新或修改,消息主题是:"+ topic+",消息内容是:"+msg);
    }

}

在redis中对name这个key进行set操作

set name wsl

在控制台就可以看到name这个key被操作了

删除

跟上面的更新监听一样,只需要把订阅主题更改一下即可。同样需要添加到这个RedisMessageListenerContainer,上面已经添加,这里不做演示

@Component
@Data
public class RedisDeleteListener implements MessageListener {

    //监听主题
    private  final PatternTopic topic = new PatternTopic("__keyevent@*__:del");

    /**
     *
     * @param message 消息
     * @param pattern 主题
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String topic = new String(pattern);
        String msg = new String(message.getBody());
        System.out.println("收到key的删除,消息主题是:"+ topic+",消息内容是:"+msg);
    }
}

在redis输入命令,del name 在控制台可以看到已经收到消息了。

过期

如上面的操作方式一样

@Data
@Component
public class RedisExpiredListener implements MessageListener {

    //监听主题
    private  final PatternTopic topic = new PatternTopic("__keyevent@*__:expired");

    @Override
    public void onMessage(Message message, byte[] pattern) {
        String topic = new String(pattern);
        String msg = new String(message.getBody());
        System.out.println("收到key的过期,消息主题是:"+ topic+",消息内容是:"+msg);
    }
}

在redis中写一个定时删除的keySETEX age 18 3三秒后就可以控制台打印了相关信息

总结

到此这篇关于SpringBoot如何监听redis Key变化事件案例的文章就介绍到这了,更多相关SpringBoot监听redis Key变化事件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring Boot监听Redis Key失效事件实现定时任务的示例

    业务场景 我们以订单功能为例说明下: 生成订单后一段时间不支付订单会自动关闭.最简单的想法是设置定时任务轮询,但是每个订单的创建时间不一样,定时任务的规则无法设定,如果将定时任务执行的间隔设置的过短,太影响效率. 还有一种想法,在用户进入订单界面的时候,判断时间执行相关操作.方式可能有很多,在这里介绍一种监听 Redis 键值对过期时间来实现订单自动关闭. 实现思路 在生成订单时,向 Redis 中增加一个 KV 键值对,K 为订单号,保证通过 K 能定位到数据库中的某个订单即可,V 可为任意值

  • Redis集群下过期key监听的实现代码

    1. 前言 在使用redis集群时,发现过期key始终监听不到.网上也没有现成的解决方案.于是想,既然不能监听集群,那我可以建立多个redis连接,分别对每个redis的key过期进行监听.以上做法可能不尽人意,目前也没找到好的解决方案,如果有好的想法,请留言告知哦!不多说,直接贴我自己的代码! 2. 代码实现 关于Redis集群配置代码此处不贴,直接贴配置监听类代码! redis.host1: 10.113.56.68 redis.port1: 7030 redis.host2: 10.113

  • SpringBoot如何整合redis实现过期key监听事件

    可以用于简单的过期订单取消支付.7天自动收货场景中 1.Spring Boot整合redis 参考 https://www.jb51.net/article/170687.htm 2.打开redis服务的配置文件添加notify-keyspace-events Ex 如果是注释了,就取消注释 Linux安装redis:https://www.jb51.net/article/193265.htm Windows安装redis:https://www.jb51.net/article/176040

  • spring boot+redis 监听过期Key的操作方法

    前言: 在订单业务中,有时候需要对订单设置有效期,有效期到了后如果还未支付,就需要修改订单状态.对于这种业务的实现,有多种不同的办法,比如: 1.使用querytz,每次生成一个订单,就创建一个定时任务,到期后执行业务代码: 2.rabbitMq中的延迟队列: 3.对Redis的Key进行监控: 1.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring

  • SpringBoot如何监控Redis中某个Key的变化(自定义监听器)

    目录 SpringBoot 监控Redis中某个Key的变化 1.声明 2.基本理念 3.实现和创建监听 4.基本demo的其他配置 5.基本测试 6.小结一下 SpringBoot自定义监听器 原理 示例 SpringBoot 监控Redis中某个Key的变化 1.声明 当前内容主要为本人学习和基本测试,主要为监控redis中的某个key的变化(感觉网上的都不好,所以自己看Spring源码直接写一个监听器) 个人参考: Redis官方文档 Spring-data-Redis源码 2.基本理念

  • SpringBoot如何监听redis Key变化事件案例详解

    目录 一 .功能概览 二.事件类型 三.配置 三.案例 代码 新增和修改都是set指令 删除 过期 总结 键空间通知(keyspace notification) 一 .功能概览 键空间通知使得客户端可以通过订阅频道或模式, 来接收那些以某种方式改动了 Redis key变化的事件. 所有修改key键的命令. 所有接收到 LPUSH key value [value …] 命令的键. db数据库中所有已过期的键. 事件通过 Redis 的订阅与发布功能(pub/sub)来进行分发, 因此所有支持

  • js实现无刷新监听URL的变化示例代码详解

    无刷新改变路由的两种方法通过hash改变路由 代码 window.location.hash='edit' 效果 http://xxxx/#edit 通过history改变路由 history.back(): 返回浏览器会话历史中的上一页,跟浏览器的回退按钮功能相同 history.forward():指向浏览器会话历史中的下一页,跟浏览器的前进按钮相同 history.go(): 可以跳转到浏览器会话历史中的指定的某一个记录页 history.pushState()可以将给定的数据压入到浏览器

  • 微信小程序 监听手势滑动切换页面实例详解

    微信小程序 监听手势滑动切换页面实例详解 1.对应的xml里写上手势开始.滑动.结束的监听: <view class="touch" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd" ></view> 2.js: var touchDot = 0;//触摸时的原点 var time = 0;// 时

  • Android 监听软键盘状态的实例详解

    Android 监听软键盘状态的实例详解 近日遇到要检测软键盘是否显示或隐藏的问题,搜了一下网上,最后找到一个很简单的,记录一下. activityRoot是activity的根view,就是xml里面的第一个view,给它设置一个id. final View activityRootView = findViewById(R.id.activityRoot); activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(ne

  • npm script 的文件监听和自动刷新的命令详解

    文件监听的作用是为了实现自动化,释放双手和精力,提高效率,让开发者更加关注于开发.npm script 文件监听和 grunt.gulp 功能类似. 自动刷新,意思就是改动文件保存后,页面自动刷新,减少日常开发的操作. 代码检查的监听和自动化 代码检查工具 stylelint.eslint.jsonlint 这些对 watch 支持很弱,所以就需要引入工具包 onchange 安装命令依赖包 npm i onchange -D // 或 yarn add onchange -D 编写命令 "sc

  • Flume监听oracle表增量的步骤详解

    需求:获取oracle表增量信息,发送至udp514端口,支持ip配置 步骤: (1)需要的jar  oracle的 odbc5.jar(oracle安装目录  /jdbc/lib下查找) (2)flume的开源包flume-ng-sql-source-1.4.3.jar  最新的好像是1.5的 小版本记不住了 这个下载地址直接csdn上就有 这两个jar 都拷贝到flume的lib下 (3)flume配置文件 a1.sources = r1 a1.sinks = k1 a1.channels

  • android studio按钮监听的5种方法实例详解

    1.匿名内部类 public class MainActivity extends AppCompatActivity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn1 = fin

  • SpringBoot + WebSocket 实现答题对战匹配机制案例详解

    概要设计 类似竞技问答游戏:用户随机匹配一名对手,双方同时开始答题,直到双方都完成答题,对局结束.基本的逻辑就是这样,如果有其他需求,可以在其基础上进行扩展 明确了这一点,下面介绍开发思路.为每个用户拟定四种在线状态,分别是:待匹配.匹配中.游戏中.游戏结束.下面是流程图,用户的流程是被规则约束的,状态也随流程而变化 对流程再补充如下: 用户进入匹配大厅(具体效果如何由客户端体现),将用户的状态设置为待匹配 用户开始匹配,将用户的状态设置为匹配中,系统搜索其他同样处于匹配中的用户,在这个过程中,

  • SpringBoot之通过BeanPostProcessor动态注入ID生成器案例详解

    在分布式系统中,我们会需要 ID 生成器的组件,这个组件可以实现帮助我们生成顺序的或者带业务含义的 ID. 目前有很多经典的 ID 生成方式,比如数据库自增列(自增主键或序列).Snowflake 算法.美团 Leaf 算法等等,所以,会有一些公司级或者业务级的 ID 生成器组件的诞生.本文就是通过 BeanPostProcessor 实现动态注入 ID 生成器的实战. 在 Spring 中,实现注入的方式很多,比如 springboot 的 starter,在自定义的 Configuratio

随机推荐