Feign实现微服务间远程调用续;基于Redis实现消息队列用于延迟任务的处理,Redis分布式锁的实现;(黑马头条Day05)
目录
延迟任务和定时任务
使用Redis设计延迟队列原理
点评项目中选用list和zset两种数据结构进行实现
如何缓解Redis内存的压力同时保证Redis中任务能够被正确消费不丢失
系统流程设计
使用Feign实现微服务间的任务消费以及文章自动审核
系统微服务功能介绍
提交文章->审核文章执行流程
Redis中SET NX实现分布式锁
延迟任务和定时任务
定时任务
有固定周期,有明确的触发事件。
延迟任务
没有固定的开始时间,它常常是由一个事件触发的,而在这个事件触发之后的一段时间内触发另一个事件,任务可以立即执行,也可以延迟一段时间后执行。参考如下:
延迟任务的实现常常基于一个延迟队列,延迟队列的实现方案有:
DelayQueue、RebbitMQ、Redis中基于Zset数据结构的实现。【本篇文章主要介绍项目中使用到的Redis实现的延迟队列,后续会将其他方法实现的延迟队列逐步完善总结】
使用Redis设计延迟队列原理
Redis的基本数据结构中的Zset内部可以根据给定的权重对元素进行排序,随后使用
stringRedisTemplate.opsForZSet().rangeByScore(key, min, max),对指定的Key寻找score在min-max间的元素。在向Zset中插入元素的时候可以将优先级设置为socre,如果将时间作为优先级实现延迟队列,可以在插入元素同时获取当前系统时间作为socre,如果需要指定5min后执行,则将当前系统获取的时间+5min作为对应元素的socre值。实现基于Redis作为延迟队列。
点评项目中选用list和zset两种数据结构进行实现
常规需求下基于Redis实现的延迟队列,只需要根据zset设置对应元素的score即可实现,如果进一步考虑数据量非常大的情况下此时时间复杂度比较高。在zset中分别使用zadd(.)以及zrange(.)的时间复杂度分别为:
- ZADD时间复杂度O(M*logN):M成功添加的元素数,N是有序集合的基数。
- ZRANGE:按照从低到高的顺序,获取指定排名范围内的成员。时间复杂度:O(log(N)+M),其中 N 是有序集合的基数,M 是指定排名范围内的成员数量。
选用list和zset相结合的方式实现延迟队列,list中存储当前需要执行的任务,zset中存储需要延迟(未来执行)的任务,此时向list的一端存储元素并从list的另一端取出元素,不仅可以保证任务消费的有序性,同时list中存储以及获取元素的时间复杂度均为O(1)在数据量大的情况下性能更优。
如何缓解Redis内存的压力同时保证Redis中任务能够被正确消费不丢失
Redis是基于内存的数据库,有一定的存储容量,可以采用Redis+MySQL相结合的方式。
- 每次到达一个新的任务需要延迟消费时,首先将对应任务存储到MySQL数据中,其次将其根据消费时间(立马消费、延迟消费)存储到对应list或zset中。
- 在任务被消费时,首先从Redis的list中获取元素进行消费,并将任务从Redis中删除,同时将对应的任务从MySQL数据库中进行删除,避免重复消费。
- 任务需要消费时首先将其存储到MySQL中,随后将对应时间范围内(比如小于当前时间5min)存入到Redis中,时间大于规定范围的存储到MySQL数据库中,并且每消费一条Redis中的任务同时将MySQL中对应的任务清理。所以MySQL中存储的任务均是未消费的任务,使用定时任务从MySQL中提取任务并加载到Redis中进行消费,此操作必须先将Redis中的任务全部清空,避免相同的任务再次加载到Redis中被重复消费。
- zset中存储的任务借助Spring Task框架提供的定时任务功能,按照一定时间间隔自动根据score提取对应范围的任务并将其加载到list中进行消费。
系统流程设计
使用Feign实现微服务间的任务消费以及文章自动审核
系统微服务功能介绍
- ①:feign微服务:定义feign远程调用的接口。
- ②:article微服务:app端数据存储,以及实现feign中定义的保存文章配置相关接口。
- ③:schedule微服务:消息队列微服务,实现任务MySQL的记录以及Redis中任务的消费。同时实现feign中定义的调用延迟队列的接口。
- ④:wemedia微服务:浏览器端/管理端实现,用于实现保存自媒体文章,调用sehedule微服务,实现任务延迟消费以及调用article微服务实现文章自动审核后保存app端文章相关信息。
为什么需要将延迟队列相关实现单独防止在一个微服务schedule中:
提高复用性,如果将延迟队列实现防止在wemedia微服务中,直接进行调用可以省去不必要的远程调用过程或者MQ实现。同时出现如果其他微服务也需要使用到Redis实现的消息队列,此时需要重新实现,所以将其抽取为一个单独的微服务,提高复用性。
提交文章->审核文章执行流程
可以参考SpringCloud Feign实现微服务间的远程调用(黑马头条Day04)-CSDN博客 的了解Feign的远程调用的简单原理。
- 自媒体发布文章,远程调用消息队列微服务,将任务存入消息(延迟)队列。
- 自媒体微服务通过远程调用定时拉取消息队列中的任务进行文章审核。
- 自媒体微服务审核完文章后调用app端相关微服务,将文章相关html页面对应的url路径等信息存入到文章相关数据表。
上图中有两个地方并没有画出:
- 延迟队列微服务定期从zset中根据score范围取数据并放进list中进行消费。
- 延迟队列微服务定期从MySQL数据库中加载未消费的任务到延迟队列。
贴两个小代码:
/*** 定时刷新数据从ZSet到list中*/@Scheduled(cron = "0 */1 * * * ?")public void refresh(){// 添加分布式锁String token = cacheService.tryLock("FUTURE_TASK_SYNC", 1000 * 30);if(StringUtils.isNotBlank(token)){log.info("启动定时刷新任务,当前时间为:{}", System.currentTimeMillis() / 1000);// 获取所有未来数据的集合的keySet<String> fututrKeys = cacheService.scan(ScheduleConstants.FUTURE + "*");for (String fututrKey : fututrKeys) {// 根据futureKey计算topicKeyString topicKey = ScheduleConstants.TOPIC + fututrKey.split(ScheduleConstants.FUTURE)[1];// 获取该组key下需要消费的数据Set<String> tasks = cacheService.zRangeByScore(fututrKey, 0, System.currentTimeMillis());// 将需要消费的任务添加list中if(!tasks.isEmpty()){cacheService.refreshWithPipeline(fututrKey, topicKey, tasks);log.info("成功的将{}对应的数据刷新到{}中", fututrKey, topicKey);}}}}/*** 定时加载数据库中的数据到Redis中*/@PostConstruct // 开启即加载@Scheduled(cron = "0 */5 * * * ?")public void reloadData(){// 清理缓存中的数据clearCache();// 查询数据库中数据,根据执行时间小于当前时间5min// 获取5分钟后的时间Calendar calendar = Calendar.getInstance();calendar.add(Calendar.MINUTE, 5);List<Taskinfo> taskinfos = taskinfoMapper.selectList(Wrappers.<Taskinfo>lambdaQuery().lt(Taskinfo::getExecuteTime, calendar.getTime()));if(taskinfos != null && taskinfos.size() > 0){// 将查询的数据添加到缓存中for (Taskinfo taskinfo : taskinfos) {Task task = new Task();BeanUtils.copyProperties(taskinfo, task);task.setExecuteTime(taskinfo.getExecuteTime().getTime());addTaskToRedis(task);log.info("添加任务到Redis中:{}", task);}}}/*** 清理缓存中的数据*/private void clearCache() {Set<String> topicKey = cacheService.scan(ScheduleConstants.TOPIC + "*");Set<String> futureKey = cacheService.scan(ScheduleConstants.FUTURE + "*");cacheService.delete(topicKey);cacheService.delete(futureKey);}
Redis中SET NX实现分布式锁
为什么需要分布式锁:控制分布式系统有序的去对共享资源进行操作,通过互斥来保证数据的一致性。考虑以下场景,如果两个延迟队列微服务同时从zset中刷新未来要执行的任务到list中,由于两个微服务设置的定时时间都一样,此时会出现共享变量的重复操作。
使用Redis实现的分布式锁保证同一时刻只有一个微服务操作共享资源。
sexnx (SET if Not eXists) 命令在指定的 key 不存在时,为 key 设置指定的值。
这种加锁的思路是,如果 key 不存在则为 key 设置 value,如果 key 已存在则 SETNX 命令不做任何操作
客户端A请求服务器设置key的值,如果设置成功就表示加锁成功
客户端B也去请求服务器设置key的值,如果返回失败,那么就代表加锁失败
客户端A执行代码完成,删除锁
客户端B在等待一段时间后再去请求设置key的值,设置成功
客户端B执行代码完成,删除锁
可以参考Redission实现的分布式锁:Redis分布式锁实现-CSDN博客。
暂时写到这里,有时间再补.....
相关文章:

Feign实现微服务间远程调用续;基于Redis实现消息队列用于延迟任务的处理,Redis分布式锁的实现;(黑马头条Day05)
目录 延迟任务和定时任务 使用Redis设计延迟队列原理 点评项目中选用list和zset两种数据结构进行实现 如何缓解Redis内存的压力同时保证Redis中任务能够被正确消费不丢失 系统流程设计 使用Feign实现微服务间的任务消费以及文章自动审核 系统微服务功能介绍 提交文章-&g…...
CSS 常见属性设置
一. 文本属性 1.1. 装饰线 text-decoration text-decoration有如下常见取值: none:无任何装饰线(可以去除a元素默认的下划线)underline:下划线overline:上划线line-through:中划线(删除线&…...

docker学习入门
1、docker简介 docker官网: www.docker.com dockerhub官网: hub.docker.com docker文档官网:docs.docker.com Docker是基于Go语言实现的云开源项目。 Docker的主要目标是:Build, Ship and Run Any App, Anywhere(构建&…...

蓝牙系列七:开源蓝牙协议栈BTStack数据处理
继续蓝牙系列的研究。 在上篇博客,通过阅读BTStack的源码,大体了解了其框架,对于任何一个BTStack的应用程序都有一个main函数,这个main函数是统一的。这个main函数做了某些初始化之后,最终会调用到应用程序提供的btstack_main,在btstack_main里面首先做一些初始化,然后…...
数据仓库作业一:第1章 绪论
目录 一、给出下列英文短语或缩写的中文名称,并简述其含义。二、简述操作型数据与分析型数据的主要区别。三、简述数据仓库的定义。四、简述数据仓库的特征。五、简述主题的定义。六、简述元数据的概念。七、简述数据挖掘的主要任务。八、简述数据挖掘的主要步骤。九…...
spring aop中获取request和response
Spring AOP 操作中如何使用request和response 实际使用时,如果方法一不行,请使用方法二 方法一 HttpServletRequest request ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); HttpServletResponse respons…...

在Mac上安装nginx+rtmp 本地服务器
需要使用终端命令,如果没有Homebrew,要安装Homebrew,执行: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 一、安装Nginx 1、先clone Nginx项目到本地: brew tap de…...

解决ChatGPT发送消息没有反应
ChatGPT发消息没反应 今天照常使用ChatGPT来帮忙码代码,结果发现发出去的消息完全没有反应,即不给我处理,也没有抱任何的错误,按浏览器刷新,看起来很正常,可以查看历史对话,但是再次尝试还是一…...

windows关闭copilot预览版
如果用户不想在windows系统当中启用Copilot,可以通过以下三种方式禁用。 第一种:隐藏Copilot 按钮 右键点击任务栏,取消勾选“显示 Copilot(预览版)按钮”,任务栏则不再显示,用户可以通过快捷键…...

基于Java的社区买菜系统(Vue.js+SpringBoot)
目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.1.1 数据中心模块2.1.2 菜品分类模块2.1.3 菜品档案模块2.1.4 菜品订单模块2.1.5 菜品收藏模块2.1.6 收货地址模块 2.2 可行性分析2.3 用例分析2.4 实体类设计2.4.1 菜品分类模块2.4.2 菜品档案模块2.4.3…...

html--心花怒放
代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>Canvas 绘制一个❤</title><link rel"shortcut icon" href"../../assets/images/icon/favicon.ico" type"ima…...

FPGA的配置状态字寄存器Status Register
目录 简介 状态字定义 Unknown Device/Many Unknow Devices 解决办法 一般原因 简介 Xilinx的FPGA有多种配置接口,如SPI,BPI,SeletMAP,Serial,JTAG等;如果从时钟发送者的角度分,还可以…...
【HarmonyOS Arkts笔记】http网络请求封装
common.ts export default class CommonConstant {/*** The host address of the server.*/static readonly SERVER: string 请求接口地址;/*** The request success code.*/static readonly SUCCESS_CODE: number 200;/*** Read timeout.*/static readonly READ_TIMEOUT: n…...

html前端的几种加密/解密方式
HTML前端的加密解密方式有以下几种: 一、base64加密 Base64编码:Base64是一种将二进制数据转换为可打印字符的编码方式。在前端,可以使用JavaScript的btoa()函数进行Base64编码,使用atob()函数进行解码。 var str "hello…...

算法学习01:排序二分
算法学习01:排序&&二分 文章目录 算法学习01:排序&&二分前言需要记忆的模版:快速排序归并排序:整数二分:浮点数二分 一、排序1.快速排序2.归并排序: 二、二分1.整数2.浮点数 总结 前言 需要…...

OpenAI (ChatGPT)中国免费试用地址
GitHub - click33/chatgpt---mirror-station-summary: 汇总所有 chatgpt 镜像站,免费、付费、多模态、国内外大模型汇总等等 持续更新中…… 个人能力有限,搜集到的不多,求大家多多贡献啊!众人拾柴火焰高!汇总所有 cha…...
IOS面试题object-c 11-20
11、解释self [super init]方法? 容错处理, 当父类初始化失败,会返回一个nil, 表示初始化失败。 由于继承的关系, 子类是需要拥有父类的实例和行为, 因此, 我们必须先初始化父类,然后再初始化子类 12、简述使用block有什么优点?代码紧凑,传值…...
北斗导航 | 十四种抗差稳健估计(抗差M估计)方法(算法公式)
===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 稳健估计(M估计) 1、Huber法2、残差绝对和最小法3、L1-L2法...

【JavaEE】_Spring MVC项目使用数组与集合传参
目录 1. 使用数组传参 1.2 传递单个参数 1.3 传递多个名称相同的参数 1.3.1 关于urlencode 2. 使用集合传参 1. 使用数组传参 创建一个Spring MVC项目,其中 .java文件内容如下: package com.example.demo.controller;import com.example.demo.Per…...

Centos 9 安装 k8s
为了尽可能契合生产环境的部署情况,这里用kubeadm安装集群,同时方便跟随笔记一步步实践的过程,也更加了解k8s的一些特性和基础知识。 先决条件 这里将通过虚拟机安装3台centos stream 9服务器,并组成kubeneters集群(…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

2021-03-15 iview一些问题
1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...

【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...