Kafka事务是怎么实现的?Kafka事务消息原理详解

在这里插入图片描述

目录

    • 一、Kafka事务性消息
      • 1.1 介绍Kafka事务性消息
      • 1.2 事务性消息的应用场景
      • 1.3 Kafka事务性消息的优势
    • 二、Kafka事务性消息的使用
      • 2.1 配置Kafka以支持事务性消息
        • 生产者配置
        • 消费者配置
      • 2.2 生产者:发送事务性消息
        • 创建Kafka生产者
        • 开始事务
        • 发送消息
        • 提交或中止事务
      • 2.3 消费者:处理事务性消息
        • 创建 Kafka 消费者
        • 订阅主题
        • 处理消息
        • 提交位移
    • 三、事务性消息的最佳实践
      • 3.1 保障消息的一次交付
        • 3.1.1 生产者幂等性
        • 3.1.2 消费者去重
      • 3.2 事务性消息的监控和故障排查
        • 3.2.1 监控工具
        • 3.2.2 故障排查
      • 3.3 事务性消息的性能考量
        • 3.3.1 性能调整
        • 3.3.2 吞吐量优化
    • 四、示例:生产和消费Kafka事务性消息
      • 4.1 示例1:生产事务性消息
        • 示例1代码:生产者
        • 代码说明:
      • 4.2 示例2:消费事务性消息
        • 示例2代码:消费者
        • 代码说明:
    • 五、总结
      • Kafka系列文章:

大家好,我是哪吒。

前两天,有个朋友去面试,被问到Kafka事务的问题。

她的第一反应是:

我是来面试Java的,怎么问我大数据的Kafka?

在这里插入图片描述

不过Kafka确实是Java程序员必备的中间件技术了,这点是毋庸置疑的。

在这里插入图片描述

Kafka几乎是当今时代背景下数据管道的首选,无论你是做后端开发、还是大数据开发,对它可能都不陌生。开源软件Kafka的应用越来越广泛。

面对Kafka的普及和学习热潮,哪吒想分享一下自己多年的开发经验,带领读者比较轻松地掌握Kafka的相关知识

上一节我们说到了解密Kafka主题的分区策略:提升实时数据处理的关键,今天系统的说一下Kafka的事务,实现步步为营,逐个击破,拿下Kafka。

在当今大数据时代,数据的可靠性和一致性变得至关重要。Kafka作为一个分布式流数据平台,强调了实时数据的高吞吐量传输,而Kafka事务性消息则在这个过程中发挥了至关重要的作用。

本文将详细介绍Kafka事务性消息,探究它们如何确保数据一致性,以及在各种应用场景中的应用。

一、Kafka事务性消息

1.1 介绍Kafka事务性消息

Kafka事务性消息是一项关键的功能,为确保数据一致性提供了重要的支持。在本部分,我们将深入了解Kafka事务性消息的基本概念。

Kafka事务性消息的概念

在这里插入图片描述

Kafka事务性消息是一种机制,用于确保消息的可靠性传递和处理。与非事务性消息相比,它们在数据处理中提供了额外的保证。一旦消息被写入Kafka集群,它们将被认为是已经处理,无论发生了什么。

为什么需要事务性消息?

在这里插入图片描述

事务性消息对于确保数据一致性至关重要。在某些应用程序中,消息的完整性和可靠性至关重要。如果在消息处理期间发生故障,如何保证消息不会丢失或重复是一个复杂的问题。Kafka事务性消息提供了解决这些问题的方式,使得消息处理更加可控和可靠。

事务性消息的特性

Kafka事务性消息具有以下关键特性:

在这里插入图片描述

  • 原子性:事务性消息要么完全成功,要么完全失败。这确保了消息不会被部分处理。

  • 可靠性:一旦消息被写入Kafka,它们将被视为已经处理,即使发生了应用程序或系统故障。

  • 顺序性:事务性消息在单个分区内保持顺序。这对于需要按顺序处理的应用程序至关重要。

  • 幂等性:Kafka生产者可以配置为幂等,确保相同的消息不会被重复发送。

  • Exactly Once语义:事务性消息支持"仅一次"语义,即消息要么完全到达一次,要么不到达。

