kafka基本特性简介

1、简介

kafka是LinkedIn开发的用于日志数据处理的流式消息处理系统。官网上说kafka is a distributed、partitioned、replicated commit logservice.这句话充分体现了kafka的特性。kafka是首先是一个用于处理流式数据的日志处理系统,然后他是分布式的,他支持分区便于横向拓展,他具有冗余备份功能。

目前kafka主要有三个方面的用途,分别是消息订阅与发布系统、消息存储、流式数据处理。本文主要围绕kafka的消息订阅与发布功能进行介绍。

2、基本概念

2.1 topic

topic主题是kafka对流的一个抽象。主题是一个分类,例如新闻可以分为体育、战争、科技等话题,不同的主题有不同的发布者和订阅者。

2.2 partition

partiton是kafka的一个重要概念,是一个主题在物理上的分组。如下图所示,一个topic被分成了3个partition,每个partition都是一个队列结构。partition可以存在于不同的机器上,这样的好处是实现了负载均衡,不同的consumer可以从不同的partition中获取数据,partition的这种结构还便于集群的横向拓展。

2.3 producers和consumers

producer用于向kafka集群发送消息,消息必须具有主题。

consumers是消费者,向kafka获取消息。kafka作为消息队列灵活的地方在于它提出了Consumer Group的概念,Consumer Group内部可以有一个到多个Consumer。Consumer Group的好处在于:

1、负载均衡

一个Consumer Group里的Consumer应该是功能相近的,这些Consumer可以在不同的机器上,多个Consumer共同完成同一个Group的任务能够实现负载均衡。

2、保持队列的顺序一致性

一个topic的一个partition只对应一个Consumer,这样的好处就是由于一个partition里的消息是按照先后顺序的,那么交给一个Consumer来处理也会保持先后顺序。

下面是一个例子,假如某个topic具有3个partition,而一个具有3个Consumer的Group订阅了该消息,此时,每个partition会一对一地被Consumer消费。此时增加一个partition,那么3个Consumer中会有一个要多处理一个partition的消息。而如果增加的是一个Consumer的话,这个Consumer会空闲。

2.4 offset

kafka另外一个灵活的地方是offset偏移。kafka的数据在被消费之后不会立即被删除。一般来说只有在消息超过一定的时间限制后才会被删除,消费者消费的过程其实是将偏移指针向队列尾部移动的过程。当然消费者可以自定义地对偏移指针进行修改,如下代码所示为自动提交offset更改:

Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "test");
props.put("enable.auto.commit", "true");
props.put("auto.commit.interval.ms", "1000");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("foo","bar"))
while(true){
    ConsumerRecords<String,String> records=consumer.poll(100);
    for(ConsumerRecord<String,String> record:records){
        System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
    }
}

如下代码所示为手动提交offset更改,值得注意的是在Consumer的配置中,“enable.auto.commit”被设置成了false,通过Consumer.commitSync()来提交offset。

Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "test");
props.put("enable.auto.commit", "false");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props);
consumer.subscribe(Arrays.asList("foo", "bar"));
final int minBatchSize = 200;
List<ConsumerRecord<String, String>> buffer = new ArrayList<>();
while (true) {
    ConsumerRecords<String, String> records = consumer.poll(100);
    for (ConsumerRecord<String, String> record : records) {
        buffer.add(record);
    }
    if (buffer.size() >= minBatchSize) {
        insertIntoDb(buffer);
        consumer.commitSync();
        buffer.clear();
    }
}

除此之外还能进行更加精细地更改,精细到partition级别,如下代码所示针对每个partition的消息,使用consumer.commitSync(Collections.singletonMap(partition, new OffsetAndMetadata(lastOffset + 1)))。

try {
    while(running) {
        ConsumerRecords<String, String> records = consumer.poll(Long.MAX_VALUE);
        for (TopicPartition partition : records.partitions()) {
            List<ConsumerRecord<String, String>> partitionRecords = records.records(partition);
            for (ConsumerRecord<String, String> record : partitionRecords) {
                System.out.println(record.offset() + ": " + record.value());
            }
            long lastOffset = partitionRecords.get(partitionRecords.size() - 1).offset();
            consumer.commitSync(Collections.singletonMap(partition, new OffsetAndMetadata(lastOffset + 1)));
        }
    }
} finally {
  consumer.close();
} 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值