什么是死信队列?死信队列是如何导致的?
死信交换机(Dead Letter Exchange,DLX)
- 定义:死信交换机是一种特殊的交换机,专门用于**接收从其他队列中因特定原因变成死信的消息**。它的本质还是交换机,遵循RabbitMQ中交换机的基本工作原理,如根据路由规则将消息发送到绑定的队列。
- 作用:为死信提供一个集中处理的入口点。通过将死信发送到死信交换机,再由其路由到相应的死信队列,可以方便地对这些异常消息进行统一管理和处理,确保数据不丢失。
死信队列(Dead Letter Queue,DLQ)
- 定义:死信队列用于存储那些无法在正常流程中被消费的消息,即死信。这些消息进入死信队列后,可以后续进行分析、重试或其他特殊处理。
- 产生死信的原因:
- 消息被拒绝且不重新入队:消费者调用
basic.reject
或basic.nack
方法拒绝消息,并将requeue
参数设置为false
,表明该消息不再重新放回原队列等待消费,从而成为死信。 - 消息过期:可以为消息或队列设置生存时间(TTL,Time-To-Live)。当消息在队列中的存活时间超过设定的TTL值时,消息就会过期成为死信。消息的TTL既可以在发送消息时针对单条消息设置,也可以在声明队列时对队列中的所有消息统一设置。
- 队列达到最大长度:当为队列设置了最大长度(
Max-Length
),并且队列中的消息数量达到这个上限时,新进入的消息会被丢弃成为死信。
- 消息被拒绝且不重新入队:消费者调用
代码举例
下面将用代码举例,由于消息过期而进入死信队列
初始化RabbitMQ的连接配置、队列和交换机的声明
/*** RabbitMQ配置类* 负责管理RabbitMQ的连接配置、队列和交换机的声明*/
@Slf4j
public class RabbitMQConfig {// 普通队列和死信队列的配置常量public static final String NORMAL_QUEUE = "normal.queue"; // 普通队列名称public static final String DLX_QUEUE = "dlx.queue"; // 死信队列名称public static final String NORMAL_EXCHANGE = "normal.exchange"; // 普通交换机名称public static final String DLX_EXCHANGE = "dlx.exchange"; // 死信交换机名称public static final String NORMAL_ROUTING_KEY = "normal.routing.key"; // 普通路由键public static final String DLX_ROUTING_KEY = "dlx.routing.key"; // 死信路由键/*** 创建RabbitMQ连接** @return Connection RabbitMQ连接对象* @throws Exception*/public static Connection createConnection() throws Exception {ConnectionFactory factory = new ConnectionFactory();factory.setHost("xxxx"); // 设置RabbitMQ服务器地址factory.setPort(5672); // 设置RabbitMQ服务器端口factory.setUsername("xxxx"); // 设置用户名factory.setPassword("xxxx"); // 设置密码return factory.newConnection(); // 创建并返回新的连接}/*** 初始化RabbitMQ的队列和交换机* 包括:* 1. 删除已存在的队列和交换机* 2. 声明死信交换机和队列* 3. 声明普通交换机和队列* 4. 设置队列的死信参数* 5. 绑定队列和交换机** @throws Exception*/public static void init() throws Exception {try (Connection connection = createConnection();Channel channel = connection.createChannel()) {// 删除已存在的队列和交换机try {channel.queueDelete(NORMAL_QUEUE);channel.queueDelete(DLX_QUEUE);channel.exchangeDelete(NORMAL_EXCHANGE);channel.exchangeDelete(DLX_EXCHANGE);} catch (Exception e) {// 忽略删除不存在的队列或交换机时的错误log.warn("删除队列或交换机时出错(可能是首次创建): {}", e.getMessage());}// 声明死信交换机,类型为direct,持久化channel.exchangeDeclare(DLX_EXCHANGE, "direct", true);// 声明死信队列,持久化channel.queueDeclare(DLX_QUEUE, true, false, false, null);// 将死信队列绑定到死信交换机,使用死信路由键channel.queueBind(DLX_QUEUE, DLX_EXCHANGE, DLX_ROUTING_KEY);// 声明普通交换机,类型为direct,持久化channel.exchangeDeclare(NORMAL_EXCHANGE, "direct", true);// 设置普通队列的死信参数Map<String, Object> args = new HashMap<>();args.put("x-dead-letter-exchange", DLX_EXCHANGE); // 设置死信交换机args.put("x-dead-letter-routing-key", DLX_ROUTING_KEY); // 设置死信路由键// 声明普通队列,并应用死信参数channel.queueDeclare(NORMAL_QUEUE, true, false, false, args);// 将普通队列绑定到普通交换机,使用普通路由键channel.queueBind(NORMAL_QUEUE, NORMAL_EXCHANGE, NORMAL_ROUTING_KEY);}}
}
消息生产者
/*** 消息生产者类* 负责向RabbitMQ发送消息*/
@Slf4j
public class MessageProducer {/*** 发送消息到普通队列* 该方法会:* 1. 创建RabbitMQ连接和通道* 2. 将消息发布到普通交换机* 3. 使用try-with-resources自动关闭连接和通道* * @param message 要发送的消息内容* @throws Exception */public void sendMessage(String message) throws Exception {// 使用try-with-resources自动管理连接和通道的关闭try (Connection connection = RabbitMQConfig.createConnection();Channel channel = connection.createChannel()) {// 打印发送的消息内容log.info("发送消息: {}", message);// 发布消息到普通交换机// 参数说明:// 1. 交换机名称// 2. 路由键// 3. 消息属性(这里为null表示使用默认属性)// 4. 消息内容(转换为字节数组)channel.basicPublish(RabbitMQConfig.NORMAL_EXCHANGE,RabbitMQConfig.NORMAL_ROUTING_KEY,null,message.getBytes());}}/*** 发送带TTL的消息到普通队列* 该方法会:* 1. 创建RabbitMQ连接和通道* 2. 设置消息的TTL属性* 3. 将消息发布到普通交换机* 4. 使用try-with-resources自动关闭连接和通道* * @param message 要发送的消息内容* @param ttl 消息的过期时间(毫秒)* @throws Exception 如果发送过程中出现错误则抛出异常*/public void sendMessageWithTTL(String message, int ttl) throws Exception {// 使用try-with-resources自动管理连接和通道的关闭try (Connection connection = RabbitMQConfig.createConnection();Channel channel = connection.createChannel()) {// 设置消息属性,包括TTLAMQP.BasicProperties properties = new AMQP.BasicProperties.Builder().expiration(String.valueOf(ttl)).build();// 打印发送的消息内容log.info("发送消息: {}, TTL: {}ms", message, ttl);// 发布消息到普通交换机// 参数说明:// 1. 交换机名称// 2. 路由键// 3. 消息属性(包含TTL)// 4. 消息内容(转换为字节数组)channel.basicPublish(RabbitMQConfig.NORMAL_EXCHANGE,RabbitMQConfig.NORMAL_ROUTING_KEY,properties,message.getBytes());}}
}
消息消费者
/*** 消息消费者类* 负责从普通队列和死信队列中消费消息*/
@Slf4j
public class MessageConsumer {/*** 消费普通队列中的消息* 该方法会:* 1. 创建RabbitMQ连接和通道* 2. 设置预取计数为1,确保公平分发* 3. 创建消费者回调处理消息* 4. 确认消息处理完成** @throws Exception 异常*/public void consumeNormalQueue() throws Exception {// 创建RabbitMQ连接和通道Connection connection = RabbitMQConfig.createConnection();Channel channel = connection.createChannel();// 设置预取计数为1,确保公平分发,避免某个消费者处理过多消息channel.basicQos(1);// 创建普通队列消费者回调DeliverCallback deliverCallback = (consumerTag, delivery) -> {// 获取消息内容String message = new String(delivery.getBody(), StandardCharsets.UTF_8);log.info("收到普通队列消息: {}", message);// 模拟消息处理耗时try {Thread.sleep(20000);} catch (InterruptedException e) {throw new RuntimeException(e);}// 确认消息处理完成channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);};// 开始消费普通队列// 参数说明:// 1. 队列名称// 2. 是否自动确认消息(false表示手动确认)// 3. 消息处理回调// 4. 消费者取消回调(这里为空实现)channel.basicConsume(RabbitMQConfig.NORMAL_QUEUE, false, deliverCallback, consumerTag -> {});}/*** 消费死信队列中的消息* 该方法会:* 1. 创建RabbitMQ连接和通道* 2. 设置预取计数为1,确保公平分发* 3. 创建消费者回调处理消息* 4. 确认消息处理完成** @throws Exception 异常*/public void consumeDlxQueue() throws Exception {// 创建RabbitMQ连接和通道Connection connection = RabbitMQConfig.createConnection();Channel channel = connection.createChannel();// 设置预取计数为1,确保公平分发channel.basicQos(1);// 创建死信队列消费者回调DeliverCallback deliverCallback = (consumerTag, delivery) -> {// 获取消息内容String message = new String(delivery.getBody(), StandardCharsets.UTF_8);log.info("收到死信队列消息: {}", message);// 确认消息处理完成channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);};// 开始消费死信队列// 参数说明:// 1. 队列名称// 2. 是否自动确认消息(false表示手动确认)// 3. 消息处理回调// 4. 消费者取消回调(这里为空实现)channel.basicConsume(RabbitMQConfig.DLX_QUEUE, false, deliverCallback, consumerTag -> {});}
}
测试
@Slf4j
public class DLXTest {private static final int THREAD_COUNT = 1; // 并发线程数private static final int MESSAGE_COUNT = 2; // 每个线程发送的消息数/*** 主方法,执行死信队列测试流程* 测试流程:* 1. 初始化RabbitMQ的队列和交换机* 2. 创建生产者和消费者实例* 3. 启动普通队列和死信队列的消费者线程* 4. 使用线程池发送测试消息* 5. 等待消息处理完成** @param args* @throws Exception*/public static void main(String[] args) throws Exception {// 初始化RabbitMQ的队列和交换机RabbitMQConfig.init();// 创建生产者和消费者实例MessageProducer producer = new MessageProducer();MessageConsumer consumer = new MessageConsumer();// 启动普通队列消费者线程new Thread(() -> {try {consumer.consumeNormalQueue();} catch (Exception e) {log.error("普通队列消费者异常", e);}}).start();// 启动死信队列消费者线程new Thread(() -> {try {consumer.consumeDlxQueue();} catch (Exception e) {log.error("死信队列消费者异常", e);}}).start();// 创建线程池和计数器ExecutorService executorService = Executors.newFixedThreadPool(THREAD_COUNT);CountDownLatch latch = new CountDownLatch(THREAD_COUNT);// 提交任务到线程池for (int i = 0; i < THREAD_COUNT; i++) {final int threadId = i;executorService.submit(() -> {try {// 每个线程发送MESSAGE_COUNT条消息for (int j = 0; j < MESSAGE_COUNT; j++) {// 随机生成消息TTL(1-30秒)int ttl = (int) (Math.random() * 30000) + 1000;String message = String.format("消息-线程%d-第%d条 (消息TTL: %dms)", threadId + 1, j + 1, ttl);producer.sendMessageWithTTL(message, ttl);// 随机延迟0-100ms,模拟真实场景Thread.sleep((long) (Math.random() * 100));}} catch (Exception e) {log.error("发送消息异常", e);} finally {latch.countDown();}});}// 等待所有消息发送完成latch.await();log.info("所有消息已发送完成");// 关闭线程池executorService.shutdown();executorService.awaitTermination(1, TimeUnit.MINUTES);// 保持程序运行,等待消息处理完成Thread.sleep(60000);log.info("测试完成");}
}
从结果可以看出,第一条消息 ttl 为 28301ms,被普通消费者进行消费,而产生的第二条消息得到 ttl 为 4332ms,由于第一条消息在消费时耗时较久,在此期间 第二条消息已经过期,不得不进入死信队列,由死信消费者进行处理,从前面的日志时间也可以看出,刚好间隔 4s 左右。
相关文章:
什么是死信队列?死信队列是如何导致的?
死信交换机(Dead Letter Exchange,DLX) 定义:死信交换机是一种特殊的交换机,专门用于**接收从其他队列中因特定原因变成死信的消息**。它的本质还是交换机,遵循RabbitMQ中交换机的基本工作原理,…...
计算机网络:深入分析三层交换机硬件转发表生成过程
三层交换机的MAC地址转发表生成过程结合了二层交换和三层路由的特性,具体可分为以下步骤: 一、二层MAC地址表学习(基础转发层) 初始状态 交换机启动时,MAC地址表为空,处于学习阶段。 数据帧接收与源MAC学习 当主机A发送数据帧到主机B时,交换机会检查数据帧的源MAC地址。…...
java使用MinIO,虚拟机时间异常
使用docker进行环境部署和启动 docker pull minio/miniodocker run -d -p 9000:9000 -p 9001:9001 \-e "MINIO_ROOT_USERminio" \-e "MINIO_ROOT_PASSWORDminio123" \-v /opt/minio/data:/data \-v /opt/minio/config:/root/.minio \minio/minio server --…...
使用Jmeter进行核心API压力测试
最近公司有发布会,需要对全链路比较核心的API的进行压测,今天正好分享下压测软件Jmeter的使用。 一、什么是Jmeter? JMeter 是 Apache 旗下的基于 Java 的开源性能测试工具。最初被设计用于 Web 应用测试,现已扩展到可测试多种不同的应用程…...
嵌入式学习笔记 - LCD
一 显示器接口种类: 下图中间左边一个为不带MCU的RGB屏,中间右边一个为带MCU的MCU屏 带控制器的LCD屏幕跟STM32单片机的交互方式,可以为串口,也可以为SPI,或者8080,通过命令的方式对液晶控制器芯片进行操作…...
聊聊Spring AI Alibaba的SentenceSplitter
序 本文主要研究一下Spring AI Alibaba的SentenceSplitter SentenceSplitter spring-ai-alibaba-core/src/main/java/com/alibaba/cloud/ai/transformer/splitter/SentenceSplitter.java public class SentenceSplitter extends TextSplitter {private final EncodingRegis…...
Python 异常处理与文件 IO 操作:构建健壮的数据处理体系(3/10)
摘要:在 Python 开发中,异常处理和文件 IO 操作是构建稳定程序的基石。本文将深入探讨异常捕获机制、上下文管理器原理,并结合 JSON/CSV 数据持久化与实战项目,帮助你掌握应对复杂场景的核心技术。 本文深入探讨了 Python 编程中的…...
Python中,正则表达式,
目录 1.基本匹配2.量词3.边界匹配4.选择和逻辑5.示例代码 在Python中,正则表达式(Regular Expressions,简称regex)是一种强大的文本处理工具,用于匹配、查找和替换字符串中的模式。Python通过 re模块提供正则表达式支…...
CSS:元素显示模式与背景
元素显示模式 元素显示模式是指元素在浏览器页面中显示的模式,比如<div></div>是独占一行的块级元素,<span></span>是行内元素 元素显示模式分为三大类: 块级元素行内元素行内块元素 块级元素 block 常见的块级…...
Java游戏服务器开发流水账(2)开发中Maven的管理
Maven 是一款流行的 Java 项目管理工具,它基于项目对象模型(Project Object Model,POM)的概念来管理项目的构建、依赖和文档等。游戏服务器开发中也会使用. 项目构建 生命周期管理:Maven 定义了一套清晰的项目构建生…...
学习设计模式《八》——原型模式
一、基础概念 原型模式的本质是【克隆生成对象】; 原型模式的定义:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象 。 原型模式的功能: 1、通过克隆来创建新的对象实例; 2、为克隆出来的新对象实例复制…...
【MySQL】存储引擎 - MEMORY详解
📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...
正则表达式实用指南:原理、场景、优化与引擎对比
正则表达式实用指南:原理、场景、优化与引擎对比 正则表达式(Regular Expression,简称 regex 或 regexp)是程序员处理文本数据时不可或缺的“瑞士军刀”。无论是表单校验、日志分析、数据清洗,还是敏感信息脱敏&#…...
Python3正则表达式:字符串魔法师的指南[特殊字符]♂️
Python3正则表达式 什么是正则表达式?在Python中使用正则表达式一、正则表达式基础语法:你的魔法咒语基本匹配符字符类:性格各异的字符们预定义字符类:常见角色的快捷方式重复限定符:贪婪的收集者贪婪vs非贪婪…...
k8s术语之CronJob
CronJob管理基于时间的Job,即: 在给定时间点只运行一次 周期性地在给定时间点运行 一个CronJob对象类似于crontab文件中的一行。它根据指定的预定计划周期地运行一个Job,格式可以参考Cron 前提条件 当前使用地Kubernetes集群,版本>1.8.对…...
常见的提示词攻击方法 和防御手段——提示词注入(Prompt Injection)攻击解析
提示词注入(Prompt Injection)攻击解析 提示词注入是一种针对大型语言模型(LLM)的新型攻击手段,攻击者通过精心设计的输入文本(提示词)操控AI模型的输出,使其执行非预期行为或泄露敏…...
软件逆向工程核心技术:脱壳原理与实战分析
目录 一、脱壳技术概述:从保护到还原的逆向之旅 1.1 脱壳技术的本质与核心价值 1.2 壳的分类与核心技术解析 1.3 学习路径:从压缩壳到加密壳的渐进式突破 二、脱壳三步法:系统化逆向工程框架 2.1 核心流程总览 2.2 实战案例࿱…...
C27-简单选择排序法
一 基本思想 每轮从待排序序列中选出最小或最大的元素,与待排序区间起始位置交换,逐步缩小待排序区间 二 算法实现 遍历数组:设数组长度为n,外层循环i从0到n-2(共n-1轮) 找最小值下标:内层循环j从i1到n-1,遍历待排序区间(i到n-1),记录找最小值下标min 交换元素:将arr[i]与a…...
【Redis】持久化与事务
文章目录 1. 持久化1.1 RDB(定期)1.1.1 触发方式1.1.2 触发流程 1.2. AOF(实时)1.2.1 设置AOF1.2.2 刷新策略1.2.3 重写机制 2. 事务2.1 redis事务概念2.2 事务操作 Mysql有几个特性: 原子性一致性隔离性,redis是串行的,自带隔离性持久性&…...
Web 自动化之 HTML JavaScript 详解
文章目录 一、HTML 常用标签二、javascript 脚本1、什么是 javascript(js)2、 js变量和函数3、js 弹窗处理4、js 流程控制语句和 switch 结构语句应用 一、HTML 常用标签 HTML:超文本标记语言 超文本:不仅只包含文字,还有超链接、视频…这些…...
【JavaScript】二十九、垃圾回收 + 闭包 + 变量提升
文章目录 1、作用域1.1 局部作用域1.2 全局作用域1.3 作用域链 2、JC垃圾回收机制♻️3、GC算法3.1 引用计数法3.2 标记清除法 4、闭包4.1 定义4.2 闭包的应用:实现数据的私有 5、变量提升 1、作用域 即一个范围,离开了这个范围,这个变量就不…...
Python在自动驾驶实时数据处理中的应用:让AI驾驶更智能、更高效
Python在自动驾驶实时数据处理中的应用:让AI驾驶更智能、更高效 近年来,自动驾驶技术的飞速发展离不开人工智能和数据处理的支撑,而Python作为AI与数据分析的核心编程语言,在自动驾驶实时数据处理方面扮演着不可或缺的角色。从传感器数据解析,到路径规划与决策优化,再到…...
功能安全的关键——MCU锁步核技术全解析(含真实应用方案)
随着智能汽车的发展,整车对功能安全的要求越来越高。特别是像电动助力转向(EPS)、制动控制系统、气囊控制器这类对“出错零容忍”的系统,已经广泛采用一种重要的安全架构——锁步核(Lockstep Core)。 今天我…...
Java实现桶排序算法
1. 桶排序原理图解 桶排序是一种基于分桶思想的非比较排序算法,适用于数据分布较为均匀的场景。其核心思想是将数据分散到有限数量的“桶”中,每个桶再分别进行排序(通常使用插入排序或其他简单的排序算法)。以下是桶排序的步骤&a…...
剖析 FFmpeg:从基本功能到过滤器,实现音视频处理的灵活性
目录 1.解复用2 解码2.1 音频解码2.2 视频解码 3 修饰3.1 avio3.2 重采样 4 过滤器4.1 过滤器基本知识4.2 简单过滤器4.3 复杂滤镜图 1.解复用 解复用就是把容器中的媒体流分离出来,方便我们对媒体流处理。 step1:对媒体文件上下文初始化 AVFormatCont…...
maven如何搭建自己的私服(LINUX版)?
环境准备 安装 JDK :确保系统已安装 JDK 8 或更高版本。可以通过以下命令安装 JDK: 安装 OpenJDK :sudo apt update && sudo apt install openjdk-11-jdk 安装 Oracle JDK :需要添加第三方仓库,例如 WebUpd8 …...
机器视觉的手机FPC油墨丝印应用
在现代智能手机制造过程中,精密的组件装配和质量控制是确保产品性能和用户体验的关键。其中,柔性印刷电路板(FPC)的油墨丝印工艺尤为关键,它不仅影响到电路板的美观,更直接关系到电路的导电性能和可靠性。而…...
AI原生手机:三大技术阵营的终极对决与未来展望
引言:AI手机时代的真正到来 2024年,智能手机行业迎来了一个历史性转折点——AI原生手机从概念走向主流。根据IDC最新报告,中国AI手机出货量同比激增591%,渗透率从2023年的3%飙升至22%。这一数据背后,是手机厂商在硬件…...
CFCA受邀参加盛京银行手机银行7.0发布会
4月30日,盛京银行举办手机银行7.0发布会。 盛京银行手机银行7.0围绕“慧享生活,财富随行”主题,聚焦便捷体验、财富管理、惠民生活,构建12大类服务,升级142项功能,全新设置信用卡频道,推出“云…...
IT/OT 融合架构下的工业控制系统安全攻防实战研究
1. 引言 随着工业 4.0 和智能制造的浪潮席卷全球,信息技术 (IT) 与运营技术 (OT) 的融合已成为不可逆转的趋势。这种融合旨在通过实时数据交换和分析,打破传统的信息孤岛,显著提升生产效率、优化决策、降低运营成本并增强市场竞争力。IT 系统…...
AI优化高频PCB信号完整性:猎板PCB的技术突破与应用实践
随着5G通信、AI服务器及新能源汽车的快速发展,高频PCB的信号完整性已成为决定电子产品性能的关键。本文以猎板PCB的技术实践为例,解析如何通过AI算法与精密制造工艺的结合,实现高频信号传输的极致优化,为行业提供高可靠性的解决方…...
【Bluedroid】蓝牙 SDP(服务发现协议)模块代码解析与流程梳理
本文深入剖析Bluedroid蓝牙协议栈中 SDP(服务发现协议)服务记录的全生命周期管理流程,涵盖初始化、记录创建、服务搜索、记录删除等核心环节。通过解析代码逻辑与数据结构,揭示各模块间的协作机制,包括线程安全设计、回…...
obj = null; 赋值null之前没有其他引用指向obj对象,那么,当obj=null时,会被垃圾回收机制立即回收吗?
不会立即回收。 具体原因是: 赋值 obj null; 后,对象变成“不可达”,符合垃圾回收条件,但垃圾回收器并不会立刻回收它。垃圾回收是CLR自动控制的非确定性过程,什么时候执行回收取决于系统内存压力、GC策略、分代情况…...
Android 数据持久化之 文件存储
在 Android 开发中,存储文件是一个常见的需求。 本文中介绍 openFileOutput 和 File 两种不同的方式来操作文件。 一、File 方式 根据文件的存储位置和访问权限,可以将文件存储分为内部存储(Internal Storage)和外部存储&#x…...
差分OPA verilogaA 模型
做电路设计,需要提前用理想模型如VerilogA模型做验证。这里分享一个由ahdlib库里单端opamp改造而来的差分opamp。参考何乐年的《模拟集成电路设计与仿真》10.4节423页; 描述的小信号模型如上。 VerilogA 用到了SRI/C,GBWgm/C,gaingm*r1等概念…...
oracle goldengate非并行进程转换为并行进程
oracle goldengate非并行进程转换为并行进程 在上一期的文章中写道了直接创建并行进程的方式对大事务进行分解,这对于新建立同步进程的时候提前规划是很有帮助的,但是如果对已经进行了同步的进程重新建立需要耗时比较长,Oracle提供了非并行进…...
58.[前端开发-前端工程化]Day05-webpack-Git安装-配置-Git命令
Git版本控制工具详解 1 邂逅版本控制工具 认识版本控制(版本控制) 版本控制的功能 版本控制的历史 2 集中式和分布式区别 集中式版本控制 分布式版本控制 3 Git的环境安装搭建 Git的安装 Bash – CMD – GUI 区别 Git的配置分类 Git的配置选项 Git的…...
CF每日5题
每日刷题两小时颐养天年 1855A 800 思维 将不高兴的同学计数cnt 不高兴的同学之间两两交换,一定不会在 p i i p_ii pii的位置上,贡献是cnt/2 如果cnt%2>0,那就多交换一次 void solve() {int n;cin>>n;int cnt0;forr(i,1,n){in…...
Redis实现分布式获取全局唯一自增ID的案例。
【1】简易自增版本(从 1 开始 1,2,3,...) 项目结构 下面是一个基于 RedisTemplate 实现的分布式全局唯一自增 ID 生成器的案例。适用于 Java Spring Boot 环境,利用 Redis 的原子操作 INCR 指令。 ✅ 原理说明 Redis 提供的 INCR 命令是原子性的&…...
创建型模式:工厂方法(Factory Method)模式
一、简介 工厂方法(Factory Method)模式是一种创建型设计模式,它定义了一个创建对象的接口,但让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。在 C# 中,工厂方法模式提供了一种更灵活的对象创建方式,将对象的创建和使用分离,提高了代码的可维护性和…...
大型语言模型在网络安全领域的应用综述
大型语言模型在网络安全领域的应用综述 简介1. 引言1.1 背景与意义1.2 LLMs 的基本概念1.3 LLMs 在网络安全中的优势1.4 报告目标 2. 文献综述方法2.1 研究问题2.2 文献检索策略2.3 文献筛选标准 3. LLMs 在网络安全领域的应用3.1 软件和系统安全 (Software and System Securit…...
TDEngine 与 Grafana
目录 实践目录 Grafana 参考文档 实践目录 10.60.100.194:/home/dualven/tdengine Grafana systemctl status grafana-server http://10.60.100.194:3000/ 这个端口与mydoor的new server服务冲突 (同时只开一个) 参考文档 运行监…...
iPhone手机连接WiFi异常解决方法
iPhone手机连接WiFi异常解决方法 一、问题现象二、iPhone连不上可能的原因三、基础排查与快速修复第一步:重启大法第二步:忽略网络,重新认证第三步:关闭“私有无线局域网地址”第四步:修改DNS服务器第五步:还原网络设置四、路由器端排查及设置关闭MAC地址过滤或添加到白名…...
微服务不注册到nacos的方法
引言:在开发中,有时候多个开发一起开发,可能会同时注册到dev环境中,这样可能会影响dev环境,那么在idea添加2个参数即可解决 spring.cloud.nacos.discovery.register-enabled falsespring.cloud.nacos.discovery.enabled false...
Spring Boot + Vue 实现在线视频教育平台
一、项目技术选型 前端技术: HTML CSS JavaScript Vue.js 前端框架 后端技术: Spring Boot 轻量级后端框架 MyBatis 持久层框架 数据库: MySQL 5.x / 8.0 开发环境: IDE:Eclipse / IntelliJ IDEA JDK&…...
【嵌入式开发-SPI】
嵌入式开发-SPI ■ SPI简介■ SPI (Standard SPI)■ DSPI (Dual SPI)■ QSPI是 Queued SPI的简写 ■ SPI简介 SPI协议其实是包括:Standard SPI、Dual SPI和Queued SPI三种协议接口,分别对应3-wire, 4-wire…...
【链表扫盲】FROM GPT
链表是一种线性数据结构,由节点(Node)组成,每个节点包含两个部分: 数据域(data): 存储节点值。指针域(next): 存储指向下一个节点的引用。 链表…...
如何在macOS上通过SSHFS挂载远程文件系统
在macOS系统中,想要便捷地访问远程计算机上的目录?借助SSH文件系统(SSHFS)就能轻松实现。SSHFS是一款文件系统客户端,它基于SSH文件传输协议(SFTP)建立安全连接,进而实现对远程文件的…...
Android studio profiler使用
主要讲内存泄露排查 1、把怀疑内存泄露的页面都跑一边,然后回到初始页面 2、打开profile的home,找到Analysis Memory Usage,点击右下角start profiler task,开始分析内存,等待分析完成,分析过程中页面是卡…...
排序算法-选择排序
选择排序是一种简单直观的排序算法,其核心思想是每次从未排序的部分中选出最小(或最大)的元素,放到已排序部分的末尾。 选择排序步骤 初始化:将序列分为已排序部分(初始为空)和未排序部分&…...