当前位置: 首页 > news >正文

《框架封装 · Redis 事件监听》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗
🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,欢迎多多交流。👍

文章目录

    • 写在前面的话
    • 技术入门
    • 实战分享
    • 运用场景
    • 总结陈词


写在前面的话

企业实战开发中,事件监听的运用场景非常多,当某事件发生的时候,会触发某个响应处理,其主要优势体现在多负载实例的场景下。与前几篇博文《知识点扫盲 · 监听器 Listener》《后端程序猿 · 基于 Lettuce 实现缓存容错策略》提到的观察者模式、发布订阅模式等,有异曲同工之妙。
本篇文章先介绍一下,框架封装人员如何处理事件监听场景,默认基于 RedisMessageListenerContainer实现,下面以此技术加以说明。


技术入门

【技术简介】
RedisMessageListenerContainer 是 Spring Data Redis 提供的一个类,用于异步处理 Redis 中的发布/订阅消息。它利用 Redis 的发布/订阅机制,通过消息通道(channel)或模式(pattern)订阅消息,并在消息到达时触发相应的监听器方法。该机制广泛应用于实时数据处理、消息广播等场景。

【使用入门】
Step1、引入 Maven 依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Step2、注册消息监听 Bean,订阅事件

@Bean
RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {RedisMessageListenerContainer container = new RedisMessageListenerContainer();container.setConnectionFactory(connectionFactory);container.setTaskExecutor(this.defaultTaskExecutor());Topic websocket = new ChannelTopic("websocket");Topic versionUpdate = new ChannelTopic("versionUpdate");List<Topic> list = new ArrayList<>();list.add(websocket);list.add(versionUpdate);WebsocketRedisMessageListener listener = new WebsocketRedisMessageListener();listener.setRedisTemplate(redisTemplate);container.addMessageListener(listener, list);return container;
}

Step3、实现监听消费逻辑

public class WebsocketRedisMessageListener implements MessageListener {@Overridepublic void onMessage(Message message, byte[] pattern) {try {String msgChannel = new String(pattern);String msgBody = (String) getRedisTemplate().getValueSerializer().deserialize(message.getBody());switch (msgChannel) {case TOPIC_VERSION:VersionSocket versionSocket = new VersionSocket();versionSocket.sendMessageAll(msgBody);break;default:LOGGER.warn("处理redis主题, 找不到对应的主题,{}", msgChannel);break;}} catch (Exception e) {LOGGER.error("处理redis事件失败:{}", ExceptionUtil.stacktraceToString(e));}}
}

Step4、按需发布事件

redisTemplate.convertAndSend("versionUpdate", JSON.toJSONString(versionUpdate));

【拓展说明】
通过 RedisMessageListenerContainer 还可以实现针对 Redis-Key 增删改以及过期的监听。
这不是本篇文章重点,详情搜索:KeyExpirationEventMessageListener、 PatternTopic 等关键词。


实战分享

设计思路:
技术基础入门介绍完了,功能可以实现,但是步骤略多,作为框架封装开发人员,肯定要帮忙加工一下,不可能放任各业务部门的开发人员随意添加,那可能出现各种奇葩问题,还需要架构人员兜底。
接下来分享一下实战经验:
1、事件监听的实现方式有多种,框架集成了 Redis 监听方式,作为事件总线模块的默认底层实现。如果想使用其他中间件来替代默认实现,也预留了接口,方便替换,Redis 监听实现的关键技术依然是RedisMessageListenerContainer
2、将消息监听器Bean的定义工作放到框架核心包处理,包含设定默认线程池等
3、提供快速使用消费功能的接口,开发人员只需要按规约实现接口即可完成订阅工作
4、提供发布消息的API,统一操作入口

下面贴一下代码,展示封装后,开发人员如何使用:

//订阅事件
public class PortalEventListener implements ZhanshenEventListener {/*** 订阅事件KEY*/public static final Set<String> PATTERN_KEY = Set.of("zhanshen.portal");@Overridepublic Set<String> patterns() {return PATTERN_KEY;}@Overridepublic void handleEvent(ZhanshenEvent zhanshenEvent) {log.info("收到事件消息,pattern:{},data:{} ", zhanshenEvent.getPattern(), zhanshenEvent.getData());}
}//发布事件
ZhanshenEventListener.publishEvent("zhanshen.portal", "测试事件消息");//补充:可以定义多个ZhanshenEventListener实现类,框架会统一帮忙触发。

