为了方便开发,我打算实现一个Redis 工具集

Sentinel--哨兵系列数据下载地址及流程更新【202310】 哨兵系列数据下载地址及流程更新。哨兵系列卫星作为哥白尼计划的一部分,主要目标便是对地球的观测任务。哥白尼计划由三部分组成:空间部分(哨兵系列太空任务与其他太空机构任务)、测量部分(提供海洋、大陆表面和大气信息的陆基和机载数据收集网络)、数据管理与全球共享。 阅读详情

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料: 

e0d26e2efa3cb9c2b6bb8b17cb6e9d6b.gif

👉这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号等等功能:

  • Boot 地址:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • Cloud 地址:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn

来源:juejin.cn/post/
7254574621898686521


1 前言

Redis 基本上是互联网公司必备的工具了,Redis的应用场景实在太多了,但是有很多相似的功能如果每个项目都要实现一遍就显得太麻烦了,所以为了方便,我打算开发一个基于 Redis 的工具集,尽量做到开箱即用。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

2 目前实现功能

这个工具集并没有开发完成,实现了部分功能,如下图

d29752d82c3c356f79b70b8e54fe3b94.png

简单介绍下已经实现的模块:

  • common : 整个项目公共模块,比如AOP工具等;

  • delay: Redis实现的延迟队列;

  • lock: Redis实现的分布式锁;

  • mq: Redis实现消息队列;

  • query: Redis实现分页模糊查询;

  • web: Redis实现web相关的功能;

    • duplicate :防止重复提交;

以上的这些模块都是已经实现的了,还有 社交、限流、幂等相关功能后面会陆续实现。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

3 如何使用

1.引入 Maven 依赖

目前可以下载代码上传到自己的私服或者本地仓库,后面会推到 Maven 中央仓库

<dependency>
    <groupId>cn.org.wangchangjiu</groupId>
    <artifactId>redis-util-spring-boot-starter</artifactId>
    <version>1.0.0-SNAPSHOT</version>
</dependency>

2.配置文件(application.yaml)开启各模块功能开关

redis:
  util:
    mq:
      enable: true
    delay:
      enable: true

3.实现消息发送者

MQ消息发送:

cc4a8920e53e545a7363fe438787d054.png

延迟消息发送:

da8d34c4f1621674e0b20390d06b9da8.png

4.实现消息监听器

MQ消息监听器:

ed914265470136c20ce144b7690d4e26.png

延迟消息监听器:

4f3fc9c89aee8d160340c38f6c7f3385.png

4 MQ和delay实现细节

MQ实现细节

容器启动时,简单来说就是通过springboot自动装配,创建一些Bean,如下图:

9d3858e4ecaaea07612b44dde120bf4f.png

值得注意的是,springboot3.X 自动装配方式有点变化,需要创建文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,文件内容就直接写 自动配置类

57c4c7b1d31d1af81a233cbb808b41c5.png

RedisUtilAutoConfiguration 主自动装配类会 import 各个模块的自动装配类:

e224994c317206867a37f3915cfe1df2.png

我们以 RedisStreamAutoConfiguration 为例:

341c51d4f124624858dbf5abe1fff001.png

该装配类生效需要显示打开,然后就是创建各种Bean。

最主要的Bean有:

  • RedisMessageConsumerManager:

ca9c3057a964db76a036559f62ae3c91.png

该Bean实现了 BeanPostProcessor 接口,主要作用是,获取被注解 RedisMessageListener 修饰的方法,把信息封装在 RedisMessageConsumerContainer 对象里,方便后面反射调用。

1f898dcd3baf7cf6bd7a2e10d60202c0.png
  • StreamMessageListenerContainer:

这个Bean主要是做 redis MQ 的配置,比如配置:一次最多获取多少条消息、没有消息时阻塞时间、执行任务的executor、错误处理器、以及消费组、是否自动ACK等配置,具体代码如下:

