spring kafka使用

本文介绍了Spring Kafka的使用,探讨了如何确保Kafka消息不丢失和避免重复消费,以及如何实现消息队列的高可用。内容包括在pom.xml中添加依赖,消息发布与订阅,数据库交互,以及Kafka的基本架构和高可用机制,如partition、replica和选举机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1,pom.xml中添加依赖

<dependency>
			<groupId>org.springframework.kafka</groupId>
			<artifactId>spring-kafka</artifactId> 
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka -->
		<dependency>
		    <groupId>org.apache.kafka</groupId>
		    <artifactId>kafka_2.12</artifactId>
		    <version>2.0.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients -->
		<dependency>
		    <groupId>org.apache.kafka</groupId>
		    <artifactId>kafka-clients</artifactId>
		    <version>2.0.0</version>
		</dependency>

2,定时从存入数据库中取出未发布的消息发布

  @Value("${kafka.producer.toerp.topic}")
  private String topic;
 
  @Resource
  private KafkaTemplate<String, String> kafkaTemplate;
  @Scheduled(cron = "0/1 * * * * ? ") // 每1秒执行一次
  @Override
  public void pushEventPublish() {
    EventPublish eventPublish = new EventPublish();
    eventPublish.setStatus((byte) 0);
    Map<String, Object> entityMap = findAll(eventPublish, PageRequest.of(0, Integer.MAX_VALUE));
    List<EventPublish> eventList = (List<EventPublish>) entityMap.get("data");
    for (EventPublish event : eventList) {
      try {
        kafkaTemplate.send(topic, JsonMapper.getInstance().toJson(event)).get(10, TimeUnit.SECONDS);
        event.setOffset(0);
        event.setStatus((byte) 1);
        save(event);
      } catch (Exception e) {
        log.error("{}", e);
      }
    }
  }

3,从kafka中订阅主题消息并存入数据库中

  @KafkaListener(topics = "${kafka.producer.fromerp.topic}")
  @Override
  public void kafkaConsumer(ConsumerRecord<String, Object> record) {
    EventProcess eventProcess = 
    JsonMapper.getInstance().fromJson(record.value().toString(), EventProcess.class);
    if (eventProcess == null || eventProcess.getPayLoad() == null) {
      return;
    }
    log.info("payLoad长度:{}", eventProcess.getPayLoad().length());
    eventProcess.setStatus((byte) 0);
    eventProcess.setOffset(record.offset());
    eventProcess.setId(null);
    save(eventProcess);
  }

4,从数据库中取消息进行处理

  @Scheduled(cron = "0/1 * * * * ? ") // 每30秒执行一次
  @Override
  public void findAllToExecute() {
    //TODO
}

5,配置文件

kafka.producer.fromerp.topic=wokuerp//订阅主题
kafka.producer.toerp.topic=wokuweb//发布主题

spring.kafka.bootstrap-servers=ip:9092
spring.kafka.consumer.group-id=web-consumer-group
spring.kafka.consumer.enable-auto-commit=true

Kafka消息保证不丢失和重复消费问题

在数据生产时避免数据丢失的方法:
使用同步模式的时候,有3种状态保证消息被安全生产,在配置为1(只保证写入leader成功)的话,如果刚好leader partition挂了,数据就会丢失。
还有一种情况可能会丢失消息,就是使用异步模式的时候,当缓冲区满了,如果配置为0(还没有收到确认的情况下,缓冲池一满,就清空缓冲池里的消息),
数据就会被立即丢弃掉。
只要能避免上述两种情况,那么就可以保证消息不会被丢失。
就是说在同步模式的时候,确认机制设置为-1,也就是让消息写入leader和所有的副本。
还有,在异步模式下,如果消息发出去了,但还没有收到确认的时候,缓冲池满了,在配置文件中设置成不限制阻塞超时的时间,也就说让生产端一直阻塞,这样也能保证数据不会丢失。

在数据消费时,避免数据丢失的方法:如果使用了storm,要开启storm的ackfail机制;如果没有使用storm,确认数据被完成处理之后,再更新offset值。低级API中需要手动控制offset值。

数据重复消费的情况,如果处理?
(1)去重:将消息的唯一标识保存到外部介质中,每次消费处理时判断是否处理过;
(2)不管:大数据场景中,报表系统或者日志信息丢失几条都无所谓,不会影响最终的统计分析结果。

如何保证消息队列的高可用啊?

kafka一个最基本的架构认识:多个broker组成,每个broker是一个节点;你创建一个topic,这个topic可以划分为多个partition,每个partition可以存在于不同的broker上,每个partition就放一部分数据。

这就是天然的分布式消息队列,就是说一个topic的数据,是分散放在多个机器上的,每个机器就放一部分数据。

实际上rabbitmq之类的,并不是分布式消息队列,他就是传统的消息队列,只不过提供了一些集群、HA的机制而已,因为无论怎么玩儿,rabbitmq一个queue的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个queue的完整数据。

kafka 0.8以前,是没有HA机制的,就是任何一个broker宕机了,那个broker上的partition就废了,没法写也没法读,没有什么高可用性可言。

kafka 0.8以后,提供了HA机制,就是replica副本机制。每个partition的数据都会同步到吉他机器上,形成自己的多个replica副本。然后所有replica会选举一个leader出来,那么生产和消费都跟这个leader打交道,然后其他replica就是follower。写的时候,leader会负责把数据同步到所有follower上去,读的时候就直接读leader上数据即可。只能读写leader?很简单,要是你可以随意读写每个follower,那么就要care数据一致性的问题,系统复杂度太高,很容易出问题。kafka会均匀的将一个partition的所有replica分布在不同的机器上,这样才可以提高容错性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值