本节的目标是帮助您理解Kafka事务性消息的核心概念。接下来,我们将探讨它们的应用场景以及相对于非事务性消息的优势。

1.2 事务性消息的应用场景

事务性消息在多种应用场景中发挥着关键作用。以下是一些常见的应用场景,其中事务性消息特别有用:

金融交易处理:在金融领域,每笔交易都必须具备原子性,确保不发生不一致或重复的交易。事务性消息可用于记录和处理金融交易,保证交易的完整性。

订单处理:在电子商务平台上,订单处理必须是可靠的,以确保订单的创建、支付和发货不会出现问题。事务性消息可用于跟踪和处理订单的不同阶段,从而确保订单流程的一致性。

库存管理:对于企业,库存管理是至关重要的。事务性消息可用于跟踪库存的变化,以确保库存的准确性和可靠性。

日志记录:在大数据和日志记录应用中,日志的完整性是至关重要的。事务性消息可用于确保日志的完整性,即使在日志处理集群发生故障时也能保持一致性。

系统通知:对于需要向用户发送通知或提醒的应用程序,确保通知的可靠发送至关重要。事务性消息可用于实现这一目标。

1.3 Kafka事务性消息的优势

相对于非事务性消息,Kafka事务性消息具有明显的优势,特别是在需要数据一致性的应用场景中。以下是Kafka事务性消息的优势:

数据一致性:事务性消息可确保消息要么被完全处理,要么不被处理。这消除了数据处理中的不一致性,有助于维护数据一致性。

可靠性:一旦消息被写入Kafka,它们将被视为已经处理,即使发生了应用程序或系统故障。这确保了消息的可靠传递。

幂等性:Kafka生产者可以配置为幂等,这意味着相同的消息不会被重复发送。这有助于减少不必要的消息传递,避免数据重复。

Exactly Once语义:事务性消息支持"仅一次"语义,即消息要么完全到达一次,要么不到达。这是某些应用程序所需的高级语义。

错误处理:事务性消息提供了一种处理错误的机制,以确保消息可以被恢复或重试,而不会丢失。

在这里插入图片描述

二、Kafka事务性消息的使用

在这一部分,我们将深入研究如何使用Kafka事务性消息来确保数据的一致性。

2.1 配置Kafka以支持事务性消息

配置Kafka以支持事务性消息对于确保消息在传递和处理过程中的一致性非常重要。在本节中,我们将详细讨论如何配置Kafka以支持事务性消息,包括生产者和消费者的设置。

生产者配置

在生产者端,需要进行一些特定的配置以启用事务性消息。以下是一些关键的配置参数:

  • acks:这是有关生产者接收到确认之后才认为消息发送成功的设置。对于事务性消息,通常将其设置为acks=all,以确保消息仅在事务完全提交后才被视为成功发送。

  • transactional.id:这是用于标识生产者实例的唯一ID。在配置文件中设置transactional.id是启用事务性消息的关键步骤。

  • enable.idempotence:幂等性是指相同的消息不会被重复发送。对于事务性消息,通常将其设置为enable.idempotence=true,以确保消息不会重复发送。

配置示例:

acks=all
transactional.id=my-transactional-id
enable.idempotence=true
消费者配置

在消费者端,同样需要进行适当的配置以确保正确处理事务性消息。以下是一些消费者的重要配置参数:

  • isolation.level:这是用于控制消费者的隔离级别的设置。对于事务性消息,通常将其设置为isolation.level=read_committed,以确保只读取已经提交的事务消息。

  • auto.offset.reset:这是消费者启动时从哪里开始读取消息的设置。通常将其设置为auto.offset.reset=earliest,以确保不会错过任何已提交的消息。

配置示例:

isolation.level=read_committed
auto.offset.reset=earliest

配置Kafka以支持事务性消息是确保消息可靠传递和处理的关键步骤。这些配置设置可以确保在生产和消费事务性消息时的正确行为。

2.2 生产者:发送事务性消息

在这一部分,我们将深入研究如何使用Kafka生产者来发送事务性消息。发送事务性消息是确保数据一致性的关键步骤,需要特别小心。以下是详细的步骤和示例:

创建Kafka生产者

首先,我们需要创建一个 Kafka 生产者的实例。这个生产者实例将负责将消息发送到 Kafka 主题。创建生产者需要配置参数,包括 Kafka 集群的地址、消息的键和值的序列化器、事务ID 等。

下面是一个创建 Kafka 生产者的示例:

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.Producer;
import org.apache.kafka.clients.producer.ProducerConfig;
import java.util.Properties;

public class MyKafkaProducer {
    public static Producer<String, String> createProducer() {
        Properties properties = new Properties();
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");
        properties.put(ProducerConfig.TRANSACTIONAL_ID_CONFIG, "my-transactional-id");

        return new KafkaProducer<>(properties);
    }
}
开始事务

在准备发送事务性消息之前,我们需要明确地开始一个事务。这通过调用 beginTransaction 方法来实现。一旦事务开始,所有后续的消息发送将包含在这个事务中。

producer.beginTransaction();
发送消息

在事务内,我们可以开始发送消息。这些消息将被包含在事务中,只有在事务成功提交时才会真正写入 Kafka 主题。

producer.send(new ProducerRecord<>("my-topic", "key1", "value1"));
producer.send(new ProducerRecord<>("my-topic", "key2", "value2"));
提交或中止事务

事务性消息的一个关键特性是它们要么完全成功,要么完全失败。因此,在消息发送后,我们需要根据消息的处理结果来决定是提交事务还是中止事务。这可以通过调用 commitTransactionabortTransaction 方法来实现。

try {
    producer.commitTransaction();
} catch (ProducerFencedException | OutOfOrderSequenceException | AuthorizationException e) {
    // 处理异常,通常中止事务并重试
    producer.close();
} catch (CommitFailedException e) {
    // 事务提交失败,通常中止事务并重试
    producer.close();
}

上述步骤提供了一个基本的示例,演示如何使用 Kafka 生产者发送事务性消息。事务性消息的发送确保了消息的可靠性和一致性,尤其在需要原子性保证的情况下非常有用。

2.3 消费者:处理事务性消息

在这一部分,我们将深入研究如何使用 Kafka 消费者来处理事务性消息。正确处理事务性消息对于保证数据一致性至关重要。以下是详细的步骤和示例:

创建 Kafka 消费者

首先,我们需要创建一个 Kafka 消费者的实例。这个消费者实例将负责从 Kafka 主题中读取消息。创建消费者需要配置参数,包括 Kafka 集群的地址、消息的键和值的反序列化器、消费者组 ID 等。

下面是一个创建 Kafka 消费者的示例:

import org.apache.kafka.clients.consumer.Consumer;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import java.time.Duration;
import java.util.Collections;
import java.util.Properties;

public class MyKafkaConsumer {
    public static Consumer<String, String> createConsumer() {
        Properties properties = new Properties();
        properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        properties.put(ConsumerConfig.GROUP_ID_CONFIG, "my-consumer-group");
        properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");
        properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");

        return new KafkaConsumer<>(properties);
    }
}
订阅主题

消费者需要明确地订阅包含事务性消息的主题。这通过调用 subscribe 方法来实现。一旦订阅,消费者将开始接收该主题上的消息。

consumer.subscribe(Collections.singletonList("my-topic"));
处理消息

一旦事务性消息到达,消费者需要确保消息被正确处理。这通常涉及到处理消息的逻辑,确保数据的一致性。处理消息的逻辑将根据具体的应用和需求而异。

ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<String, String> record : records) {
    String key = record.key();
    String value = record.value();
    // 处理消息的逻辑
}
提交位移

消费者需要负责提交消息的位移,以便正确跟踪已处理的消息。这通过调用 commitSynccommitAsync 方法来实现。位移的提交确保了消息不会被重复处理。

consumer.commitSync();

上述步骤提供了一个基本的示例,演示了如何使用 Kafka 消费者处理事务性消息。消费者的正确配置和消息处理确保了消息的可靠性和一致性。在实际应用中,处理消息的逻辑将更加复杂,以满足特定的需求。

在这里插入图片描述

