Redis的键空间监听功能

news2024/11/25 18:47:18

文章目录

  • Redis 键空间通知
    • 一、keyspace介绍
    • 二、事件通知配置
    • 三、不同命令生成的事件
    • 四、客户端测试
    • 五、Springboot整合Redis键空间监听
      • 5.1 方式一
      • 5.2 方式二

Redis 键空间通知

一、keyspace介绍

keyspace(键空间通知)针对指定key发生的一切改动,推送给订阅的客户端,侧重于针对指定key的操作

键空间通知监听格式:__keyspace@<db>__:<key>

二、事件通知配置

默认情况下,键空间事件通知被禁用,因为虽然不太明智,但该功能会使用一些 CPU 功率。notify-keyspace-events有两种配置方式

  • 通过redis.conf配置
  • 通过config set 启用通知,重启失效
例:config set notify-keyspace-events “KEA”

将参数设置为空字符串会禁用通知。为了启用该功能,使用由多个字符组成的非空字符串,其中每个字符都有特殊含义

字符发送的通知
K键空间通知,所有通知以 __keyspace@<db>__ 为前缀
E键事件通知,所有通知以__keyevent@<db>__为前缀
gdelexpirerename 等类型无关的通用命令的通知
$string命令的通知
llist命令的通知
sset命令的通知
hhash命令的通知
zzset命令的通知
e驱逐(evict)事件:每当有键因为 maxmemory 政策而被删除时发送
A参数 g$lshzxe 的别名

至少KE应该出现在字符串中,否则无论字符串的其余部分如何,都不会传递任何事件。

例如,要仅启用列表的键空间事件,配置参数必须设置为Kl,等等。

您可以使用该字符串KEA来启用所有类型的通知

三、不同命令生成的事件

具体的看官方文档:Redis 键空间通知,这里举几个例子:

  • DEL为每个已删除的键生成一个del事件。
  • RENAME生成两个事件,一个rename_from针对源键的事件,一个rename_to针对目标键的事件。
  • MOVE生成两个事件,一个move_from针对源键的事件,一个move_to针对目标键的事件。
  • COPY生成一个copy_to事件。
  • EXPIRE及其所有变体(PEXPIREEXPIREATPEXPIREATexpire在使用正超时(或未来时间戳)调用时都会生成一个事件。请注意,当使用过去的负超时值或时间戳调用这些命令时,键将被删除,并且仅del生成一个事件。

四、客户端测试

Redis键空间监听的本质是通过订阅与键相关的消息通知来实现的。当一个Redis键空间的事件发生时,Redis会将事件信息发送到相应的频道(channel),而订阅了该频道的客户端就会接收到这些消息通知。

1.打开redis客户端连接,然后设置所有类型事件都通知

C:\Users\Lenovo>redis-cli
127.0.0.1:6379> config set notify-keyspace-events "KEA"
OK
127.0.0.1:6379>

2.订阅一个频道,配置key为qqq:*就会触发通知

# PSUBSCRIBE命令用于订阅一个或多个符合指定模式的频道(channel),支持通配符模式
127.0.0.1:6379> PSUBSCRIBE __keyspace@*__:qqq:*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "__keyspace@*__:qqq:*"
3) (integer) 1

在这里插入图片描述

3.新开一个客户端

C:\Users\Lenovo>redis-cli
127.0.0.1:6379> set qqq:111 222
OK
127.0.0.1:6379>

结果:可以看到只要qqq:*的发生了变动,就会触发通知
在这里插入图片描述

在这里插入图片描述

五、Springboot整合Redis键空间监听

5.1 方式一

1.引入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
        <version>2.5.4</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

2.配置redis

server.port=8080

spring.redis.port=6379
spring.redis.host=127.0.0.1

3.配置监听器

@Slf4j
@Component
public class RedisListener implements MessageListener {

    @Override
    public void onMessage(Message message, byte[] pattern) {
        System.out.println(message.toString());
        String body = new String(message.getBody());
        System.out.println(body);
        String channel = new String(message.getChannel());
        System.out.println(channel);

        int index = channel.indexOf(":");
        String key = channel.substring(index + 1); // 找到第一个冒号的位置,冒号后面就是key

        log.info("redis key: {} , channel: {}", key, channel);
    }
}

4.开启监听以及配置监听范围

@Component
public class RedisContainer {
    
    @Autowired
    RedisListener redisListener;
    @Autowired
    private TaskExecutor redisListenerContainerTaskExecutor;

