kafka事务

官方网址

用户提供一个事务id,用于初始化生产者。

一、额外的概念

  1. Transaction Coordinator
    类似于consumer group coordinator,管理事务日志和生产者的pid。
  2. Transaction Log
    类似于 Consumer Offsets topic,事务日志是事务的持久化存储,存储着每个活动的事务状态。已经完成的事务,其实事务日志就没有意义了。
  3. Control Messages.
    是写到用户topic的特殊的消息,这些日志不会暴露给用户 。broker用来提示消费者之前收到的事务消息是commited还是aborted的。
  4. TransactionalId
    每个生产者有唯一的TransactionalId,当多个生产者有相同的TransactionalId时,会使用最新的那个生产者。
   KafkaProducer producer = createKafkaProducer(“bootstrap.servers”, “localhost:9092”,“transactional.id”, “my-transactional-id”);
  1. producer epoch
    保证一个TransactionalId逻辑上只对应一个生产者。可以解决僵尸实例,即一个生产者挂掉后,系统重新启动一个新的生产者。但是原来的生产者又重新启动了,这时kafka就会把这生产者停掉。

二、 Data Flow
dataflow
网上很多地方可以找到这个图片。
这张图描述了一个事务的完整流程:
6. Finding a transaction coordinator – the FindCoordinatorRequest
寻找Transaction Coordinator。
7. Getting a producer Id – the InitPidRequest
获取分配的producer Id(pid)(需要显示指定TransactionalId)。
8. Starting a Transaction – The beginTransaction() API
这里只是从producer的角度表示开启了一个新事务,从Transaction Coordinator的角度,并没有开始一个事务。
9. The consume-transform-produce loop
这是一个比较长的过程,有很多请求在这个过程里。
4.1 AddPartitionsToTxnRequest
当producer写内容到一个新分区TopicPartition的时候,向Transaction Coordinator发消息,Transaction Coordinator记录到事务日志,表示一个事务的开始。之所以要记录producer事务里写的每一个分区是因为事务结束后要发送commit or abort markers到每个分区

4.2 ProduceRequest
4.3 AddOffsetCommitsToTxnRequest
4.4 TxnOffsetCommitRequest

  1. Committing or Aborting a Transaction
    准备提交或者终止事务,当producer发送请求之后,事务协调器做以下事情:
    1. 写PREPARE_COMMIT or PREPARE_ABORT 消息到事务日志。
    2. 写COMMIT (or ABORT) markers 到每个分区。
    3. Finally writes the COMMITTED (or ABORTED) message to transaction log.

当消费者接收到事务消息后,会缓存下来,一直等到接收到COMMIT(PID) or ABORT消息,才决定怎么处理消息。

三、 异常情况
官方文档

  1. 客户端或者服务端在事务的过程中可能发生错误,并且有可能已经往部分分区写了消息。这时一般有两种解决办法,1. 事务开始后,broker会启动timer,当timer超时后,终止事务。2. Transaction Coordinator主动终止事务。也就是往已经发送的分区,再发送终止消息。然后再决定是否由其他的生产者重启事务。

四、 消费者
消费者有两种模式:READ_COMMITTED or READ_UNCOMMITTED
READ_UNCOMMITTED:做了唯一改变就是,直接忽略 transactional control messages。
READ_COMMMITTED: 消费者客户端有个map [TxId-Partition] -> messages的映射。把收到的消息先存储起来,直到收到了 COMMIT or ABORT的事务控制消息。

发布了117 篇原创文章 · 获赞 219 · 访问量 55万+
展开阅读全文

springboot整合kafka超时的问题,错误提示如下所示

10-10

Caused by: org.apache.kafka.common.errors.TimeoutException: Timeout expired while fetching topic metadata 2019-10-10 00:06:20,395 ERROR [main] o.s.t.c.TestContextManager [TestContextManager.java:250] Caught exception while allowing TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener@78e117e3] to prepare test instance [com.nowcoder.community.KafkaTests@9b3be1c] java.lang.IllegalStateException: Failed to load ApplicationContext ## 测试代码如下: ``` import org.apache.kafka.clients.consumer.ConsumerRecord; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.kafka.core.KafkaTemplate; import org.springframework.stereotype.Component; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest @ContextConfiguration(classes = CommunityApplication.class) public class KafkaTests { @Autowired private KafkaProducer kafkaProducer; @Test public void testKafka() { kafkaProducer.sendMessage("test", "你好"); kafkaProducer.sendMessage("test", "在吗"); try { Thread.sleep(1000 * 10); } catch (InterruptedException e) { e.printStackTrace(); } } } @Component class KafkaProducer { @Autowired private KafkaTemplate kafkaTemplate; public void sendMessage(String topic, String content) { kafkaTemplate.send(topic, content); } } @Component class KafkaConsumer { @KafkaListener(topics = {"test"}) public void handleMessage(ConsumerRecord record) { System.out.println(record.value()); } } ``` 测试方法时报错,Caused by: org.apache.kafka.common.errors.TimeoutException: Timeout expired while fetching topic metadata 求大佬看看。 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览