三、事务性消息的最佳实践

在这一节,我们将提供一些关于如何使用Kafka事务性消息的最佳实践。这包括如何确保消息的一次交付、监控和故障排查以及性能优化。

3.1 保障消息的一次交付

3.1.1 生产者幂等性

确保生产者的幂等性是关键,以防止消息被重复发送。以下是一些关键策略和实践,可用于确保生产者的幂等性:

1. 分配唯一消息ID: 为每条消息分配一个唯一的消息ID。这可以是全局唯一的,也可以是特定于主题的唯一。在发送消息之前,生产者可以检查已经发送的消息记录,以确保当前消息的ID不重复。

2. 使用幂等性API: Kafka 提供了幂等性的生产者 API。你可以在生产者配置中启用幂等性,设置 enable.idempotence=true,以确保消息在发送时不会被重复处理。

3. 实现自定义幂等性: 在一些情况下,自定义实现幂等性逻辑可能是必要的。这可以涉及到在消息处理端的数据库或存储中跟踪已处理消息的状态,以确保消息不会被重复处理。

4. 设置适当的重试机制: 如果消息发送失败,生产者应该具备适当的重试机制,以确保消息最终被成功发送。重试机制需要在生产者的配置中进行设置。

3.1.2 消费者去重

保障消息不会被重复处理同样至关重要。以下是一些策略和最佳实践,可用于实现消费者的去重:

1. 幂等性消息处理逻辑: 消费者的消息处理逻辑应该是幂等的。这意味着无论消息被处理多少次,其结果都应该是相同的。这通常需要在应用程序代码中进行实施。

2. 消息唯一标识: 为每条消息分配一个唯一的标识符,如消息ID。在处理消息前,消费者可以维护一个记录已处理消息的数据结构,以确保消息不会被重复处理。

3. 消费者去重过程: 消费者在处理消息前,可以查询已处理消息的记录,如果消息已存在于记录中,可以选择跳过处理或进行进一步处理。这可以防止消息的重复处理。

4. 消费者库支持: 一些消息队列处理库提供了内置的去重机制,你可以利用这些库来简化去重处理。

以上内容提供了详细的策略和最佳实践,以确保消息的一次交付。这是保障数据一致性的关键步骤,特别适用于事务性消息的处理。这些实践可以根据具体的应用和需求进行定制化。

3.2 事务性消息的监控和故障排查

3.2.1 监控工具

监控Kafka事务性消息是确保系统的可靠性的重要部分。以下是一些监控工具和策略:

  • Kafka内置指标:Kafka提供了一组内置指标,用于监控事务性消息的性能和状态。你可以使用这些指标来跟踪消息的处理情况。

  • 日志文件:Kafka的日志文件包含了详细的事件信息,可以用于故障排查和性能分析。定期检查日志文件,以查找潜在的问题。

  • 监控系统:使用专业的监控系统,如Prometheus和Grafana,来建立实时监控和警报。这些系统可以帮助你及时发现问题并采取措施。

3.2.2 故障排查

当事务性消息出现问题时,需要能够排查和解决这些问题。以下是一些故障排查策略:

  • 日志分析:定期分析Kafka的日志文件,查找异常和错误信息。这可以帮助你及早发现问题并采取措施。

  • 监控警报:建立监控警报,以便在出现问题时立即收到通知。这有助于快速响应问题。

  • 版本和配置管理:确保Kafka和应用程序的版本和配置得到正确管理。不同版本或配置的不一致可能导致问题。

3.3 事务性消息的性能考量

性能是任何消息系统的关键指标,特别是对于高吞吐量和低延迟的需求。以下是一些性能考量和优化策略:

3.3.1 性能调整
  • 生产者性能调整:通过调整生产者的配置参数,如batch.sizeacks等,可以优化消息发送性能。

  • 消费者性能调整:消费者的性能也可以通过配置参数,如max.poll.recordsfetch.min.bytes等进行调整。

3.3.2 吞吐量优化
  • 分区和并

