你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

Azure 事件中心的 Apache Kafka 事务

本文详细介绍了如何将 Apache Kafka 事务 API 与 Azure 事件中心配合使用。

概述

事件中心提供 Kafka 终结点,现有的 Kafka 客户端应用程序可将该终结点用作运行你自己的 Kafka 群集的替代方案。 事件中心可与许多现有 Kafka 应用程序配合使用。 有关详细信息,请参阅适用于 Apache Kafka 的事件中心

本文档重点介绍如何无缝地将 Kafka 事务 API 与 Azure 事件中心配合使用。

注意

Kafka Transactions 目前在高级层和专用层中以公共预览版提供。

Apache Kafka 中的事务

在云本机环境中,应用程序必须能够灵活地应对网络中断及命名空间重启和升级。 需要严格处理保证的应用程序必须使用事务框架或 API 来确保执行所有操作,要么不执行任何操作,以便可靠地管理应用程序和数据状态。 如果一组操作失败,则可以原子方式可靠地重试这些操作,以确保正确的处理保证。

注意

当需要以“全部或无”方式处理多个操作时,通常需要事务性保证。

对于所有其他操作,如果特定操作失败,则客户端应用程序默认复原,从而以指数退避方式重试操作。

Apache Kafka 提供事务 API,以确保跨相同或不同的主题/分区集提供此级别的处理保证。

事务适用于以下情况:

  • 事务生成者。
  • 仅一次处理语义。

事务生成者

事务生成者确保将数据以原子方式写入到不同主题的多个分区。 生成者可以启动事务,写入同一主题或跨不同主题的多个分区,然后提交或中止事务。

为了确保生成者是事务性的,应将 enable.idempotence 设置为 true,以确保数据仅写入一次,从而避免发送端重复数据。 此外,应将 transaction.id 设置为唯一标识生成者。

    producerProps.put("enable.idempotence", "true");
    producerProps.put("transactional.id", "transactional-producer-1");
    KafkaProducer<String, String> producer = new KafkaProducer(producerProps);

初始化生成者后,以下调用可确保生成者以事务生成者身份向中转站注册 -

    producer.initTransactions();

然后,生成者必须显式开始事务,按正常方式执行跨不同主题和分区的发送操作,然后使用以下调用提交事务 –

    producer.beginTransaction();
	/*
        Send to multiple topic partitions.
    */
    producer.commitTransaction();

如果事务因错误或超时而需要中止,则生成者可以调用 abortTransaction() 方法。

	producer.abortTransaction();

仅一次语义

仅一次语义在事务生成者的基础上构建,方法是在生成者的事务范围内添加使用者,以便保证每个记录都仅读取、处理和写入一次

首先实例化事务生成者 -


    producerProps.put("enable.idempotence", "true");
    producerProps.put("transactional.id", "transactional-producer-1");
    KafkaProducer<K, V> producer = new KafkaProducer(producerProps);

    producer.initTransactions();

然后,使用者必须配置为只读取非事务性消息或提交的事务性消息,具体方法是设置以下属性 –


	consumerProps.put("isolation.level", "read_committed");
	KafkaConsumer <K,V> consumer = new KafkaConsumer<>(consumerProps);

实例化使用者后,可以订阅必须从中读取记录的主题 –


    consumer.subscribe(singleton("inputTopic"));

使用者轮询输入主题中的记录后,生成者将开始处理记录并将其写入输出主题的事务范围。 写入记录后,将创建所有分区的已更新偏移量映射。 然后,生成者会在提交事务之前将这个更新后的偏移量映射发送到事务。

在任何情况下,事务都将中止,生成者会以原子方式再次重试处理。

	while (true) {
		ConsumerRecords records = consumer.poll(Long.Max_VALUE);
		producer.beginTransaction();
        try {
    		for (ConsumerRecord record : records) {
    			/*
                    Process record as appropriate
                */
                // Write to output topic
    	        producer.send(producerRecord(“outputTopic”, record));
    		}
    
            /*
                Generate the offset map to be committed.
            */
            Map <TopicPartition, OffsetAndMetadata> offsetsToCommit = new Hashap<>();
            for (TopicPartition partition : records.partitions()) {
                // Calculate the offset to commit and populate the map.
                offsetsToCommit.put(partition, new OffsetAndMetadata(calculated_offset))
            }
            
            // send offsets to transaction and then commit the transaction.
    		producer.sendOffsetsToTransaction(offsetsToCommit, group);
    		producer.commitTransaction();
        } catch (Exception e)
        {
            producer.abortTransaction();
        }
	}

警告

如果事务在 max.transaction.timeout.ms 之前未提交或中止,则事务将自动由事件中心中止。 默认 max.transaction.timeout.ms 由事件中心设置为“15 分钟”,但生成者可以通过在生成者配置属性中设置 transaction.timeout.ms 属性将其替代为较小的值。

迁移指南

如果有想要与 Azure 事件中心一起使用的现有 Kafka 应用程序,请查看 Azure 事件中心的 Kafka 迁移指南以快速启动运行。

后续步骤

若要详细了解事件中心和适用于 Kafka 的事件中心,请参阅以下文章: