【RabbitMQ】消息确认机制 持久化 发布确认机制

文章目录

  • Ⅰ. 消息确认
    • 一、消息确认机制
    • 二、手动确认方法
      • ① 肯定确认
      • ② 否定确认
      • ③ 否定确认
    • 三、代码示例
  • Ⅱ. 持久性
    • 一、交换机持久化
    • 二、队列持久化
    • 三、消息持久化
  • Ⅲ. 发布确认机制
    • 一、confirm确认模式
    • 二、return退回模式
    • 三、常见面试题💥 -- 如何保证 RabbitMQ 消息的可靠传输?

Ⅰ. 消息确认

一、消息确认机制

生产者发送消息之后,到达消费端之后,可能会有以下情况:

  1. 消息处理成功
  2. 消息处理异常

RabbitMQ 向消费者发送消息之后,就会把这条消息删掉,那么第两种情况,就会造成消息丢失。那么如何确保消费端已经成功接收了,并正确处理了呢?

为了保证消息从队列可靠地到达消费者,RabbitMQ 提供了消息确认机制!

消费者在订阅队列时,可以指定autoAck参数,根据这个参数设置,消息确认机制分为以下两种:

  • 自动确认autoAck等于true时,RabbitMQ 会自动把发送出去的消息置为确认,然后从内存(或者磁盘)中删除,而不管消费者是否真正地消费到了这些消息。适合对于消息可靠性要求不高的场景。
  • 手动确认autoAck等于false时,RabbitMQ 会等待消费者显式地调用Basic.Ack命令,回复确认信号后才从内存(或者磁盘)中移去消息。适合对消息可靠性要求比较高的场景。
StringbasicConsume(Stringqueue,booleanautoAck,Consumercallback)throwsIOException;

代码示例:

DefaultConsumerconsumer=newDefaultConsumer(channel){@OverridepublicvoidhandleDelivery(StringconsumerTag,Envelopeenvelope,AMQP.BasicPropertiesproperties,byte[]body)throwsIOException{System.out.println("接收到消息: "+newString(body));}};channel.basicConsume(Constants.TOPIC_QUEUE_NAME1,true,consumer);

autoAck参数置为false,队列中的消息分成了两个部分:

  1. Ready:等待投递给消费者的消息数
  2. Unacked:已经投递给消费者,但是未收到消费者确认信号的消息数

如果 RabbitMQ 一直没有收到消费者的确认信号,并且消费此消息的消费者已经断开连接,则 RabbitMQ 会安排该消息重新进入队列,等待投递给下一个消费者,当然也有可能还是原来的那个消费者。

从管理平台上可以看到当前队列中Ready状态和Unacked状态的消息数:

二、手动确认方法

消费者在收到消息之后,可以选择确认,也可以选择直接拒绝或者跳过,RabbitMQ 也提供了不同的确认应答的方式,消费者客户端可以调用与其对应的 channel 的相关方法,共有以下三种:

① 肯定确认

RabbitMQ 已知道该消息并且成功的处理消息,可以将其丢弃了。

Channel.basicAck(longdeliveryTag,booleanmultiple);
  1. deliveryTag:消息的唯一标识,它是一个单调递增的 64 位的长整型值。deliveryTag是每个通道(Channel)独立维护的,所以在每个通道上都是唯一的。当消费者确认(ack)一条消息时,必须使用对应的通道上进行确认。
  2. multiple:是否批量确认。在某些情况下,为了减少网络流量,可以对一系列连续的deliveryTag进行批量确认。
    1. true:表示一次性 ack 所有小于等于指定deliveryTag的消息
    2. false:表示确认当前指定deliveryTag的消息

deliveryTag是 RabbitMQ 中消息确认机制的一个重要组成部分,它确保了消息传递的可靠性和顺序性。

② 否定确认

RabbitMQ 在 2.0.0 版本开始引入了Basic.Reject这个命令,消费者客户端可以调用channel.basicReject方法来告诉 RabbitMQ 拒绝这个消息。