行度**:合理地选择分区数量和消费者的并行度,以确保系统能够处理大量事务性消息。

  • 水平扩展:如果系统负载增加,考虑进行水平扩展,增加Kafka代理和消费者实例,以提高吞吐量。

  • 网络和存储优化:确保网络和存储基础设施足够快,以支持高吞吐量的消息传递。

上述最佳实践策略和性能优化建议可以帮助你更好地使用Kafka事务性消息,确保消息的可靠传递和一致性处理,同时满足性能需求。通过仔细的配置、监控和故障排查,你可以建立一个可靠和高性能的消息处理系统。

四、示例:生产和消费Kafka事务性消息

在这一节,我们将提供两个示例,详细展示如何生产和消费Kafka事务性消息。

4.1 示例1:生产事务性消息

示例1代码:生产者
import org.apache.kafka.clients.producer.*;
import java.util.Properties;

public class TransactionalProducerExample {
    public static void main(String[] args) {
        String bootstrapServers = "localhost:9092";
        String topic = "my-transactional-topic";

        Properties properties = new Properties();
        properties.put("bootstrap.servers", bootstrapServers);
        properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        properties.put("acks", "all");
        properties.put("enable.idempotence", "true");
        properties.put("transactional.id", "my-transactional-id");

        Producer<String, String> producer = new KafkaProducer<>(properties);

        producer.initTransactions();

        try {
            producer.beginTransaction();
            ProducerRecord<String, String> record = new ProducerRecord<>(topic, "key", "value");
            producer.send(record);
            producer.commitTransaction();
        } catch (ProducerFencedException | OutOfOrderSequenceException | AuthorizationException e) {
            // Fenced, sequence issue, or authorization exception
            producer.close();
        } catch (KafkaException e) {
            // Handle other exceptions
            producer.close();
        }

        producer.close();
    }
}
代码说明:
  • 这个示例演示了如何创建一个Kafka生产者,配置它以支持事务性消息,并生产一条事务性消息。
  • transactional.id是一个用于标识生产者事务的唯一ID。它确保了事务性消息的一致性。
  • try块中,我们使用producer.beginTransaction()来启动一个事务,然后发送一条消息,最后使用producer.commitTransaction()来提交事务。
  • 如果在事务期间发生异常,我们在catch块中处理异常并关闭生产者。

4.2 示例2:消费事务性消息

示例2代码:消费者
import org.apache.kafka.clients.consumer.*;
import java.time.Duration;
import java.util.Collections;
import java.util.Properties;

public class TransactionalConsumerExample {
    public static void main(String[] args) {
        String bootstrapServers = "localhost:9092";
        String groupId = "my-consumer-group";
        String topic = "my-transactional-topic";

        Properties properties = new Properties();
        properties.put("bootstrap.servers", bootstrapServers);
        properties.put("group.id", groupId);
        properties.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
        properties.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");

        Consumer<String, String> consumer = new KafkaConsumer<>(properties);
        consumer.subscribe(Collections.singletonList(topic));

        while (true) {
            ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
            for (ConsumerRecord<String, String> record : records) {
                System.out.printf("Consumed record with key %s and value %s%n", record.key(), record.value());
            }
        }
    }
}
代码说明:
  • 这个示例演示了如何创建一个Kafka消费者,订阅一个主题,并消费事务性消息。
  • 消费者将持续轮询主题以获取新的消息。
  • 每当有新消息可用时,它将打印出消息的键和值。

五、总结

本文深入探讨了Kafka事务性消息的关键概念、应用场景、优势、配置、使用以及最佳实践。在总结中,让我们再次强调一些关键要点,并展望Kafka事务性消息的未来。

  • Kafka事务性消息是一种机制,用于确保消息的可靠性传递和处理。它们提供了额外的保证,确保消息要么完全成功,要么完全失败。
  • 应用场景:Kafka事务性消息在金融交易、库存管理、订单处理等需要高可靠性和数据一致性的应用中发挥关键作用。
  • 优势:事务性消息相对于非事务性消息提供了更高的数据一致性和可靠性,支持原子性、幂等性和"仅一次"语义。
  • 配置:配置Kafka以支持事务性消息包括生产者和消费者的设置,如transactional.idenable.idempotence等。
  • 生产事务性消息:使用Kafka生产者,需要初始化事务、发送消息,然后提交或中止事务,以确保消息的一致性。
  • 消费事务性消息:使用Kafka消费者,需要订阅主题并持续轮询以获取消息,然后确保消息被正确处理。
  • 最佳实践:最佳实践包括保障消息的一次交付、监控和故障排查以及性能考量,以确保系统的稳定性和高性能。