@Bean(initMethod = "start", destroyMethod = "stop")
@DependsOn("redisMessageConsumerManager")
@ConditionalOnMissingBean
public StreamMessageListenerContainer<String, MapRecord<String, String, String>> streamMessageListenerContainer(@Autowired RedisMessageConsumerManager redisMessageConsumerManager,
                                                                                                                @Autowired RedisConnectionFactory redisConnectionFactory,
                                                                                                                @Autowired ErrorHandler errorHandler) {
    MyRedisStreamProperties.Options options = myRedisStreamProperties.getOptions();
    StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, MapRecord<String, String, String>> containerOptions =
            StreamMessageListenerContainer.StreamMessageListenerContainerOptions
                    .builder()
                    // 一次最多获取多少条消息
                    .batchSize(options.getBatchSize())
                    // 运行 Stream 的 poll task
                    .executor(getStreamMessageListenerExecutor())
                    // Stream 中没有消息时,阻塞多长时间,需要比 `spring.redis.timeout` 的时间小
                    .pollTimeout(options.getPollTimeout())
                    // 获取消息的过程或获取到消息给具体的消息者处理的过程中,发生了异常的处理
                    .errorHandler(errorHandler)
                    .build();

    StreamMessageListenerContainer<String, MapRecord<String, String, String>> streamMessageListenerContainer =
            StreamMessageListenerContainer.create(redisConnectionFactory, containerOptions);

    // 获取 被 RedisMessageListener 注解修饰的 bean
    Map<String, RedisMessageConsumerContainer> consumerContainerGroups =
            redisMessageConsumerManager.getConsumerContainerGroups();

    // 循环遍历,创建 消费组
    consumerContainerGroups.forEach((groupQueue, redisMessageConsumerContainer) -> {
        String[] groupQueues = groupQueue.split("#");

        // 创建消费组
        createGroups(groupQueues);

        RedisMessageListener redisMessageListener = redisMessageConsumerContainer.getRedisMessageListener();
        if(!redisMessageListener.useGroup()){
            // 独立消费 不使用组
            streamMessageListenerContainer.receive(StreamOffset.fromStart(groupQueues[1]), new DefaultGroupStreamListener(redisMessageConsumerContainer));
        } else {
            // 消费组 消费
            if(redisMessageListener.autoAck()){
                // 自动ACK
                streamMessageListenerContainer.receiveAutoAck(Consumer.from(groupQueues[0], "consumer:" + UUID.randomUUID()),
                        StreamOffset.create(groupQueues[1], ReadOffset.lastConsumed()), new DefaultGroupStreamListener(redisMessageConsumerContainer));
            } else {
                // 手动 ACK
                streamMessageListenerContainer.receive(Consumer.from(groupQueues[0], "consumer:" + UUID.randomUUID()),
                        StreamOffset.create(groupQueues[1], ReadOffset.lastConsumed()), new DefaultGroupStreamListener(redisMessageConsumerContainer));
            }
        }
    });
    return streamMessageListenerContainer;
}

/**
 *  创建消费组
 * @param groupQueues
 */
private void createGroups(String[] groupQueues) {
    // 判断是否存在队列Key
    if (stringRedisTemplate.hasKey(groupQueues[1])) {
        // 获取消费组 没有则创建
        StreamInfo.XInfoGroups groups = stringRedisTemplate.opsForStream().groups(groupQueues[1]);
        if (groups.isEmpty()) {
            stringRedisTemplate.opsForStream().createGroup(groupQueues[1], groupQueues[0]);
        } else {
            AtomicBoolean exists= new AtomicBoolean(false);
            groups.forEach(xInfoGroup -> {
                if (xInfoGroup.groupName().equals(groupQueues[0])){
                    exists.set(true);
                }
            });
            if(!exists.get()){
                stringRedisTemplate.opsForStream().createGroup(groupQueues[1], groupQueues[0]);
            }
        }
    } else {
        stringRedisTemplate.opsForStream().createGroup(groupQueues[1], groupQueues[0]);
    }
}

// todo 后面这个线程池也可以交由用户配置
private Executor getStreamMessageListenerExecutor() {
    AtomicInteger index = new AtomicInteger(1);
    int processors = Runtime.getRuntime().availableProcessors();
    ThreadPoolExecutor executor = new ThreadPoolExecutor(processors, processors, 0, TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(), r -> {
        Thread thread = new Thread(r);
        thread.setName("async-stream-consumer-" + index.getAndIncrement());
        thread.setDaemon(true);
        return thread;
    });
    return executor;
}