Channel.basicReject(long deliveryTag, boolean requeue);
  1. deliveryTag:参考channel.basicAck
  2. requeue:表示拒绝后,这条消息如何处理。
    1. true:会重新将这条消息存入队列,以便可以发送给下一个订阅的消费者。
    2. false:会把消息从队列中移除,而不会把它发送给新的消费者。

③ 否定确认

Basic.Reject命令一次只能拒绝一条消息,如果想要批量拒绝消息,则可以使用Basic.Nack这个命令,消费者客户端可以调用channel.basicNack方法来实现。

Channel.basicNack(longdeliveryTag,booleanmultiple,booleanrequeue);

三、代码示例

我们基于 SpringBoot 来演示消息的确认机制,使用方式和使用 RabbitMQ Java Client 库有一定差异。(主要体现在后者使用的是channel.basicConsume来接收消息以及做出回调处理,而前者用的是注解@RabbitListener来做回调处理)

Spring-AMQP 对消息确认机制提供了三种策略:

publicenumAcknowledgeMode{NONE,MANUAL,AUTO;}
  1. NONE
    1. RabbitMQ在投递消息后立即标记消息为已确认
    2. 不管消费者是否成功处理消息,Broker 都会立即从队列中移除消息。
    3. 如果消费者处理过程中宕机或抛出异常,消息无法再被重新投递 →可能丢失
    4. ✅ 性能高,❌ 可靠性低
  2. AUTO(默认)
    1. Spring 会在消息成功消费且未抛出异常时自动发送basicAck()
    2. 如果消息处理过程中抛出异常,则不会确认,Spring 会根据重试机制死信策略重新投递。
    3. ✅ 性能和可靠性平衡。
    4. ⚙️ 依赖 Spring 的异常处理机制判断是否 ack。
  3. MANUAL
    1. 开发者必须显式调用channel.basicAck()basicNack()
    2. 若未确认,RabbitMQ 会认为消息 “尚未成功消费”,并在消费者可用时重新投递。
    3. ✅ 最高可靠性,可实现精确控制(例如延迟 ack、批量 ack、失败重入队列)
    4. ❌ 代码复杂度稍高