    private static final Topic TOPIC_ALL_KEYSPACE = new PatternTopic("__keyspace@*__:*");
    
    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory factory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);
        // __keyspace@*__:* 可以配置一个也可配置多个
        container.addMessageListener(redisListener, TOPIC_ALL_KEYSPACE);
        container.setTaskExecutor(redisListenerContainerTaskExecutor);
        return container;
    }
}

5.测试
在这里插入图片描述

5.2 方式二

1.增加redisTemplate配置

@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        // 创建RedisTemplate对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);
        // 创建JSON序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // 设置Key的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置Value的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}

2.使用@PostConstruct,在项目启动时动态注入容器

@Slf4j
@Component
public class service {

    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private TaskExecutor redisListenerContainerTaskExecutor;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private static final Topic TOPIC_ALL_KEYSPACE = new PatternTopic("__keyspace@*__:*");

    @PostConstruct
    void init(){
        DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();

        // 创建redis监听器
        MessageListener listener = (message, pattern) -> {
            System.out.println("message: " + message.toString());
            String body = new String(message.getBody());
            System.out.println("body: " + body);
            String channel = new String(message.getChannel());
            System.out.println("channel: " + channel);

            int index = channel.indexOf(":");
            String key = channel.substring(index + 1); // 找到第一个冒号的位置,冒号后面就是key

            log.info("redis key: {} , channel: {}", key, channel);
        };

        // 创建redis监听适配器
        MessageListenerAdapter listenerAdapter = new MessageListenerAdapter(listener);

        // 创建redis消息监听容器
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisTemplate.getConnectionFactory());
        container.addMessageListener(listenerAdapter, TOPIC_ALL_KEYSPACE);
        container.setTaskExecutor(redisListenerContainerTaskExecutor);

        // redis消息监听容器注入到spring中
        BeanDefinitionBuilder listenerBeanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(RedisMessageListenerContainer.class, () -> container);
        defaultListableBeanFactory.registerBeanDefinition("redisMessageListenerContainer", listenerBeanDefinitionBuilder.getBeanDefinition());
    }
}

3.结果一样
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/824287.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

香港三维模型:基于GIS数据的精确三维城市模型及其周边2023年

基于GIS数据的精确三维城市模型及其周边2023年 包含的文件&#xff1a; 满城&#xff1a;15公里 信息&#xff1a; 仅在影院4D中设置基本卫星纹理 包含卫星/地图纹理 影院制作4d&#xff0c;可在标准渲染器中进行渲染 漫步建筑、树木&#xff08;mograph cloner&#xff…

【无标题】JSP--Java的服务器页面

jsp是什么&#xff1f; jsp的全称是Java server pages,翻译过来就是java的服务器页面。 jsp有什么作用&#xff1f; jsp的主要作用是代替Servlet程序回传html页面的数据&#xff0c;因为Servlet程序回传html页面数据是一件非常繁琐的事情&#xff0c;开发成本和维护成本都非常高…

虹科活动 | 走进宇通客车-汽车新供应链技术展精彩回顾

引言 7月27日&#xff0c;走进宇通客车-汽车新供应链技术展于宇通研发中心成功举办&#xff0c;本次展会中虹科为大家带来了一体化车载天线与车辆GNSS仿真测试方案&#xff0c;感谢您前来探讨与交流&#xff01; 精彩产品一览 车辆GNSS仿真测试方案 虹科高性能GNSS模拟器具有灵…

【二叉树进阶】二叉树经典面试题——最近公共祖先问题

文章目录 1. 二叉树的最近公共祖先1.1 思路1&#xff08;转换为链表相交问题&#xff09;1.2 链表相交问题讲解1.3 思路21.4 思路2AC代码 2. 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先2.1 思路分析2.2 AC代码 3. 普通二叉树求最近公共祖先的优化-转化为路径相交的问题3.1 思…

国产DSP,C2000,QX320F280049,打破TI垄断,支持国产

数字电源&#xff0c;光伏逆变器&#xff0c;微电机&#xff0c;充电桩&#xff0c;家电&#xff0c;机器人专用

Python绘图坐标系映射,对数坐标系

文章目录 对数坐标系自定义映射对数坐标图 对数坐标系 在实际绘图时&#xff0c;如果 x , y x,y x,y这两轴的数据变化速率相差过多&#xff0c;线性的坐标映射将无法展示图形变化的细节&#xff0c;就需要更改坐标系的数字映射逻辑&#xff0c;以获得更具细节的图像。 在matp…

【华为HCIP | 高级网络工程师】刷题日记(11)

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大二在校生&#xff0c;喜欢编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;见文末 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️ 零…

pycharm bash: 第 0 行: cd: xxxxxxx: 没有那个文件或目录