发送消息流程:

f4555ed626760436f4f400ec44c27a60.png

redis 延迟队列的实现原理和这个差不多,主要是 redission延迟队列 + 自定义注解 + 反射,代码都差不多。

5 工具地址

https://gitee.com/listen_w/redis-util-spring-boot-starter

https://github.com/jettwangcj/redis-util-spring-boot-starter


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,“长按”或“扫描”下方二维码噢:

f37898bdcc90fde7723769ccaf575208.png

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

dd828e82dd54010185262175eb24420f.png

5ad318c3f4b2ecebd8bdb88fc6a066e2.png29b8be231968e24bf9eb2363a53ab755.pngd6b7fb7adbb3761b7fc4161059441031.png70236e318eb33835f6af734f7f54e1fd.png

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
CST仿真提速秘籍:用好Local Mesh,别再让简单结构拖慢你的仿真速度 本文深入探讨了CST仿真中Local Mesh技术的应用,通过区域加密与全局排除策略,显著提升电磁仿真效率。针对5G天线阵列、微波滤波器等多尺度结构模型,提供了网格划分的黄金法则和实战技巧,帮助工程师优化仿真速度与精度,特别适用于电磁仿真和网格设置场景。 阅读详情

相关推荐

压电传感器信号放大难题?用运放设计电荷放大器的5个关键步骤

本文详细解析了压电传感器信号放大难题,并提供了用运放设计电荷放大器的5个关键步骤。从电压放大到电荷放大的范式转换,到运放选型、反馈网络设计、PCB布局及频响特性验证,帮助工程师解决工业自动化中的信号衰减问题,提升测量精度和稳定性。

weixin_27303545的博客 452

记一次使用redis stream创建的消息队列时,导致java服务的CPU、Memory过高的问题

首先通过jstack查看cpu过高的原因,进一步定位问题,由于本人对DefaultStreamMessageListenerContainer源码有操作,遂在服务中重写了该类的内容,由下方异常可以看出com.bot.base.biz.redis.rediesmq.stream.AIDefaultStreamMessageListenerContainer.lambda$getReadFunction$17(AIDefaultStreamMessageListenerContainer.java:255)出现

tikaber的博客 2508

告别软件轮询!用STM32G474的COMP比较器实现纳秒级硬件过压保护(CubeMX配置详解)

本文详细介绍了如何利用STM32G474的COMP比较器实现纳秒级硬件过压保护,通过CubeMX配置详解,展示了硬件比较器相比传统软件轮询方案在响应时间、CPU占用和可靠性等方面的显著优势。文章还提供了实战配置流程和优化技巧,帮助工程师快速构建高效的硬件保护系统。

weixin_28683689的博客 351

SpringBoot 中使用Redis Stream 实现消息监听优化

在之前的文章SpringBoot 中使用Redis Stream 实现消息监听中的demo代码写的比较乱,而且也有部分问题,随着最近有些小伙伴的交流我整理了一下代码,后续还会继续优化,感兴趣的可以在码云里拉取后实验和修改——码云地址hlove/redismq。 整理部分 整理后的代码我将redis的stream名称配置和组名通过配置文件的方式进行配置,application.yml文件如下: spring: redis: host: 127.0.0.1 password: yourpas

胡海龙 4965

深度学习模型轻量化方法之【量化】

量化虽然有着硬件友好和功效提升的特点,但它也引入了模型性能的折衷。因此,设计有效的量化策略需要在模型大小、性能以及运算速度之间做出平衡。随着深度学习算法和硬件加速技术的快速发展,量化方法在使深度网络轻量化和提高部署效率方面持续发挥着重要作用。

m0_73916791的博客 2850

从仿真到现实:BeamDojo双足机器人项目实战指南(附完整配置清单)