Kafka系列文章:

Kafka批处理与流处理详解

解密Kafka主题的分区策略:提升实时数据处理的关键


🏆哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师


在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Maven项目引入本地jar

Maven项目引入本地jar 1.对应maven模块项目中建lib目录&#xff0c;将jar放入进去 2.在对应的模块pom.xml中引入此依赖jar 3.在对应的maven-plugin插件打包的pom.xml中指定需要includeSystemScope为true的jar

HTML的img常见应用属性

目录 一、src、alt、width、height 的运用二、title的运用三、align的运用四、border的运用 一、src、alt、width、height 的运用 src指定图像的URL&#xff0c;即图像的路径alt指定图像的替代文本&#xff0c;当图像无法显示时&#xff0c;会显示替代文本。width指定图像的宽…

【特殊文件(一)】属性文件读写实操

文章目录 属性文件特殊文件概述Properties属性文件概述Properties属性文件读取Properties属性文件写操作 属性文件 特殊文件概述 IO流是用来读、写文件中的数据。但是我们接触到的文件大部分都是普通的文本文件&#xff0c;普通的文本文件里面的数据是没有任何格式规范的&…

E. Greedy Shopping

线段树经典题 维护最大值和最小值 还有区间和 #include<bits/stdc.h> using namespace std; using ll long long; const int N 2e510; ll w[N]; struct Segment{ll l,r;ll val,fmin,fmax;ll lz; }tr[N<<2];int n,m;void pushup(int u){tr[u].val tr[u<<…

有关光伏电站绝缘阻抗异常排查分析-安科瑞 蒋静

近几年&#xff0c;光伏发电技术迅猛发展&#xff0c;光伏扶贫电站及分布式光伏使光伏发电走进千家万户。然而光伏发电设备运行期间仍存在隐患。及时发现并解决*常见异常运行故障&#xff0c;可以很大地提高光伏发电设备可利用率&#xff0c;是保证光伏发电设备正常运行、满足收…

class074 背包dp-分组背包、完全背包【算法】

class074 背包dp-分组背包、完全背包【算法】 算法讲解074【必备】背包dp-分组背包、完全背包 code1 P1757 通天之分组背包 // 分组背包(模版) // 给定一个正数m表示背包的容量&#xff0c;有n个货物可供挑选 // 每个货物有自己的体积(容量消耗)、价值(获得收益)、组号(分组)…

“我“的测试之路,从初级测试到测试开发,往后前景...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、测试工程师的现…

PHP基础 - 数组

在PHP中,数组是一种特殊的变量类型,可以存储多个值。PHP中有多种创建数组的方法,其中之一是使用array()函数。 1. 数值数组 带有数字 ID 键的数组 <?php $scars = array("age","name","domicile"); // 使用数组函数创建一个空数组# 人…

基于SpringBoot+Vue前后端分离的景点数据分析平台(Java毕业设计)

大家好&#xff0c;我是DeBug&#xff0c;很高兴你能来阅读&#xff01;作为一名热爱编程的程序员&#xff0c;我希望通过这些教学笔记与大家分享我的编程经验和知识。在这里&#xff0c;我将会结合实际项目经验&#xff0c;分享编程技巧、最佳实践以及解决问题的方法。无论你是…

TailwindCSS 配置可视化检查器

问题 TailwindCSS 框架为我们提供了大量默认的类和属性&#xff0c;而且开发者也能够自定义类和配置。 对于初学者来说&#xff0c;这些配置其实是比较复杂的&#xff0c;这也是tailwindcss最大的入手成本&#xff0c;开发者的记忆负担和心智负担也都比较大。 有没有办法能够…

vue3原生方法滚动列表