下面以 AcknowledgeMode.NONE 为例,其它两种就是就是改一下配置文件中的acknowledge-mode即可!

  1. 配置确认机制:

    spring:rabbitmq:addresses:amqp://liren:123123@127.0.0.1/lirendadalistener:simple:acknowledge-mode:none# 设置确认机制为立刻确认
  2. 编写常量类:

    publicclassConstant{publicstaticfinalStringACK_EXCHANGE_NAME="ack_exchange";publicstaticfinalStringACK_QUEUE="ack_queue";}
  3. 配置与绑定队列和交换机:

    @ConfigurationpublicclassRabbitMQConfig{@Bean("ackQueue")publicQueueackQueue(){returnQueueBuilder.durable(Constants.ACK_QUEUE).build();}@Bean("ackExchange")publicDirectExchangeackExchange(){returnExchangeBuilder.directExchange(Constants.ACK_EXCHANGE_NAME).durable(true).build();}@Bean("ackBinding")publicBindingackBinding(@Qualifier("ackQueue")Queuequeue,@Qualifier("ackExchange")DirectExchangeexchange){returnBindingBuilder.bind(queue).to(exchange).with("ack");}}
  4. 发送消息:

    @RequestMapping("/producer")@RestControllerpublicclassproducerController{@AutowiredprivateRabbitTemplaterabbitTemplate;@RequestMapping("/ack")publicStringack(){rabbitTemplate.convertAndSend(Constants.ACK_EXCHANGE_NAME,"ack","consumer ack test...");return"发送成功!";}}
  5. 消费消息:

    @ComponentpublicclassAckListener{@RabbitListener(queues=Constants.ACK_QUEUE)publicvoidListenerQueue(Messagemessage,Channelchannel)throwsUnsupportedEncodingException{System.out.printf("接收到消息: %s, deliveryTag: %d%n",newString(message.getBody(),"UTF-8"),message.getMessageProperties().getDeliveryTag());// 模拟处理失败,会抛异常inta=3/0;System.out.println("处理完成");}}

Ⅱ. 持久性

消费者处理消息时,消息如何不丢失呢?如何保证当 RabbitMQ 服务停掉以后,生产者发送的消息不丢失呢?

默认情况下,RabbitMQ 退出或者由于某种原因崩溃时,会忽视队列和消息,除非告知它不要这么做

RabbitMQ 的持久化分为三个部分:

  • 交换器持久化
  • 队列持久化
  • 消息持久化

一、交换机持久化

交换器的持久化是在声明交换机时设置durable参数为true,相当于将交换机的属性在服务器内部保存。

设置持久化之后,当 RabbitMQ 的服务器发生意外或关闭之后,进行重启时不需要重新去建立交换机,交换机会自动建立,相当于一直存在。

如果交换器不设置持久化,那么在 RabbitMQ 服务重启之后,相关的交换机元数据会丢失,对一个长期使用的交换器来说,建议将其置为持久化的。

ExchangeBuilder.topicExchange(Constant.ACK_EXCHANGE_NAME).durable(true).build()

二、队列持久化

队列的持久化是在声明队列时设置durable参数为true

如果队列不设置持久化,那么在 RabbitMQ 服务重启之后,该队列就会被删掉,此时数据也会丢失。(因为队列不存在了,那么消息也无处可存了)

但是设置了队列的持久化,也只能保证该队列本身的元数据不会因异常情况而丢失,并不能保证内部所存储的消息不会丢失要确保消息不会丢失,需要设置消息持久化

💥注意事项:创建队列的时候默认durabletrue,即 RabbitMQ默认开启队列持久化

三、消息持久化

消息实现持久化,需要在发送消息的时候,将消息的投递模式(MessageProperties中的deliveryMode)设置为 2,也就是MessageDeliveryMode.PERSISTENT

publicenumMessageDeliveryMode{NON_PERSISTENT,// 非持久化PERSISTENT;// 持久化}

设置了队列以及消息的持久化,当 RabbitMQ 服务重启之后,消息依旧存在。

如果只设置队列持久化,重启之后消息会丢失;如果只设置消息持久化,重启之后队列消失,继而消息也丢失。所以单单设置消息持久化而不设置队列持久化显得毫无意义

// 非持久化信息channel.basicPublish("",QUEUE_NAME,null,msg.getBytes());// 持久化信息channel.basicPublish("",QUEUE_NAME,MessageProperties.PERSISTENT_TEXT_PLAIN,msg.getBytes());

其中MessageProperties.PERSISTENT_TEXT_PLAIN实际就是封装了这个属性,其源码如下所示:

publicstaticfinalBasicPropertiesPERSISTENT_TEXT_PLAIN=newBasicProperties("text/plain",null,null,2,// deliveryMode0,null,null,null,null,null,null,null,null,null);

如果是在 springboot 中使用RabbitTemplate发送持久化消息,操作如下所示:

// 要发送的消息内容Stringmessage="This is a persistent message";// 创建一个Message对象,设置为持久化MessagemessageObject=newMessage(message.getBytes(),newMessageProperties());messageObject.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);// 使用RabbitTemplate发送消息rabbitTemplate.convertAndSend(Constant.ACK_EXCHANGE_NAME,"ack",messageObject);

💥注意事项:RabbitMQ 默认情况下会将消息视为持久化的,除非队列被声明为非持久化,或者消息在发送时被标记为非持久化。

将所有的消息都设置为持久化,会严重影响 RabbitMQ 的性能(随机)。写入磁盘的速度比写入内存的速度慢得不止一点点。对于可靠性不是那么高的消息可以不采用持久化处理以提高整体的吞吐量。在选择是否要将消息持久化时,需要在可靠性和吐吞量之间做一个权衡。

将交换器、队列、消息都设置了持久化之后就能百分之百保证数据不丢失了吗❓❓❓答案是否定的。

  1. 从消费者来说,如果在订阅消费队列时将autoAck参数设置为true,那么当消费者接收到相关消息之后,还没来得及处理就宕机了,这样也算数据丢失。这种情况很好解决,将autoAck参数设置为false,进行手动确认。
  2. 在持久化消息被 RabbitMQ 接收后,并不会立即写入磁盘。RabbitMQ 并不会为每条消息都执行同步落盘(即调用操作系统的fsync方法),而是先通过write()写入操作系统的页缓存中,等待系统或批量策略触发再真正写入磁盘。因此,如果在这段缓存尚未同步到磁盘的时间窗口内 RabbitMQ 节点发生宕机或重启,尚未落盘的消息仍可能丢失。

这个问题怎么解决呢❓❓❓

  1. 引入 RabbitMQ 的仲裁队列,如果主节点(master)在此特殊时间内挂掉,可以自动切换到从节点(slave),这样有效地保证了高可用性,除非整个集群都挂掉。(此方法同样不能保证 100% 可靠,但是配置了仲裁队列要比没有配置仲裁队列的可靠性要高很多,实际生产环境中的关键业务队列一般都会设置仲裁队列)
  2. 还可以在发送端引入事务机制或者发布确认机制来保证消息已经正确地发送并存储至 RabbitMQ 中。

Ⅲ. 发布确认机制

在使用 RabbitMQ 的时候,可以通过消息持久化来解决因为服务器的异常崩溃而导致的消息丢失,但是还有一个问题,当消息的生产者将消息发送出去之后,消息到底有没有正确地到达服务器呢?如果在消息到达服务器之前已经丢失(比如 RabbitMQ 重启,那么 RabbitMQ 重启期间生产者消息投递失败),持久化操作也解决不了这个问题,因为消息根本没有到达服务器,何谈持久化?

RabbitMQ 为我们提供了两种解决方案:

  1. 通过事务机制实现(比较消耗性能,在实际工作中使用也不多)
  2. 通过发布确认机制实现(这里主要介绍这种方案)

RabbitMQ 为我们提供了两个方式来控制消息的可靠性投递

  1. confirm确认模式
  2. return退回模式

一、confirm确认模式

生产者在发送消息的时候,对发送端设置一个ConfirmCallback的监听,无论消息是否到达交换机,这个监听都会被执行。如果 Exchange 成功收到,ACK 为 true;如果没收到消息,ACK 就为 false。

RabbitTemplate.ConfirmCallbackConfirmListener区别💥💥💥

在 RabbitMQ 中,ConfirmListenerConfirmCallback都是用来处理消息确认的机制,但它们属于不同的客户端库,并且使用的场景和方式有所不同。

  1. ConfirmListener是 RabbitMQ Java Client 库中的接口。这个库是 RabbitMQ 官方提供的一个直接与 RabbitMQ 服务器交互的客户端库。ConfirmListener接口提供了两个方法:handleAckhandleNack,用于处理消息确认和否定确认的事件。
  2. ConfirmCallback是 Spring AMQP 框架中的一个接口,专门为 Spring 环境设计,用于简化与 RabbitMQ 交互的过程。它只包含一个confirm方法,用于处理消息确认的回调。

在 SpringBoot 应用中,通常会使用ConfirmCallback,因为它与 Spring 框架的其他部分更加整合,可以利用 Spring 的配置和依赖注入功能。而在使用 RabbitMQ Java Client 库时,则可能会直接实现ConfirmListener接口,更直接的与 RabbitMQ 的 Channel 交互。

publicinterfaceConfirmCallback{/** * 确认回调 * @param correlationData: 发送消息时的附加信息, 通常用于在确认回调中识别特定的消息 * @param ack: 交换机是否收到消息, 收到为true, 未收到为false * @param cause: 当消息确认失败时,这个字符串参数将提供失败的原因.这个原因可以用于调试和错误处理 * 成功时, cause为null */voidconfirm(@NullableCorrelationDatacorrelationData,booleanack,@NullableStringcause);}
  1. 配置RabbitMQ

    spring:rabbitmq:addresses:amqp://liren:123123@127.0.0.1/lirendadalistener:simple:acknowledge-mode:manual# 消息确认publisher-confirm-type:correlated# 发布确认机制

其中发布确认机制这里有三种可选方式:(对应前面学习发布确认机制时候的 无确认、单独确认/批量确认、异步确认)

模式是否启用确认方式阻塞性性能典型场景
NONE无确认非阻塞⭐⭐⭐⭐普通日志、监控消息
SIMPLE同步等待阻塞关键事务型消息
CORRELATED异步回调非阻塞⭐⭐⭐高并发可靠投递
  1. 常量类

    // 发布确认机制publicstaticfinalStringCONFIRM_EXCHANGE_NAME="confirm_exchange";publicstaticfinalStringCONFIRM_QUEUE="confirm_queue";
  2. 设置确认回调逻辑并发送消息

    1. 无论消息确认成功还是失败,都会调用ConfirmCallbackconfirm方法

      • 如果消息发送成功,ack=true
      • 如果消息发送失败,ack=false,并且由参数 cause 提供失败的原因
    publicclassRabbitTemplateConfig{@Bean("ackRabbitTemplate")publicRabbitTemplateAckRabbitTemplate(ConnectionFactoryconnectionFactory){RabbitTemplaterabbitTemplate=newRabbitTemplate(connectionFactory);returnrabbitTemplate;}@Bean("confirmRabbitTemplate")publicRabbitTemplateConfirmRabbitTemplate(ConnectionFactoryconnectionFactory){RabbitTemplaterabbitTemplate=newRabbitTemplate(connectionFactory);rabbitTemplate.setConfirmCallback(newRabbitTemplate.ConfirmCallback(){@Overridepublicvoidconfirm(CorrelationDatacorrelationData,booleanack,Stringcause){if(ack){System.out.printf("消息接收成功, id:%s",correlationData.getId());}else{System.out.printf("消息接收失败, id:%s cause:%s",correlationData.getId(),cause);}}});returnrabbitTemplate;}}
  3. 发送消息

    @RequestMapping("/producer")@RestControllerpublicclassproducerController{@Resource(name="ackRabbitTemplate")privateRabbitTemplateackRabbitTemplate;@Resource(name="confirmRabbitTemplate")privateRabbitTemplateconfirmRabbitTemplate;@RequestMapping("/ack")publicStringack(){ackRabbitTemplate.convertAndSend(Constants.ACK_EXCHANGE_NAME,"ack","consumer ack test...");return"发送成功!";}@RequestMapping("/confirm")publicStringconfirm(){CorrelationDatacorrelationData=newCorrelationData("1");confirmRabbitTemplate.convertAndSend(Constants.CONFIRM_EXCHANGE_NAME,"confirm","consumer confirm test...",correlationData);return"发送成功!";}}

上面代码中有几处细节:

  1. 如果需要让不同的 RabbitTemplate 使用不同的配置的话,则需要对各自的 RabbitTemplate 进行配置,然后注册成不同的 Bean 对象交给 Spring 管理,在需要使用的时候利用@Resource注入即可。
  2. 为了防止多次调用 RabbitTemplate 的时候出现多次设置ConfirmCallback导致报错的情况,通常将设置ConfirmCallback的操作放在配置类中完成

二、return退回模式

消息到达 Exchange 之后,会根据路由规则匹配,把消息放入 Queue 中。Exchange 到 Queue 的过程,如果一条消息无法被任何队列消费(即没有队列与消息的路由键匹配或队列不存在等),可以选择把消息退回给发送者。消息退回给发送者时,我们可以设置一个返回回调方法,对消息进行处理,这就是所谓的退回模式。

  1. 配置 RabbitMQ(同 confirm 模式)

    spring:rabbitmq:addresses:amqp://liren:123123@127.0.0.1/lirendadalistener:simple:acknowledge-mode:manual# 消息确认publisher-confirm-type:correlated# 发布确认机制
  2. 设置返回回调逻辑:当消息无法被路由到任何队列,它将返回给发送者,这时setReturnCallback设置的回调将被触发

    @Bean("confirmRabbitTemplate")publicRabbitTemplateConfirmRabbitTemplate(ConnectionFactoryconnectionFactory){RabbitTemplaterabbitTemplate=newRabbitTemplate(connectionFactory);// 设置confirm回调(发送者 -> 交换机)rabbitTemplate.setConfirmCallback(newRabbitTemplate.ConfirmCallback(){@Overridepublicvoidconfirm(CorrelationDatacorrelationData,booleanack,Stringcause){if(ack){System.out.printf("消息接收成功, id:%s\n",correlationData.getId());}else{System.out.printf("消息接收失败, id:%s cause:%\n",correlationData.getId(),cause);}}});// 设置return回调(交换机 -> 队列)rabbitTemplate.setMandatory(true);rabbitTemplate.setReturnsCallback(newRabbitTemplate.ReturnsCallback(){@OverridepublicvoidreturnedMessage(ReturnedMessagereturned){System.out.printf("消息被退回: %s\n",returned);}});returnrabbitTemplate;}
  3. 发送消息:

    @RequestMapping("/returns")publicStringreturns(){CorrelationDatacorrelationData=newCorrelationData("5");confirmRabbitTemplate.convertAndSend(Constants.CONFIRM_EXCHANGE_NAME,"confirm","consumer returns test...",correlationData);confirmRabbitTemplate.convertAndSend(Constants.CONFIRM_EXCHANGE_NAME,"confirm11","consumer returns test...",correlationData);return"发送成功!";}

使用RabbitTemplate.setMandatory()方法设置消息的mandatory属性为true(默认为 false)。这个属性的作用是告诉 RabbitMQ,如果一条消息无法被任何队列消费,RabbitMQ 应该将消息返回给发送者,此时ReturnCallback会被触发。

其中该回调函数中有一个参数:ReturnedMessage,包含以下属性:

publicclassReturnedMessage{// 返回的消息对象,包含了消息体和消息属性privatefinalMessagemessage;// 由Broker提供的回复码, 表示消息无法路由的原因. 通常是一个数字代码,每个数字代表不同的含义.privatefinalintreplyCode;// 一个文本字符串, 提供了无法路由消息的额外信息或错误描述.privatefinalStringreplyText;// 消息被发送到的交换机名称privatefinalStringexchange;// 消息的路由键,即发送消息时指定的键privatefinalStringroutingKey;}

三、常见面试题💥 – 如何保证 RabbitMQ 消息的可靠传输?

从这个图中可以看出,消息可能丢失的场景以及解决方案:

  1. 生产者将消息发送到 RabbitMQ Server 失败

    1. 可能原因:网络问题等
    2. 解决办法:发布确认机制中的confirm 模式
  2. 消息在交换机中无法路由到指定队列:

    1. 可能原因:代码或者配置层面错误,导致消息路由失败
    2. 解决办法:发布确认机制中的return 模式
  3. 消息队列自身数据丢失

    1. 可能原因:消息到达 RabbitMQ 之后,RabbitMQ Server 宕机导致消息丢失
    2. 解决办法:持久性机制
      1. 开启 RabbitMQ 持久化,就是消息写入之后会持久化到磁盘,如果 RabbitMQ 挂了,恢复之后会自动读取之前存储的数据。(极端情况下,RabbitMQ 还未持久化就挂了,可能导致少量数据丢失,这个概率极低,也可以通过集群的方式提高可靠性)
  4. 消费者异常,导致消息丢失

    1. 可能原因:消息到达消费者,还没来得及消费、消费者宕机、消费者逻辑有问题
    2. 解决办法:消息确认机制
      • RabbitMQ 提供了消费者应答机制来使 RabbitMQ 能够感知到消费者是否消费成功消息。默认情况下消费者应答机制是自动应答的,可以开启手动确认,当消费者确认消费成功后才会删除消息,从而避免消息丢失。除此之外,也可以配置重试机制(参考下一章节),当消息消费异常时,通过消息重试确保消息的可靠性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1160810.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

降AI工具哪家强?2026年最新免费平台盘点,这10款高效好用别错过!

央视新闻说到了“大学生论文里的AI味渐浓”这件事。 现实就是这样。结课论文要查AI率,毕业论文也查,就连平时作业都逃不掉,AI率太高直接不过。每次查AICG出来结果的那一刻,简直是大学生崩溃的瞬间。 看着满屏幕的标红&#xff0…

麦橘超然Flux能否替代Stable Diffusion?对比分析

麦橘超然Flux能否替代Stable Diffusion?对比分析 1. 技术背景与选型动因 近年来,AI图像生成技术迅速演进,从早期的GAN架构到如今主流的扩散模型(Diffusion Models),生成质量不断提升。Stable Diffusion 自…

DeepSeek-V4蓄势待发!梁文锋署名论文或开启第二个DeepSeek时刻

据权威媒体The Information报道,DeepSeek将于2月(春节)发布新一代旗舰模型DeepSeek V4,该模型具备强大的编程能力,预计将对当前的AI竞争格局产生重大影响。元旦前一天,DeepSeek发了篇梁文锋署名论文&#x…

制造业企业如何构建高效数据采集系统:从挑战到实践

在当今竞争激烈的全球市场中,制造业企业正面临着前所未有的压力。产品生命周期缩短、客户需求日益个性化、供应链波动加剧,这些因素共同推动着企业向智能化、数字化方向转型。然而,许多制造企业在数字化转型的起步阶段就遇到了巨大障碍——数…

免费降AI工具精选:2026年10大平台横向评测,教你高效降低AI率!

央视新闻说到了“大学生论文里的AI味渐浓”这件事。 现实就是这样。结课论文要查AI率,毕业论文也查,就连平时作业都逃不掉,AI率太高直接不过。每次查AICG出来结果的那一刻,简直是大学生崩溃的瞬间。 看着满屏幕的标红&#xff0…

1.什么是电子签名?

📝 Java实现PDF在线盖章签字和签名 | 解锁文档处理新姿势 🚀 大家好呀~✨ 我是雪碧聊技术,今天给大家带来一篇超实用的技术干货!🌟 如果你正在为 PDF文档的电子签名 而烦恼,或者想在自己的项目中…

2026年免费降AI神器盘点:10款工具亲测对比,轻松应对各类AI检测系统!

央视新闻说到了“大学生论文里的AI味渐浓”这件事。 现实就是这样。结课论文要查AI率,毕业论文也查,就连平时作业都逃不掉,AI率太高直接不过。每次查AICG出来结果的那一刻,简直是大学生崩溃的瞬间。 看着满屏幕的标红&#xff0…

Claude自己写出Claude!2小时干完两月活,人类在工位上多余了?

Claude Cowork的横空出世,不仅是用10天自建系统的技术奇迹,更是对人类职业价值的一次残酷拷问:当AI两小时能干完两个月的工作,我们是该庆幸解放,还是该恐惧被替代? 打工人版Claude重磅出世,给全…

VSCode函数级开发与代码审计——核心操作全解析与落地实践

【精选优质专栏推荐】 《AI 技术前沿》 —— 紧跟 AI 最新趋势与应用《网络安全新手快速入门(附漏洞挖掘案例)》 —— 零基础安全入门必看《BurpSuite 入门教程(附实战图文)》 —— 渗透测试必备工具详解《网安渗透工具使用教程(全)》 —— 一站式工具手册《CTF 新手入门实战教…

Qwen模型快速选型指南:3小时试遍主流方案不超30元

Qwen模型快速选型指南:3小时试遍主流方案不超30元 你是不是也遇到过这样的情况:团队要上AI项目,领导让你尽快选出最适合的Qwen系列模型,但你一查发现——Qwen-7B、Qwen-Long、Qwen-Image、Qwen-Image-Edit……名字一堆&#xff0…

企业级开发环境中STM32CubeMX下载安装标准化流程

企业级开发中如何“无痛”落地 STM32CubeMX:从安装到团队协同的实战指南你有没有遇到过这样的场景?新同事入职第三天还在折腾开发环境,最后发现是因为他用的 STM32CubeMX 版本比团队高了半个小版本,生成的时钟配置代码直接让主控跑…

实现订单自动关闭机制——电商系统中的定时任务设计与实践

【精选优质专栏推荐】 《AI 技术前沿》 —— 紧跟 AI 最新趋势与应用《网络安全新手快速入门(附漏洞挖掘案例)》 —— 零基础安全入门必看《BurpSuite 入门教程(附实战图文)》 —— 渗透测试必备工具详解《网安渗透工具使用教程(全)》 —— 一站式工具手册《CTF 新手入门实战教…

改进A星算法:剔除冗余节点与光滑转折点

改进A星算法 剔除冗余节点,光滑转折点 对比优化前后路径。在路径规划领域,A星算法无疑是一颗耀眼的明星。然而,原始的A星算法生成的路径可能存在冗余节点,并且转折点不够光滑,影响了路径的实用性和美观性。今天咱们就来…

2.Java实现电子签名的两种工具

📝 Java实现PDF在线盖章签字和签名 | 解锁文档处理新姿势 🚀 大家好呀~✨ 我是雪碧聊技术,今天给大家带来一篇超实用的技术干货!🌟 如果你正在为 PDF文档的电子签名 而烦恼,或者想在自己的项目中…

Mac系统如何批量命名,Mac批量重命名软件工具

A Better Finder Rename:Mac 用户文件批量重命名的最佳选择如果你需要对文件进行批量命名,Mac自带的批量命名工具能大大提升你的效率。假如你需要为这些图片重新命名,将这些图片命名为墙纸并且加上连续的序号,选中图片后单击右键&…

基于拉丁超立方采样与自适应核密度估计的电力系统概率潮流精准计算

采用拉丁超立方采样的电力系统概率潮流计算 (自适应核密度估计,自适应带宽核密度估计) 拉丁超立方采样属于分层采样,是一种有效的用采样值反映随机变量的整体分布的方法。 其目的是要保证所有的采样区域都能够被采样点覆盖。 该方…

Z-Image-ComfyUI单卡部署教程:16G显存轻松运行指南

Z-Image-ComfyUI单卡部署教程:16G显存轻松运行指南 阿里最新开源,文生图大模型。 1. 引言 1.1 背景与学习目标 随着生成式AI的快速发展,文生图(Text-to-Image)模型已成为内容创作、设计辅助和智能应用开发的重要工具…

GBDT 生态的未来演化:从技术竞争到协同标准的形成

GBDT 生态的未来演化:从技术竞争到协同标准的形成在结构化数据竞赛场景下,XGBoost、LightGBM 与 CatBoost 形成三足鼎立格局。技术竞争推动了性能极限的突破,而 scikit-learn 作为统一接口促成了工具链的融合,预示着模型评估标准化…

adb 远程连接设备

1、连接设备 adb connect xxxx:5555 2、登陆设备 adb -s xxxx:5555 shell 3、上推下拉 连接设备后就可以操作 adb push adb pull /userdata/log/ ./ 这句把文件放到当前路径下了

Mac文件批量重命名工具:A Better Finder Rename

A Better Finder Rename:Mac 用户文件批量重命名的最佳选择如果你需要对文件进行批量命名,Mac自带的批量命名工具能大大提升你的效率。假如你需要为这些图片重新命名,将这些图片命名为墙纸并且加上连续的序号,选中图片后单击右键&…