本文提供了一份基于BeamDojo项目的双足机器人从仿真训练到现实部署的完整实战指南。详细拆解了硬件选型(如宇树G1、Jetson Orin NX、Livox Mid-360)、Isaac Gym仿真环境搭建、强化学习训练技巧(如双评论家架构、课程学习)以及关键的Sim2Real迁移策略,旨在帮助开发者将前沿研究成果转化为可落地的工程实践。

hhh00的博客 877

一篇文章搞定Redis Stream

队列是一种数据结构,对应到我们生活中的例子,就是排队。讲究着先来先处理的原则,目的是为了避免混乱与系统瘫痪。消息队列把我们具体的业务,都抽象成为“消息”。排队做核酸,也可以叫做“核酸”队列。消峰填谷这点表现最明显的就是我们常说的秒杀系统,访问量在某一个刻,到达巅峰,然后又断崖式下跌。根据具体的业务场景,把业务处理的压力压入到消息队列中,以时间轴为水平线,来处理业务。消峰填谷异步解耦。

lt_xiaodou的博客 4099

Claude Code Router 401错误修复

claude code router配置相关环境变量问题

如沐春风 6364

芋道 Spring Boot Redis 入门

摘要: 原创出处http://www.iocoder.cn/Spring-Boot/Redis/「芋道源码」欢迎转载,保留摘要,谢谢! 1. 概述 2. 快速入门 3. 序列化 4. 项目实践 5. 示例补充 6. 尝试 Redisson 666. 彩蛋 本文在提供完整代码示例,可见https://github.com/YunaiV/SpringBoot-Labs的lab-11-spring-data-redis目录。 原创不易,给点个Star嘿,一起冲鸭! 1. 概述...

YHJ 5650

从原理到应用:深入解析双编码器在机器人关节力矩感知中的实现

本文深入解析了双编码器方案在机器人关节力矩感知中的实现原理与应用。该方案通过在电机侧和输出侧分别安装编码器,利用两者位置差异间接高精度计算外力,克服了传统电流环精度不足和扭矩传感器成本高昂的缺点。它为实现协作机器人的丝滑拖动示教、灵敏碰撞检测以及足式机器人的动态平衡与柔顺控制提供了关键技术支撑,是目前高性能机器人力控的主流选择。

t8u9v0w1x的博客 664

运维系列【仅供参考】: Windos10和Windos11 配置intel网卡vlan的方法

Windos10和Windos11 配置intel网卡vlan的方法

weixin_54626591的博客 477

芋道 Spring Boot Redis 入门(上)

点击上方“芋道源码做积极的人,而不是积极废人!源码精品专栏摘要: 原创出处 http://www.iocoder.cn/Spring-Boot/Redis/ 「芋道源码」欢迎转载,保留摘要,谢谢!1. 概述2. 快速入门2.1 引入依赖2.2 配置文件2.3 简单测试2.4 RedisTemplate3. 序列化3.1 RedisSerializer3.2 配置序列化方式3.3 自定义 Redi...

芋艿V 544

ISP 芯片作为独立设备节点的驱动实现要点:多平台结构差异与工程部署策略解析

随着 ISP(Image Signal Processor)从 SoC 集成形态向独立芯片模块演进,在多摄系统、高动态场景、AI 图像前处理等需求下,ISP 作为单独设备节点进行驱动设计已成为主流趋势。尤其在多 SoC 平台(如高通、联发科、展锐、Rockchip)中,不同厂商对 ISP 的抽象方式与驱动接口处理存在显著差异。本文以实际工程为基础,从 Linux 内核下的设备注册流程、media\_entity 配置、VideoDevice 分配、数据 DMA 管理、与 sensor 的流同步控制等关键点展

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 1466

为了便捷开发,我计划实现一个Redis 工具集

Redis 基本上是互联网公司必备的工具了,Redis的应用场景实在太多了,但是有很多相似的功能如果每个项目都要实现一遍就显得太麻烦了,所以为了方便,我打算开发一个基于 Redis 的工具集,尽量做到开箱即用。

wdj_yyds的博客 97

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

为了方便开发,我实现了一个Redis 工具集

