kafka

一,简介

Kafka 是分布式发布-订阅消息系统。

它最初由 LinkedIn 公司开发,使用 Scala语言编写,之后成为 Apache 项目的一部分。

二,producer(生产者) 和consumer(消费者)

发送消息者称为Producer。消息接收者成为Consumer。

三,broker

kafka cluster(kafka集群)包含一个或多个服务器,服务器节点称为broker。

四,topic

一个topic可以认为是一类消息。一个topic当中有不确定条数的消息。

五,分区

如果一个topic中的所有消息都存在一台服务器(broker)上有三个弊端。第一个弊端:文件会越来越大;第二个弊端:读和写都在一台机器上,没有做到高性能;第三个弊端:如果机器倒台集群无法运转,没有做到高可用。

那么就将一个topic分成多个分区,每个分区存放在不同的broker上,即一个broker存储topic的一部分内容。

5.1分区副本

(1)partition的副本被称为replication,每个分区可以有多个副本。

(2)所有的读写请求都会通过leader完成,follower只负责备份数据,follower会被动定期地去复制leader上的数据。

(3)如果有M个replication,M就是topic的复制因子。其中有一个是Leader,其他M-1个是follower。注:那么这个副本的意思就不是leader的副本,而是指的是总体。

(4)默认情况下Kafka对应的topic的replication数量为1,即每个partition都只有leader。为了确保消息的可靠性,通常应用中将其值(由broker的参数offsets.topic.replication.factor指定)大小设置为大于1,比如3。

(5)事实上,同步复制要求所有能工作的follower都复制完,这条消息才会被commit,这种复制方式极大的影响了吞吐率。而异步复制方式下,follower异步的从leader复制数据,数据只要被leader写入log就被认为已经commit,这种情况下如果follower都还没有复制完,落后于leader时,突然leader宕机,则会丢失数据。而Kafka的这种使用ISR的方式则很好的均衡了确保数据不丢失以及吞吐率。

5.2分区数和broker数的关系。

(1)如果某个topic有N个partition,集群有N个broker,那么每个broker存储该topic的一个partition。

(2)如果某个topic有N个partition,集群有大于N个broker,那么其中有N个broker存储该topic的一个partition,剩下的broker不存储该topic的partition数据(但是可能会存储分区副本,)。

(3)如果某个topic有N个partition,集群有小于N个broker,那么一个broker存储该topic的一个或多个partition。在实际生产环境中,尽量避免这种情况的发生,这种情况容易导致Kafka集群数据不均衡。

综上:分区数量最好不要大于broker服务器的数量。

 

5.3如何理解分区内消息有序,分区间消息无序?

如下图所示:part1里面是消息1和消息6。part2里面是消息3和消息4。part3里面是消息2和消息5。

很明显分区内消息有序,这个有序指的是消息的先后顺序,消息序号并不一定紧挨着。

分区之间,比如part1中的消息不完全都在part2之前,part3中的消息也不完全都在part2之后。

因为每条消息都被append到该partition中,是顺序写磁盘,因此效率非常高(经验证,顺序写磁盘效率比随机写内存还要高,这是Kafka高吞吐率的一个很重要的保证)。

 

5.4 生产者producer如何发送数据到不同的partition

在发送一条消息时,可以指定这条消息的key,producer根据这个key和partition机制来判断将这条消息发送到哪个parition。paritition机制可以通过指定producer的paritition.class这一参数来指定,该class必须实现kafka.producer.Partitioner接口。如果key被解析为整数,则将该整数对partition总数取余,该消息会被发送到该数对应的partition。

import kafka.producer.Partitioner;
import kafka.utils.VerifiableProperties;

public class JasonPartitioner<T> implements Partitioner {

    public JasonPartitioner(VerifiableProperties verifiableProperties) {}
    
    @Override
    public int partition(Object key, int numPartitions) {
        try {
            int partitionNum = Integer.parseInt((String) key);
            return Math.abs(Integer.parseInt((String) key) % numPartitions);
        } catch (Exception e) {
            return Math.abs(key.hashCode() % numPartitions);
        }
    }
}
 
//如果将上例中的class作为partition.class,并通过如下代码发送20条消息(key分别为0,1,2,3)至topic2(包含4个partition)。
  

public void sendMessage() throws InterruptedException{
  for(int i = 1; i <= 5; i++){
        List messageList = new ArrayList<KeyedMessage<String, String>>();
        for(int j = 0; j < 4; j++){
            messageList.add(new KeyedMessage<String, String>("topic2", j+"", "The " + i + " message for key " + j));
        }
        producer.send(messageList);
    }
  producer.close();
}

5.4 文件存储

每个partion(目录)相当于一个巨型文件被平均分配到多个大小相等segment(段)数据文件中。但每个段segment file消息数量不一定相等,这种特性方便old segment file快速被删除。默认保留7天的数据。

Segment file组成:由2大部分组成,分别为index file和data file,此2个文件一一对应,成对出现,后缀”.index”和“.log”分别表示为segment索引文件、数据文件。 

Segment文件命名规则:partion全局的第一个segment从0开始,后续每个segment文件名为上一个segment文件最后一条消息的offset值。数值最大为64位long大小,19位数字字符长度,没有数字用0填充。 

索引文件存储大量元数据,数据文件存储大量消息,索引文件中元数据指向对应数据文件中message的物理偏移地址。 

其中以索引文件中元数据3,497为例,在368769.log数据文件中表示第3个message(在全局partiton表示第368772个message)、以及该消息的物理偏移地址为497。 

 

segment data file由许多message组成, qq物理结构如下: 

 读取offset=368776的message,需要通过下面2个步骤查找。

5.4.1、查找segment file

00000000000000000000.index表示最开始的文件,起始偏移量(offset)为0 
00000000000000368769.index的消息量起始偏移量为368770 = 368769 + 1 
00000000000000737337.index的起始偏移量为737338=737337 + 1 
其他后续文件依次类推。 
以起始偏移量命名并排序这些文件,只要根据offset 二分查找文件列表,就可以快速定位到具体文件。

当offset=368776时定位到00000000000000368769.index和对应log文件。

5.4.2、通过segment file查找message

当offset=368776时,依次定位到00000000000000368769.index的元数据物理位置和00000000000000368769.log的物理偏移地址 
然后再通过00000000000000368769.log顺序查找直到offset=368776为止。

5.5 数据默认存储时长

默认情况下,磁盘数据保存7天。

六,kafka在zookeeper中的数据

七,消费数据

6.1 队列模式

队列模式中,多个consumers可以同时从服务端读取消息,每个消息只被其中一个consumer读到。

6.2 发布订阅模式

发布-订阅模式中消息被广播到所有的consumer中。

6.3 consumer group

Consumers可以加入一个consumer group,组内的Consumer是一个竞争的关系,共同竞争一个topic内的消息。

topic中的所有数据都会发送到每个group组内,组内consumer竞争分区数据。

同一个group组内的用户,只消费各自分到的分区中的数据。

如果所有的consumer都在一个组中,这就成为了传统的队列模式。如果所有的consumer都不在不同的组中,这就成为了发布-订阅模式。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值