【Rabbitmq篇】高级特性----TTL,死信队列,延迟队列
目录
一.TTL
???1.设置消息的TTL
2.设置队列的TTL
3.俩者区别?
二.死信队列
定义:
消息成为死信的原因:
1.消息被拒绝(basic.reject 或 basic.nack)
2.消息过期(TTL)
3.队列达到最大长度?
?编辑?
死信队列的应用场景
三.延迟队列?
?定义:
应用场景?
实现一:TTL+死信队列?
?实现二:延迟队列插件
?编辑?俩种实现对比:
一.TTL
TTL(TimetoLive,过期时间),即过期时间.RabbitMQ可以对消息和队列设置TTL.
它代表消息的存活时间。当一条消息被发送到 RabbitMQ 队列后,TTL 可以限制消息在队列中能够存活的最长时间。一旦消息在队列中的存活时间超过了 TTL 设定的值,消息就会被自动删除。
咱们在网上购物,经常会遇到一个场景,当下单超过24小时还未付款,订单会被自动取消
申请退款之后,超过7天未被处理,则自动退款这就是设置了TTL
目前有俩种方式可以设置消息的TTL
一是设置队列的TTL,队列中所有消息都有相同的过期时间.
二是对消息本身进行单独设置,每条消息的TTL可以不同.如果两种方法一起使用,则消息的TTL以两者之间较小的那个数值为准.
先看针对每条消息设置TTL
1.设置消息的TTL
1)配置交换机&队列
//TTLpublic static final String TTL_QUEUE = "ttl.queue";public static final String TTL_EXCHANGE = "ttl.exchange";//TTL@Bean("ttlQueue")public Queue ttlQueue() {return QueueBuilder.durable(Constants.TTL_QUEUE).build();}@Bean("ttlExchange")public DirectExchange ttlExchange() {return ExchangeBuilder.directExchange(Constants.TTL_EXCHANGE).build();}@Bean("ttlBinding")public Binding ttlBinding(@Qualifier("ttlQueue") Queue queue,@Qualifier("ttlExchange") DirectExchange directExchange) {return BindingBuilder.bind(queue).to(directExchange).with("ttl");}
2)发送消息
MessagePostProcessor messagePostProcessor = new MessagePostProcessor() {@Overridepublic Message postProcessMessage(Message message) throws AmqpException {message.getMessageProperties().setExpiration("10000");//单位为毫秒,设置10秒后过期return message;}};
MessagePostProcessor中 重写postProcessMessage 方法
可以设置它的过期时间
这里使用了lambda表达式
@RequestMapping("/ttl")public String ttl() {System.out.println("ttl!!!");rabbitTemplate.convertAndSend(Constants.TTL_EXCHANGE,"ttl","ttl test...", message -> {message.getMessageProperties().setExpiration("10000");//单位为毫秒,设置10秒后过期return message;});return "消息发送成功";}
3)测试
十秒钟过后结果:
自动消失了这条消息
如果不设置TTL,则表示此消息不会过期;如果将TTL设置为0,则表示除非此时可以直接将消息投递到消费者,否则该消息会被立即丢弃.
2.设置队列的TTL
设置队列TTL的方法是在创建队列时,加 x-message-ttl 参数实现的,单位是毫秒
1)配置队列和绑定关系
public static final String TTL_QUEUE2= "ttl.queue2";@Bean("ttlQueue2")public Queue ttlQueue2() {return QueueBuilder.durable(Constants.TTL_QUEUE2).ttl(20000).build();}@Bean("ttlBinding2")public Binding ttlBinding2(@Qualifier("ttlQueue2") Queue queue,@Qualifier("ttlExchange") DirectExchange directExchange) {return BindingBuilder.bind(queue).to(directExchange).with("ttl");}
2)发送消息
@RequestMapping("/ttl2")public String ttl2() {System.out.println("ttl2!!!");rabbitTemplate.convertAndSend(Constants.TTL_EXCHANGE,"ttl","ttl2 test 20s...");return "消息发送成功";}
3)测试
20s后结果:
因为绑定的交换机是同一个,并且routingKey也是同一个,所有会向Q1和Q2同时发消息
我们发送的普通消息 并没有设置带有TTL的消息
所有Q1并不会消失 而Q2设置了队列的TTL,所以会消失。
4)测试2
如果发送消息的TTL(10s过期)给设置了TTL(20s过期)的队列,会发生什么结果?
结论:10s后俩个队列里面的消息全部消失,所有可得知取 它最短的时间过期
3.俩者区别
设置队列TTL属性的方法,一旦消息过期,就会从队列中删除
设置消息TTL的方法,即使消息过期,也不会马上从队列中删除,而是在即将投递到消费者之前进行判定的.
为什么这两种方法处理的方式不样?
因为设置队列过期时间,队列中已过期的消息肯定在队列头部,RabbitMQ只要定期从队头开始扫描是否有过期的消息即可.
而设置消息TTL的方式每条消息的过期时间不同,如果要删除所有过期消息需要扫描整个队列,所以不如等到此消息即将被消费时再判定是否过期,如果过期再进行删除即可.
测试!!!
@RequestMapping("/ttl")public String ttl() {System.out.println("ttl!!!");rabbitTemplate.convertAndSend(Constants.TTL_EXCHANGE,"ttl","ttl test... 3os", message -> {message.getMessageProperties().setExpiration("30000");//单位为毫秒,设置30秒后过期return message;});rabbitTemplate.convertAndSend(Constants.TTL_EXCHANGE,"ttl","ttl test... 10s", message -> {message.getMessageProperties().setExpiration("10000");//单位为毫秒,设置10秒后过期return message;});return "消息发送成功";}
先发一个设置30s过期的信息,再发一条设置10过期的信息 看看结果如何?
結果:
20s后首先是Q2(设置了20s的TTL队列)的队列全部消失
而Q1设置了10s的消息没有消失,而是等到30s过,再一起消失了
二.死信队列
定义:
当消息在一个普通队列中变成 “死信”(无法被正常消费的消息)时,这些消息会被重新路由到死信队列中。
有死信(DL),自然就有死信队列.当消息在个队列中变成死信之后,它能被重新被发送到另个交换器中,这个交换器就是DLX( Dead Letter Exchange ),绑定DLX的队列,就称为死信队列(DeadLetterQueue,简称DLQ).
声明队列和交换机与绑定关系
//正常队列public static final String NORMAL_QUEUE= "normal.queue";public static final String NORMAL_EXCHANGE = "normal.exchange";//死信队列public static final String DL_QUEUE= "dl.queue";public static final String DL_EXCHANGE = "dl.exchange";package com.bite.extensions.config;import com.bite.extensions.constant.Constants;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class DLConfig {@Bean("normalQueue")public Queue normalQueue() {return QueueBuilder.durable(Constants.NORMAL_QUEUE).deadLetterExchange(Constants.DL_EXCHANGE).deadLetterRoutingKey("dlx").build();}@Bean("normalExchange")public DirectExchange normalExchange() {return ExchangeBuilder.directExchange(Constants.NORMAL_EXCHANGE).durable(true).build();}@Bean("normalBinding")public Binding normalBinding(@Qualifier("normalQueue") Queue queue,@Qualifier("normalExchange") DirectExchange directExchange) {return BindingBuilder.bind(queue).to(directExchange).with("normal");}@Bean("dlQueue")public Queue dlQueue() {return QueueBuilder.durable(Constants.DL_QUEUE).build();}@Bean("dlExchange")public DirectExchange dlExchange() {return ExchangeBuilder.directExchange(Constants.DL_EXCHANGE).durable(true).build();}@Bean("dlBinding")public Binding dlBinding(@Qualifier("dlQueue") Queue queue,@Qualifier("dlExchange") DirectExchange directExchange) {return BindingBuilder.bind(queue).to(directExchange).with("dlx");}
}
消息成为死信的原因:
1.消息被拒绝(basic.reject 或 basic.nack)
消息被拒绝(basic.reject 或 basic.nack)****:消费者在接收到消息后可以明确地拒绝该消息,并且可以选择是否将消息重新放回队列。如果消费者拒绝消息且不重新放回队列,同时该队列配置了死信交换机(Dead - Letter - Exchange,DLX),那么消息就会被发送到死信队列。
消费者:
package com.bite.extensions.listener;import com.bite.extensions.constant.Constants;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;@Component
public class DLListener {@RabbitListener(queues = Constants.NORMAL_QUEUE)public void handleMessage(Message message, Channel channel) throws Exception {//消费者逻辑long deliverTag = message.getMessageProperties().getDeliveryTag();try {System.out.printf("[normal.queue]接收到信息: %s, deliveryTag: %d
",new String(message.getBody(),"UTF-8"),deliverTag);//业务逻辑处理System.out.println("业务逻辑处理!");int num = 3/0;System.out.println("业务逻辑完成!");//肯定确认channel.basicAck(deliverTag,false);} catch (Exception e) {//否定确认channel.basicNack(deliverTag,false,false);//requeue为false,则变成死信队列}}@RabbitListener(queues = Constants.DL_QUEUE)public void dlxHandleMessage(Message message, Channel channel) throws Exception {System.out.printf("[dl.queue]接收到信息: %s, deliveryTag: %d
", new String(message.getBody(), "UTF-8"), message.getMessageProperties().getDeliveryTag(););}
}
测试:
2.消息过期(TTL)
消息过期(TTL):如果消息在队列中的存活时间(通过设置 TTL)超过了限定时间,消息会变成死信。前提是队列配置了死信交换机,过期消息会被发送到死信队列。
设置10s过期队列:
@Bean("normalQueue")public Queue normalQueue() {return QueueBuilder.durable(Constants.NORMAL_QUEUE).deadLetterExchange(Constants.DL_EXCHANGE).deadLetterRoutingKey("dlx").ttl(10*1000).build();}
生产者:
@RequestMapping("/dl")public String dl() {System.out.println("dl test !!!");rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE,"normal","dl test 10s...");return "消息发送成功";}
测试:
10s后:
3.队列达到最大长度
队列达到最大长度**:当队列设置了最大长度限制,并且消息数量达到这个限制时,新进入队列的消息会导致最早的消息被挤出队列。如果被挤出的消息对应的队列配置了死信交换机,这些消息会成为死信并被发送到死信队列。**
设置队列最大容量为10:
@Bean("normalQueue")public Queue normalQueue() {return QueueBuilder.durable(Constants.NORMAL_QUEUE).deadLetterExchange(Constants.DL_EXCHANGE).deadLetterRoutingKey("dlx").maxLength(10l).build();}
生产者:
@RequestMapping("/dl")public String dl() {System.out.println("dl test !!!");for (int i = 0; i < 15; i++) {rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE,"normal","dl test ..."+i);}return "消息发送成功";}
测试:
死信队列的应用场景
- 消息重试与错误处理
- 场景描述:
- 在分布式系统中,消息的处理可能会因为各种原因(如网络波动、依赖服务故障、业务逻辑异常等)而失败。当消费者无法正确处理消息时,可以将消息拒绝,使其进入死信队列。
- 具体示例:
- 假设一个电商系统中,订单处理服务从消息队列中接收订单消息进行处理。如果在处理订单时,由于库存服务不可用而导致无法完成库存扣减操作,订单处理服务可以拒绝该订单消息。这条消息就会进入死信队列,然后在死信队列的消费者中,可以实现重试机制。例如,每隔一段时间(如 5 分钟)尝试重新处理这些死信消息,直到库存服务恢复或者达到最大重试次数。
- 消息过期后的补偿处理
- 场景描述:
- 对于一些有时间限制的消息,当消息过期后(可能是由于业务时效性或者设置了 TTL),将其发送到死信队列进行特殊的补偿处理。
- 具体示例:
- 在一个限时促销活动系统中,促销活动消息被发送到消息队列。这些消息设置了 TTL,代表活动的有效期。当消息过期后,表示活动已经结束。这些过期消息进入死信队列,在死信队列的消费者中,可以对过期的促销活动进行数据清理,如删除相关的临时缓存数据、更新数据库中的活动状态为 “已结束” 等操作。
- 流量削峰与缓冲
- 场景描述:
- 当消息生产者的生产速度远大于消费者的消费速度时,普通队列可能会因为消息堆积而出现问题。通过设置队列长度限制,让超过限制的消息成为死信进入死信队列,可以起到缓冲和流量削峰的作用。
- 具体示例:
- 在一个热门电商平台的促销活动期间,订单消息大量涌入消息队列。为了避免普通队列因为消息过多而崩溃,可以设置普通队列的最大长度。当订单消息数量超过这个长度时,新的消息成为死信进入死信队列。在死信队列中,可以根据业务情况,例如在流量低谷时期,再将这些死信消息重新放回普通队列进行处理,或者进行一些其他的优化策略,如合并订单消息等。…
三.延迟队列
定义:
延迟队列是一种特殊的队列,其中的消息会在经过一段延迟时间后才会被消费者消费。
即消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费
应用场景
延迟队列的使场景有很多,比如:
1. 智能家居:用户希望通过手机远程遥控家的智能设备在指定的时间进行工作.这时候就可以将用户指令发送到延迟队列,当指令设定的时间到了再将指令推送到智能设备.
2. 日常管理:预定会议后,需要在会议开始前十五分钟提醒参会人参加会议
3. 用户注册成功后,7天后发送短信,提高用户活跃度等
4. …
实现一:TTL+死信队列
队列:
@Bean("normalQueue")public Queue normalQueue() {return QueueBuilder.durable(Constants.NORMAL_QUEUE).deadLetterExchange(Constants.DL_EXCHANGE).deadLetterRoutingKey("dlx").ttl(10*1000).maxLength(10l).build();}
生产者:
@RequestMapping("/dl")public String dl() {System.out.println("dl test !!!");rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE,"normal","dl test ...");System.out.printf("%tc 消息发送成功
",new Date());return "消息发送成功";}
消费者:
@RabbitListener(queues = Constants.DL_QUEUE)public void dlxHandleMessage(Message message, Channel channel) throws Exception {System.out.printf("[dl.queue] %tc 接收到信息: %s, deliveryTag: %d
",new Date(), new String(message.getBody(), "UTF-8"), message.getMessageProperties().getDeliveryTag());}
测试1:
当前设置队列的TTL不会发生问题,可设置消息的TTL将会存在问题
测试2:设置消息的TTL
@Bean("normalQueue")public Queue normalQueue() {return QueueBuilder.durable(Constants.NORMAL_QUEUE).deadLetterExchange(Constants.DL_EXCHANGE).deadLetterRoutingKey("dlx")//.ttl(10*1000).maxLength(10l).build();}
生产者:
@RequestMapping("/delay")public String delay() {System.out.println("delay!!!");rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE,"normal","delay test... 30s", message -> {message.getMessageProperties().setExpiration("30000");//单位为毫秒,设置30秒后过期return message;});rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE,"normal","delay test... 10s", message -> {message.getMessageProperties().setExpiration("10000");//单位为毫秒,设置10秒后过期return message;});System.out.printf("%tc 消息发送成功
",new Date());return "消息发送成功";}
结果:
因为是先发30s 再发10s的消息时
结果俩条信息都过了30s才接收到,并不符合我们的预期
反正先发时间少的消息 再发长的才行,
不过这种模式终究还是存在缺陷
所以在考虑使用TTL+死信队列实现延迟任务队列的时候,需要确认业务上每个任务的延迟时间是一致的,如果遇到不同的任务类型需要不同的延迟的话,需要为每种不同延迟时间的消息建立单独的消息队列.
实现二:延迟队列插件
下载插件
插件地址Releases · rabbitmq/rabbitmq-delayed-message-exchange
选择合适的版本自行安装
再linux中找到**/usr/lib/rabbitmq/plugins目录 安装在此**
/usr/lib/rabbitmq/plugins 是个附加目录,RabbitMQ包本身不会在此安装任何内容,如果
没有这个路径,可以自己进行创建
我这边是没有的 所有我得创建一个plugins目录
再将下载好的文件拖到linux中
#启动插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
#重启服务service rabbitmq-server restart
查看结果即可
出现这种情况即可安装成功 一定要安装对应版本 小编刚刚就安装错了,捣鼓了很久
声明交换机,队列,绑定关系
//延迟队列public static final String DELAY_QUEUE= "delay.queue";public static final String DELAY_EXCHANGE = "delay.exchange";package com.bite.extensions.config;import com.bite.extensions.constant.Constants;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class DelayConfig {@Bean("delayQueue")public Queue delayQueue() {return QueueBuilder.durable(Constants.DELAY_QUEUE).build();}@Bean("delayExchange")public DirectExchange delayExchange() {return ExchangeBuilder.directExchange(Constants.DELAY_EXCHANGE).delayed().build();}@Bean("delayBinding")public Binding delayBinding(@Qualifier("delayQueue") Queue queue, @Qualifier("delayExchange") DirectExchange directExchange) {return BindingBuilder.bind(queue).to(directExchange).with("delay");}
}
生产者:
@RequestMapping("/delay2")public String delay2() {System.out.println("delay!!!");rabbitTemplate.convertAndSend(Constants.DELAY_EXCHANGE,"delay","delay test... 30s", message -> {message.getMessageProperties().setDelayLong(30000l);//单位为毫秒,设置30秒后过期return message;});rabbitTemplate.convertAndSend(Constants.DELAY_EXCHANGE,"delay","delay test... 10s", message -> {message.getMessageProperties().setDelayLong(10000l);//单位为毫秒,设置10秒后过期return message;});System.out.printf("%tc 消息发送成功
",new Date());return "消息发送成功";}
消费者:
package com.bite.extensions.listener;import com.bite.extensions.constant.Constants;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.util.Date;@Component
public class DelayListener {@RabbitListener(queues = Constants.DELAY_QUEUE)public void dlxHandleMessage(Message message, Channel channel) throws Exception {System.out.printf("[delay.queue] %tc 接收到信息: %s, deliveryTag: %d
",new Date(), new String(message.getBody(), "UTF-8"), message.getMessageProperties().getDeliveryTag());}
}
测试:
10s后:
20s后:
俩种实现对比:
二者对比:
1. 基于死信实现的延迟队列
a. 优点:1)灵活不需要额外的插件支持
b. 缺点:1)存在消息顺序问题2)需要额外的逻辑来处理死信队列的消息,增加了系统的复杂性
2. 基于插件实现的延迟队列
a. 优点:1)通过插件可以直接创建延迟队列,简化延迟消息的实现.2)避免了DLX的时序问题
b. 缺点:1)需要依赖特定的插件,有运维工作2)只适用特定版本
**结语:**写博客不仅仅是为了分享学习经历,同时这也有利于我巩固知识点,总结该知识点,由于作者水平有限,对文章有任何问题的还请指出,接受大家的批评,让我改进。同时也希望读者们不吝啬你们的点赞+收藏+关注,你们的鼓励是我创作的最大动力!
相关文章:

【Rabbitmq篇】高级特性----TTL,死信队列,延迟队列
目录 一.TTL ???1.设置消息的TTL 2.设置队列的TTL 3.俩者区别? 二.死信队列 定义: 消息成为死信的原因: 1.消息被拒绝(basic.reject 或 basic.nack) 2.消息过期(TTL) 3.队列达到最大长度? …...
机器学习赋能的智能光子学器件系统研究与应用
机器学习赋能的智能光子学器件系统研究与应用 时间: 2025年03月29日-03月30日 2025年04月05日-04月06日 机器学习赋能的光子学器件与系统:从创新设计到前沿应用 课程针对光子学方面的从业科研人员及开发者,希望了解和实践在集成光学/空间…...

尚硅谷课程【笔记】——大数据之Linux【三】
课程视频链接:尚硅谷大数据Linux课程 七、定时任务调度 任务调度:指系统在某个时间执行的特定的命令或程序。 1)系统工作:有些重要的工作必须周而复始地执行。 2)个别用户工作:用户可能希望在某些特定的时…...

Visual Studio踩过的坑
统计Unity项目代码行数 编辑-查找和替换-在文件中查找 查找内容输入 b*[^:b#/].*$ 勾选“使用正则表达式” 文件类型留空 也有网友做了指定,供参考 !*\bin\*;!*\obj\*;!*\.*\*!*.meta;!*.prefab;!*.unity 打开Unity的项目 注意:只是看࿰…...
教程 | MySQL 基本指令指南(附MySQL软件包)
此前已经发布了安装教程安装教程,现在让我们来学习一下MySQL的基本指令。 一、数据库连接与退出 连接本地数据库 mysql -uroot -p # 输入后回车,按提示输入密码(密码输入不可见)若需隐藏密码显示,可使用࿱…...

企业数据集成案例:吉客云销售渠道到MySQL
测试-查询销售渠道信息-dange:吉客云数据集成到MySQL的技术案例分享 在企业的数据管理过程中,如何高效、可靠地实现不同系统之间的数据对接是一个关键问题。本次我们将分享一个具体的技术案例——通过轻易云数据集成平台,将吉客云中的销售渠…...

网络编程 day3
思维导图 以select函数模型为例 思维导图2 对应 epoll模型 应使用的函数 题目 使用epoll函数实现 两个客户端 通过服务器 实现聊天 思路 在原先代码基础上 实现 服务器 发向 客户端 使用客户端在服务器上的 套接字描述符 实现 客户端 接收 服务器…...

Excel 融合 deepseek
效果展示 代码实现 Function QhBaiDuYunAIReq(question, _Optional Authorization "Bearer ", _Optional Qhurl "https://qianfan.baidubce.com/v2/chat/completions")Dim XMLHTTP As ObjectDim url As Stringurl Qhurl 这里替换为你实际的URLDim postD…...

【论文笔记】Are Self-Attentions Effective for Time Series Forecasting? (NeurIPS 2024)
官方代码https://github.com/dongbeank/CATS Abstract 时间序列预测在多领域极为关键,Transformer 虽推进了该领域发展,但有效性尚存争议,有研究表明简单线性模型有时表现更优。本文聚焦于自注意力机制在时间序列预测中的作用,提…...

游戏手柄Type-c方案,支持一边充电一边传输数据
乐得瑞推出LDR6023SS,专门针对USB-C接口手机手柄方案,支持手机快充,支持任天堂游戏机,PS4等设备~同时支持手机充电跟数据传输 1、概述 LDR6023SS SSOP16 是乐得瑞科技针对 USB Type-C 标准中的 Bridge 设备而开发的双 USB-C DRP …...
2. 4 模块化JDK:JDK模块结构与核心模块
第3章:模块化JDK:JDK模块结构与核心模块 JDK 9 将自身拆分为一系列模块,彻底告别传统的“单一JAR(如 rt.jar)”模式。本章深入解析 JDK 的模块化架构、核心模块功能及开发者如何高效利用这些模块。 3.1 JDK 模块化设计…...
每日一题——缺失的第一个正整数
缺失的第一个正整数 题目描述进阶:数据范围: 示例示例 1示例 2示例 3 题解思路代码实现代码解释复杂度分析总结 题目描述 给定一个无重复元素的整数数组 nums,请你找出其中没有出现的最小的正整数。 进阶: 时间复杂度ÿ…...

CEF132 编译指南 MacOS 篇 - 基础开发工具安装实战 (二)
1. 引言 在 macOS 平台上编译 CEF132 之前,首要任务是搭建一个完善的开发环境。与 Windows 和 Linux 环境不同,macOS 的开发环境主要以 Xcode 为核心。本篇将作为 CEF132 编译指南系列的第二篇,详细指导读者如何在 macOS 系统上安装和配置 X…...
vi 是 Unix 和 Linux 系统中常用的文本编辑器
vi是 Unix 和 Linux 系统中常用的文本编辑器,它有几种不同的模式,其中最常用的是命令模式和插入模式。光标控制主要在命令模式下进行,以下是一些常用的vi命令来控制光标位置: • h,j,k,l:分别用于将光标向左、向下、向…...

SwanLab x verl:可视化LLM强化学习后训练教程
文章目录 介绍Verl和SwanLab1. 环境安装2. 使用方法3. 查看训练日志 介绍Verl和SwanLab verl 是一个灵活、高效且可用于生产环境的强化学习(RL)训练框架,专为大型语言模型(LLMs)的后训练设计。它由字节跳动火山引擎团…...

职场到校园,初心未改:我的2024年
Hi,大家好,我是几何心凉。 其实早就想写一份复盘文章,正好借助2024年度博客之星的评选机会,来写下这篇总结。回望过去,感慨颇多。自从加入CSDN平台以来,已经见证了许多博主的来去匆匆,各类创作…...
C++基础知识学习记录—引用
1、引用的概念 概念:引用相当于给变量取个别名 对引用进行操作与直接操作变量相同,注意引用类型与变量类型一致 #include<iostream> using namespace std; int main(){int a10;int& cite_a a;//操作引用cite_a 与操作变量a完全一样cout &l…...
AWS Savings Plans 监控与分析工具使用指南
一、背景介绍 1.1 什么是 Savings Plans? AWS Savings Plans 是一种灵活的定价模式,通过承诺持续使用一定金额的 AWS 服务来获得折扣价格。它可以帮助用户降低 AWS 使用成本,适用于 EC2、Fargate 和 Lambda 等服务。 1.2 为什么需要监控? 优化成本支出跟踪使用情况评估投…...

【AI学习】关于 DeepSeek-R1的几个流程图
遇见关于DeepSeek-R1的几个流程图,清晰易懂形象直观,记录于此。 流程图一 来自文章《Understanding Reasoning LLMs》, 文章链接:https://magazine.sebastianraschka.com/p/understanding-reasoning-llms?continueFlagaf07b1a0…...

C++ ——从C到C++
1、C的学习方法 (1)C知识点概念内容比较多,需要反复复习 (2)偏理论,有的内容不理解,可以先背下来,后续可能会理解更深 (3)学好编程要多练习,简…...

高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...

视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
云原生周刊:k0s 成为 CNCF 沙箱项目
开源项目推荐 HAMi HAMi(原名 k8s‑vGPU‑scheduler)是一款 CNCF Sandbox 级别的开源 K8s 中间件,通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度,为容器提供统一接口,实现细粒度资源配额…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...

rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...

Linux基础开发工具——vim工具
文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...