来源:juejin.cn/post/ 7254574621898686521???? 欢迎加入小哈的星球,你将获得:专属的项目实战 / Java 学习路线 /一对一提问 / 学习打卡 / 每月赠书新项目:仿小红书(微服务架构)正在更新中... 。全栈前后端分离博客项目 2.0 版本完结啦,演示链接:http://116.62.199.48/。全程手摸手,后端 + 前端全栈开发,从 0 到 1...

犬小哈 91

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Redis工具集之限流

前一篇文章:为了方便开发,我打算实现一个Redis 工具集 主要介绍了开发 Redis 工具集的 MQ(Stream数据结构做消息队列)、delay(延迟队列)功能,这篇文件主要分享一下使用 redis 如何做分布式限流的设计方案。jMeter 压测工具配置:jMeter 压测结果:分析: burstCapacity = 10 ,初始化10个令牌,3秒钟产生 3 个令牌,共记 13个令牌。

他很懒,但也在努力的生活着 309

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Redis连接工具开发入门指南

作为一个刚接触Redis的新手,我最近尝试用Python开发了一个简单的Redis连接工具。整个过程下来,我最大的感受是:Redis的Python客户端设计得非常简洁,配合好的开发平台,新手也能快速上手。下一步我打算学习下如何处理更复杂的数据结构,比如列表和哈希。对于这种需要持续运行的服务类项目,平台的一键部署功能真是太省心了。上实践这个项目特别方便,不需要配置本地环境,直接在线就能运行代码。这里有个小技巧:Redis默认端口是6379,如果服务器在本机,host可以直接用'localhost'。

IndigoNight21的博客 930

redis安装windows_Win10安装Redis步骤总结

因为工作中开发需要用到Redis,之前都是使用内网服务器上安装的版本(Ubuntu系统),为了便于开发,打算在自己电脑上(Win10)安装一下。这里记录一下步骤。首先,Redis官网(https://redis.io/)没有提供Windows版本的安装程序,如果需要安装,需要到Github上下载适合Windows的版本。具体下载地址为:https://github.com/microsoftarc...

weixin_39687192的博客 2194

Redis模块开发,由Redis来触发RocketMQ Client进行发布消息

Redis有pubsub功能,我感觉用起来不方便,达不到我的要求,于是打算给Redis开发一个第三方模块,当key超时时自动通知RocketMQ超时的key,RocketMQ的消费者在消费消息,做响应的业务逻辑处理。   首先要做的就是github上下载RocketMQ的C++客户端源码: https://github.com/apache/rocketmq-client-cpp 然后编译...

Langeldep的专栏 1497

Redis开发最佳实践

Key的设计 易于管理 即能通过名称大概知道所涉及业务。通常我们会以service:characteristics来进行命名,如pubg_chat:uid:room_id的形式,这样可以尽可能避免冲突(当然,不同业务使用不同的Redis是更好的) 尽量简洁 Redis本质上是一个内存数据库,而内存的大小是远小于硬盘的。如果Key过大的话,会导致Redis所能存储的内容变少。所以在日常中推荐Key能...

a417484830的博客 1259

精通 Redis list:使用 redis-plus-plus 的现代 C++ 实践深度解析

在构建高性能应用的世界里,Redis 闪电般的内存数据结构与 C++ 的原生性能相结合,无疑是一剂成功的良方。Redis,常被称为“数据结构服务器”,提供了多种功能强大的工具,其中最基础也最核心的之一便是列表(List)。这种有序的字符串集合是实现队列、栈、活动流、消息推送等众多功能的基石。为了在 C++ 和 Redis 之间架起一座坚实的桥梁,一个健壮的客户端库至关重要。在这方面, 以其现代、类型安全和直观的设计脱颖而出。作为一个现代 C++11/14/17 客户端,它将 Redis 命令与开发者熟悉的

2301_80863610的博客 7568
上一篇: 轻松生成二维码:SpringBoot 与 ZXing 完美结合(综合指南)
下一篇: 腾讯重复造轮子?我们真的需要这么多RPC框架吗?
公众号-芋道源码
博客等级 码龄10年 1636粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值