题外话:注意事项
封装过程中,遇到一个小坑,分享一下:
RedisMessageListenerContainer 的默认使用线程池是SimpleAsyncTaskExecutor,每次消费都会创建一个线程来处理,这样就会有大量的新线程被创建。生产环境下建议使用自定义线程池,减少性能损耗。


运用场景

在实际开发中,每个后端服务都会有多个实例,在这种情况下,当一个接口触发的时候,需要所有实例都做出响应,那事件监听机制就非常有用了。

场景1:WebSocket 在线用户通知
博主所在公司采用WebSocket技术实现了统一门户工作站的消息通知推送功能,用户登录的时候,需要调用后端接口,存储在线用户列表数据,这时候可能信息存储在某一个实例中。
当需要给用户发通知的时候,需要拉取到所在后端的用户 Session,进行 WebSocket 的 send操作。这时候由于后端是多实例,有可能没有存储相关用户信息,这时候可以通过事件监听方式,通知各个实例触发该操作。

场景2:static 静态变量的更新
某些情况,会使用静态变量维护一些数据,当要对这些数据进行修改,仅仅触发某个后端实例的接口,是不够的,可以通过事件监听机制,其他实例也订阅该动作,同步更新相关变量。

Tips:还有很多场景,这边不赘述了,自行发散。


总结陈词

上文介绍了框架封装人员,如何处理事件监听逻辑,提供了一些思路分享。
事件监听更多情况下是订阅了事件,需要由外部主动发布事件,才能触发响应逻辑。其实还有数据监听、缓存监听等技术方案,即数据变化等情况下,会自动触发响应,比如:Redis-Key 的过期监听、OGG for Bigdata 的 Oracle 数据变化监听,关于这一点后面再开文章介绍。
本系列博文将介绍框架搭建人员如何以恰当的方式应对各式各样的情况,这也是此专栏的主题。
💗 后续将持续更新,请多多支持!

相关文章:

《框架封装 · Redis 事件监听》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…...

小白学webgl合集-Three.js加载器