效果图 代码 import { ref, onBeforeUnmount, onUnmounted } from "vue"; //定时器初始化 let timer ref(null); //ref绑定初始化 let roll ref(null); //等同于vue2中的beforeDestroy onBeforeUnmount(() > {//清除定时器clearTimeout(timer.value); }); //等同…

简单实现Spring容器(二) 封装BeanDefinition对象放入Map

阶段2: // 1.编写自己的Spring容器,实现扫描包,得到bean的class对象.2.扫描将 bean 信息封装到 BeanDefinition对象,并放入到Map.思路: 1.将 bean 信息封装到 BeanDefinition对象中,再将其放入到BeanDefinitionMap集合中,集合的结构大概是 key[beanName]–value[beanDefintion…

【图对比学习】GACN:使用对抗网络增强图对比学习

#论文题目&#xff1a;Graph Contrastive Learning with Generative Adversarial Network&#xff08;使用对抗网络增强图对比学习&#xff09; #论文地址&#xff1a;https://dl.acm.org/doi/pdf/10.1145/3580305.3599370 #论文源码开源地址&#xff1a;暂无 #论文所属会议&am…

如何公网访问内网的群晖NAS随时随地远程访问本地存储的学习资源

文章目录 前言本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是前排提醒&#xff1a; 1. 搭建群晖虚拟机1.1 下载黑群晖文件vmvare虚拟机安装包1.2 安装VMware虚拟机&#xff1a;1.3 解压黑群晖虚拟机文件1.4 虚拟机初始化1.5 没有搜索到黑群晖的解…

超卓航科引领冷喷涂增材制造革新,推动先进核反应堆发展

近日&#xff0c;超卓航科凭借其卓越的冷喷涂增材制造技术&#xff0c;成为推动核能领域创新的重要力量。该公司利用冷喷涂工程技术&#xff0c;或为核反应堆的制造和修复开辟了全新的道路。 冷喷涂技术是一种颇具前景的固态粉末沉积方法&#xff0c;可用于涂层制造、增材制造和…

【日志技术】附Logback入门教程

文章目录 日志概论日志的体系Logback快速入门日志配置文件配置日志级别 日志概论 什么是日志&#xff1f;其实可以通过下面几个问题来了解的。 系统系统能记住某些数据被谁操作&#xff0c;比如被谁删除了&#xff1f;想分析用户浏览系统的具体情况&#xff0c;比如挖掘用户的…

脱碱软化树脂Tulsimer CXO-5 MP 高盐水除钙镁树脂

一、产品介绍 Tulsimer CXO-5 MP 是一款大孔弱酸性丙烯酸系阳离子交换树脂&#xff0c;能除去水中的碱度和硬度&#xff0c;特别是除去水中的碳酸氢盐、碳酸盐及其它碱性盐类&#xff0c;适合运用于纯水 ,脱碱软化及选择性的去除重金属。适合在宽广的 pH 及温度范围情况下操作…

数据结构之单链表(不带头单向非循环链表)

一.引言 上一节我们学过了顺序表&#xff0c;那么我们想想顺序表有没有问题呢&#xff1f;我们来讨论顺序表的问题及思考。 顺序表问题&#xff1a; 1.中间/头部的插入删除&#xff0c;时间复杂度为O(N) 2. 增容需要申请新空间&#xff0c;拷贝数据&#xff0c;释放旧空间。会…

Go语言基础知识学习(一)

Go基本数据类型 bool bool型值可以为true或者false,例子&#xff1a; var b bool true数值型 类型表示范围int8有符号8位整型-128 ~ 127int16有符号16位整型-32768 ~ 32767int32有符号32位整型-2147783648 ~ 2147483647int64有符号64位整型uint8无符号8位整型0 ~ 255uint16…

使用CLion进行cuda编程,并使用cuda-gdb对核函数进行debug,这可能是全网你能够找到的最详细的CLion和cuda编程环境配置教程了

文章目录 前言一、环境准备二、相关学习资料三、环境配置1.新建Clion C Executable项目2.在Clion中的ToolChains中配置cuda-gdb3.配置CMake options4.配置CMakeLists.txt(1) Failed to compute shorthash for libnvrtc.so(2) c: error: unrecognized command-line option -G(3)…