设置里面的python接口&#xff0c;path mappings 是空的&#xff0c;设置好本地机器和远程机器所对应的目录就好了。如下图:

【100天精通python】Day23:正则表达式,基本语法与re模块详解示例

目录 专栏导读 1 正则表达式概述 2 正则表达式语法 2.1 正则表达式语法元素 2.2 正则表达式的分组操作 3 re 模块详解与示例 4 正则表达式修饰符 专栏导读 专栏订阅地址&#xff1a;https://blog.csdn.net/qq_35831906/category_12375510.html 1 正则表达式概述 python 的…

24考研数据结构-第四章:串

目录 第四章&#xff1a;串4.1串的定义和实现4.1.1串的定义4.1.2串的基本操作字符集编码 4.1.3串的存储结构1. 定长顺序存储表示基本操作实现&#xff08;基于方案四&#xff09; 2. 堆分配存储表示3. 串的链式存储结合链表思考优缺点 知识回顾 4.2串的模式匹配4.2.1朴素模式匹…

ChatGPT辅助写论文:提升效率与创造力的利器

写作是人类最重要的交流方式之一&#xff0c;也是学术研究中不可或缺的环节。然而&#xff0c;写作并不是一件容易的事情&#xff0c;尤其是对于科研人员来说&#xff0c;他们需要花费大量的时间和精力来撰写高质量的论文&#xff0c;并且面临着各种各样的挑战&#xff0c;如语…

用栈实现队列——数据结构与算法

&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️ &#x1f4a5;个人主页&#xff1a;&#x1f525;&#x1f525;&#x1f525;大魔王&#x1f525;&#x1f525;&#x1f525; &#x1f4a5;代码仓库&#xff1a;&#x1f525;&#x1f525;魔…

Flowable-子流程-事务子流程

目录 定义图形标记XML内容使用示例视频教程 定义 事务子流程也称作事务块&#xff0c;是一个嵌入式子流程&#xff0c;用来处理一组必须在同一个事务中完成的活 动&#xff0c;使它们共同成功或失败。事务子流程中如果有一个活动失败或者取消&#xff0c;整个事务子流程的所有…

<C++> 四、模板初阶

1.泛型编程 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础。 如何实现一个通用的交换函数呢&#xff1f;使用函数重载可以实现 void Swap(int &left, int &right) {int temp left;left right;right temp; …

延时函数

其实从学习FreeRTOS以来&#xff0c;一直有个疑问&#xff1a;为什么freertos.c中的延时函数要使用osDelay()&#xff0c;而不直接使用HAL_Delay()呢&#xff1f;两者有什么区别&#xff1f; 本节就来探讨一下这个问题的答案&#xff1a; 延时函数分类 相对延时&#xff1a;…

linux查看日志指令

今天导师要求&#xff0c;使用linux查看日志&#xff0c;这里呢&#xff0c;先是学习了一下ubuntu内核的linux&#xff0c;现在回顾一下查看日志的语句 linux查看日志指令 一、tail二、head三、cat四、more五、view5.1 从上往下找5.2 从下往上找5.3退出 六、搜索6.1模糊搜索6.2…

【新版系统架构补充】-嵌入式技术

嵌入式微处理体系结构 冯诺依曼结构 传统计算机采用冯诺依曼结构&#xff0c;也称普林斯顿结构&#xff0c;是一种将程序指令存储器和数据存储器合并在一起的存储器结构 冯诺依曼的计算机程序和数据共用一个存储空间&#xff0c;程序指令存储地址和数据存储地址指向同一个存…

中国最赚钱公司出炉

7月25日&#xff0c;2023年《财富》中国500强排行榜正式发布。国家电网以5300亿美元的营收位居榜首&#xff0c;中国石油和中国石化分列第二和第三。工商银行则成为最赚钱的公司。 图片来源&#xff1a;财富FORTUNE 1中国500强TOP10 数据显示&#xff0c;今年500家上榜的中国…

华为交换机配置SSH远程登录

连接console线直接配置 1、在服务器端生成本地密钥对 <HUAWEI>system-view [HUAWEI] dsa local-key-pair create Info: The key name will be: HUAWEI_Host_DSA. Info: The key modulus can be any one of the following : 1024, 2048. Info: If the key modulus i…

Qt应用开发(基础篇)——滑块类 QSlider、QScrollBar、QDial

目录 一、前言 二、QAbstractSlider类 1、invertedAppearance 2、invertedControls 3、maximum 4、minimum 5、orientation 6、pageStep 7、singleStep 8、sliderDown 9、tracking 10、sliderPosition 11、value 12、信号 三、QDial类 1、notchSize 2、notchTa…