THREE.TextureLoader: 用途: 加载单个图像文件并将其作为纹理应用到材质上。示例: const loader new THREE.DataTextureLoader(); loader.load(path/to/data.bin, function (texture) {const material new THREE.MeshBasicMaterial({ map: texture });const geometry new TH…...

【算法】字符串的排列

难度&#xff1a;中等 给你两个字符串 s1 和 s2 &#xff0c;写一个函数来判断 s2 是否包含 s1 的排列。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 换句话说&#xff0c;s1 的排列之一是 s2 的 子串 。 示例 1&#xff1a; 输入&#xff1a;…...

5-3.损失函数

文章最前&#xff1a; 我是Octopus&#xff0c;这个名字来源于我的中文名–章鱼&#xff1b;我热爱编程、热爱算法、热爱开源。所有源码在我的个人github &#xff1b;这博客是记录我学习的点点滴滴&#xff0c;如果您对 Python、Java、AI、算法有兴趣&#xff0c;可以关注我的…...

SCSA第四天

ASPF FTP --- 文件传输协议 Tftp --- 简单文件传输协议 FTP协议相较于Tftp协议 ---- 1&#xff0c;需要进行认证 2&#xff0c;拥有一套完整的命令集 用户认证 防火墙管理员认证 ---- 校验登录者身份合法性 用户认证 --- 上网行为管理中的一环 上网用户认证 --- 三层认证…...

品牌策划必读:9本改变游戏规则的营销经典

作为深耕品牌十余年的策划人&#xff0c;这些年自学啃下的书不计其数。 这里特意挑选了几本知名度不高但是却非常有用的“遗珠”优质品牌策划书籍分享出来。 如果你是一位初步了解品牌的人&#xff0c;这些书籍既包含了品牌理论基础&#xff0c;也有实用的实践指导。 这些书…...

泛型

背景 优点 类型绝对安全避免强制类型转换 泛型类 定义 使用 举例 泛型类 // 泛型类 T就是类型参数 public class Generic<T>{// key这个成员变量的类型为T,T的类型由外部指定private T t;public void set(T t){this.t t;}public T get(){return t;} }使用 // 创建一个泛…...

react动态渲染列表与函数式组件

1.如何使用jsx语法动态渲染列表呢&#xff0c;下边我用一个例子来切实总结一下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scal…...

小程序内容管理系统设计

设计一个小程序内容管理系统&#xff08;CMS&#xff09;时&#xff0c;需要考虑以下几个关键方面来确保其功能完善、用户友好且高效&#xff1a; 1. 需求分析 目标用户&#xff1a;明确你的目标用户群体&#xff0c;比如企业、媒体、个人博主等&#xff0c;这将决定系统的功…...

HDFS 块重构和RedundancyMonitor详解

文章目录 1. 前言2 故障块的重构(Reconstruct)2.1 故障块的状态定义和各个状态的统计信息2.2 故障文件块的查找收集2.5.2.1 misReplica的检测2.5.2.2 延迟队列(postponedMisreplicatedBlocks)的构造和实现postponedMisreplicatedBlocks中Block的添加postponedMisreplicatedBloc…...

Power BI DAX常用函数使用场景和代码示例

Power BI函数表达式对于没有接触过的朋友可能会有些迷茫&#xff0c;花一点时间了解一下原理在学习一些常用的DAX函数&#xff0c;就可以解决工作中绝大部分问题&#xff0c;函数使用都是共同的。 以下是一些最常用的DAX函数&#xff0c;如聚合&#xff0c;计数&#xff0c;日期…...

机器学习与深度学习:区别与联系(含工作站硬件推荐)

一、机器学习与深度学习区别 机器学习&#xff08;ML&#xff1a;Machine Learning&#xff09;与深度学习&#xff08;DL&#xff1a;Deep Learning&#xff09;是人工智能&#xff08;AI&#xff09;领域内两个重要但不同的技术。它们在定义、数据依赖性以及硬件依赖性等方面…...

大模型/NLP/算法面试题总结5——Transformer和Rnn的区别

Transformer 和 RNN&#xff08;循环神经网络&#xff09;是两种常见的深度学习模型&#xff0c;广泛用于自然语言处理&#xff08;NLP&#xff09;任务。 它们在结构、训练方式以及处理数据的能力等方面有显著的区别。以下是它们的主要区别&#xff1a; 架构 RNN&#xff0…...

【RHCE】转发服务器实验

1.在本地主机上操作 2.在客户端操作设置主机的IP地址为dns 3.测试,客户机是否能ping通...

AI提示词:打造爆款标题生成器

打开GPT输入以下内容&#xff1a; # Role 爆款标题生成器## Profile - author: 姜小尘 - version: 02 - LLM: Kimi - language: 中文 - description: 利用心理学和市场趋势&#xff0c;生成吸引眼球的自媒体文章标题。## Background 一个吸引人的标题是提升文章点击率和传播力…...

skywalking-1-服务端安装

skywalking很优秀。 安装服务端 skywalking的服务端主要是aop服务&#xff0c;为了方便查看使用还需要安装ui。另外采集的数据我们肯定要存起来&#xff0c;这个数据库就直接用官方的banyandb。也就是aop、ui、banyandb都使用官方包。 我们的目的是快速使用和体验&#xff0c…...

查看oracle ojdbc所支持的JDBC驱动版本

oracle jcbc驱动的下载地址参考&#xff1a;JDBC and UCP Downloads page 其实上文中对ojdbc所支持的JDBC驱动版本已经有说明了&#xff0c;不过&#xff0c;因为oracle的驱动包很多时间&#xff0c;都是在公司内部私服里上传维护的&#xff0c;上传的时候&#xff0c;可能又没…...

自媒体运营怎样引流客源?

不管是企业还是个人&#xff0c;越来越多都在做自媒体引流运营&#xff0c;那有什么引流客源的方式呢&#xff1f; 高质量内容&#xff1a;创作并分享有价值的内容&#xff0c;吸引目标受众&#xff0c;提升内容的分享和传播效果。 SEO优化&#xff1a;优化文章标题、关键词和…...

【算法】十进制转换为二进制

目的&#xff1a;将十进制转换为二进制 思路&#xff1a; 首先我们手算的情况是通过求余数算出进制数&#xff0c;同样代码也是通过做除法和求余数的方式&#xff0c;除法是得出下一次的被除数&#xff0c;而求余数是得到进制数 代码&#xff1a; #include<stdio.h>/…...

Postman中的API安全堡垒:全面安全性测试指南

&#x1f6e1;️ Postman中的API安全堡垒&#xff1a;全面安全性测试指南 在当今的数字化世界中&#xff0c;API安全性是保护数据和系统不可或缺的一环。Postman作为API开发和测试的领先工具&#xff0c;提供了多种功能来帮助开发者进行API安全性测试。本文将深入探讨如何在Po…...

CANN/Ascend C量化模式设置API

SetDequantType 【免费下载链接】asc-devkit 本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言&#xff0c;原生支持C和C标准规范&#xff0c;主要由类库和语言扩展层构成&#xff0c;提供多层级API&#xff0c;满足多维场景算子开发诉求。 项目地址: https://gitcode…...

PX4 Firmware V1.14.4 开源支持

PX4 官方固件版本迭代迅猛&#xff0c;这往往导致开发者在硬件兼容性、环境搭建及软件依赖性上遭遇重重挑战。为彻底解决这一问题&#xff0c;Kerloud 推出固件与文档长期支持&#xff08;LTS&#xff09;计划。我们将对飞控固件代码、技术文档及参数调优指南实施持续性维护&am…...

C++异步日志系统

文章目录异步日志系统1. 项目背景2. 设计思路2.1 核心架构2.2 关键技术点3. 实现细节3.1 线程安全的日志队列 (LogQueue)3.2 动态格式化与回退机制 (formatMessage)3.3 自动化管理4. 接口说明日志级别 (LogLevel)核心方法5. 使用指南5.1 快速上手5.2 注意事项6. 总结7.Code异步…...

从零部署私有AI助手:igogpt项目实战与优化指南

1. 项目概述与核心价值最近在折腾AI应用部署的时候&#xff0c;发现了一个挺有意思的项目&#xff0c;叫igolaizola/igogpt。乍一看这个名字&#xff0c;可能会有点摸不着头脑&#xff0c;但如果你对开源AI模型部署和WebUI界面搭建感兴趣&#xff0c;那这个项目绝对值得你花时间…...

AI助手状态可视化:像素风办公室看板的设计、部署与集成指南

1. 项目概述&#xff1a;一个像素风的AI办公室看板如果你和我一样&#xff0c;日常工作中重度依赖AI助手&#xff0c;比如OpenClaw&#xff0c;那你可能也遇到过这样的困惑&#xff1a;当AI在后台默默执行一个长任务时&#xff0c;你完全不知道它进行到哪一步了。是卡住了&…...

告别抖动与超调:深入剖析STM32直流电机控制中动态滤波与PI调节的协同优化策略

STM32直流电机控制进阶&#xff1a;动态滤波与PI调节的工程实践 在工业自动化与机器人控制领域&#xff0c;直流电机因其优异的调速性能仍是许多精密运动控制的首选。但当您已经搭建好基于STM32的PWM驱动和编码器反馈系统后&#xff0c;是否遇到过这样的困境&#xff1a;转速波…...

Adobe-GenP:探索Adobe全家桶功能解锁的智能解决方案

Adobe-GenP&#xff1a;探索Adobe全家桶功能解锁的智能解决方案 【免费下载链接】Adobe-GenP Adobe CC 2019/2020/2021/2022/2023 GenP Universal Patch 3.0 项目地址: https://gitcode.com/gh_mirrors/ad/Adobe-GenP Adobe-GenP是一款专为Adobe Creative Cloud用户设计…...

作业4:独立按键+数码管实操

文章目录 1.测试代码视频2.流水灯视频3.独立按键视频(点亮四个灯)4.独立按键视频(思考题点亮8个灯)5.数码管显示“111111”6.数码管显示“123456”7.数码管显示“11.12.13”8.数码管显示“HH8800.” 1.测试代码视频 测试2.流水灯视频 流水灯#include <reg51.h> // 包含…...

2026年最佳同城小程序推荐榜单,助你高效解锁本地生活

本文围绕同城小程序的技术架构、功能覆盖及实际应用效果展开深度解析&#xff0c;系统梳理了当前市场上的主流工具如何助力用户高效解锁本地生活服务。通过对多项核心指标的横向测评与案例分析&#xff0c;重点探讨了同城小程序在资源匹配效率、数据安全机制及生态扩展性方面的…...

初创团队如何利用 Taotoken 低成本启动 AI 功能开发与迭代

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 初创团队如何利用 Taotoken 低成本启动 AI 功能开发与迭代 对于资源有限的初创团队而言&#xff0c;在开发具备 AI 功能的产品时&a…...