学习来源:
1.简介
Apache Kafka由著名职业社交公司LinkedIn开发,最初是被设计用来解决LinkedIn公司内部海量日志传输等问题。Kafka使用Scala语言编写,于2011年开源并进入Apache孵化器,2012年10月正式毕业,现在为Apache顶级项目。
Kafka是一个分布式数据流平台,可以运行在单台或者多台服务器上部署形成集群。它提供了发布和订阅功能,使用者可以发送数据到Kafka中,也可以从Kafka中读取数据(以便进行后续的处理)。Kafka具有高吞吐、低延迟、高容错等特点。设计内在就是分布式的,分区的和可复制的提交日志服务。
2.架构组件
Broker 节点
Kafka集群包含一个或多个服务器,这种服务器被称为brokerTopic 主题
每条发布到Kafka集群的消息都有一个类别,这个类别被称为Topic。(物理上不同Topic的消息分开存储,逻辑上一个Topic的消息虽然保存于一个或多个broker上但用户只需指定消息的Topic即可生产或消费数据而不必关心数据存于何处)Partition 分区
Partition是物理上的概念,每个Topic包含一个或多个Partition.Producer 生产者
负责发布消息到Kafka brokerConsumer 消费者
消息消费者,向Kafka broker读取消息的客户端。Consumer Group 消费组
每个Consumer属于一个特定的Consumer Group(可为每个Consumer指定group name,若不指定group name则属于默认的group)。消息(Record):
实际写入Kafka中并可以被读取的消息记录。每个record包含了key、value和timestamp。Segment:消息的聚合单位,包括一定的消息数量。
一个topic,可以有partion
每个partition都是一个有序并且不可变的消息记录集合。当新的数据写入时,就被追加到partition的末尾。在每个partition中,每条消息都会被分配一个顺序的唯一标识,这个标识被称为offset,即偏移量。注意,Kafka只保证在同一个partition内部消息是有序的,在不同partition之间,并不能保证消息有序。
不同的Partition是给到不同的消费者的,所以我们也可以定制查询让特定的消息进入特定的Partition。
produce发送的消息分发到不同的partition中,consumer接受数据的时候是按照group来接受,kafka确保每个partition只能同一个group中的同一个consumer消费,如果想要重复消费,那么需要其他的组来消费。Zookeerper中保存这每个topic下的每个partition在每个group中消费的offset
跨borker的replicate(将follower视为replication);
leader挂掉,会重新选举leader。
同一个broker中的partion可以既有leader,也有follower
- 生产部分:
kafka以topic来进行消息管理,每个topic包含多个partition,每个partition对应一个逻辑log,有多个segment组成。 - 消费部分:
每个消费者实例可以消费多个分区,但是每个分区最多只能被消费者组中的一个实例消费。
复制(Replication)过程:
1)一个partition的复制个数(replication factor)包括这个partition的leader本身。
2)所有对partition的读和写都通过leader。
3)Followers通过pull获取leader上log(message和offset)
4)如果一个follower挂掉、卡住或者同步太慢,leader会把这个follower从”in sync replicas“(ISR)列表中删除。
5)当所有的”in sync replicas“的follower把一个消息写入到自己的log中时,这个消息才被认为是”committed“的。
6)如果针对某个partition的所有复制节点都挂了,Kafka选择最先复活的那个节点作为leader(这个节点不一定在ISR里)。
Consumers and Consumer Groups
1)consumer注册到zookeeper
2)属于同一个group的consumer(group id一样)平均分配partition,每个partition只会被一个consumer消费。
3)当broker或同一个group的其他consumer的状态发生变化的时候,consumer rebalance就会发生。
3.基本原理
3.1 生产者
生产者可以将数据写入到选定的主题。生产者负责决定要将哪条记录写入到那个分区当中。可以使用轮询方式,即每次取一小段时间的数据写入某个partition,下一小段的时间写入下一个partition;也可以使用一些分区函数(比如哈希),根据record的key值将记录写入不同的分区。
3.2 消费者
多个消费者实例可以组成一个消费者组,并用一个标签来标识这个消费者组。一个消费者组中的不同消费者实例可以运行在不同的进程甚至不同的服务器上。
如果所有的消费者实例都在同一个消费者组中,那么消息记录会被很好的均衡的发送到每个消费者实例。
如上图所示,一个两个节点的Kafka集群上拥有一个四个partition(P0-P3)的topic。有两个消费者组都在消费这个topic中的数据,消费者组A有两个消费者实例,消费者组B有四个消费者实例。
从图中我们可以看到,在同一个消费者组中,每个消费者实例可以消费多个分区,但是每个分区最多只能被消费者组中的一个实例消费。也就是说,如果有一个4个分区的主题,那么消费者组中最多只能有4个消费者实例去消费,多出来的都不会被分配到分区。其实这也很好理解,如果允许两个消费者实例同时消费同一个分区,那么就无法记录这个分区被这个消费者组消费的offset了。如果在消费者组中动态的上线或下线消费者,那么Kafka集群会自动调整分区与消费者实例间的对应关系。
3.3 kafka储存策略
kafka以topic来进行消息管理,每个topic包含多个partition,每个partition对应一个逻辑log,有多个segment组成。
每个segment中存储多条消息,消息id由其逻辑位置决定,即从消息id可直接定位到消息的存储位置,避免id到位置的额外映射。(每个part在内存中对应一个index,记录每个segment中的第一条消息偏移)
发布者发到某个topic的消息会被均匀的分布到多个partition上(或根据用户指定的路由规则进行分布),broker收到发布消息往对应partition的最后一个segment上添加该消息,当某个segment上的消息条数达到配置值或消息发布时间超过阈值时,segment上的消息会被flush到磁盘,只有flush到磁盘上的消息订阅者才能订阅到,segment达到一定的大小后将不会再往该segment写数据,broker会创建新的segment。
3.4 kafka删除策略
1.N天前的删除。
2.保留最近的n GB数据。
3.5 broker
与其它消息系统不同,Kafka broker是无状态的。这意味着消费者必须维护已消费的状态信息。这些信息由消费者自己维护,broker完全不管(有offset managerbroker管理)。
从代理删除消息变得很棘手,因为代理并不知道消费者是否已经使用了该消息。Kafka创新性地解决了这个问题,它将一个简单的基于时间的SLA应用于保留策略。当消息在代理中超过一定时间后,将会被自动删除。这种创新设计有很大的好处,消费者可以故意倒回到老的偏移量再次消费数据。这违反了队列的常见约定,但被证明是许多消费者的基本特征。
3.6 容错 (Multi-tenancy)
每个topic的分区都可以分布在Kafka集群的不同服务器上。比如topic A有partition 0,1,2,分别分布在Broker 1,2,3上面。每个服务器都可以处理分布在它上面的分区的写入和读取操作。另外,每个分区也可以配置多个副本用来提高容错性。
每个partition有一个服务器充当“leader”,零至多个服务器充当“follower”。Leader会处理针对于这个分区的所有读写操作,而follower只是被动的从leader中复制数据。当leader挂掉了,那么原有的follower会自动选举出一个新的leader。每台服务器都会作为一些分区的leader,也会作为其他分区的follower,所以Kafka集群内的负载会比较均衡。
如果所有的消费者实例都在不同的消费者组,那么每一条消息记录会被广播到每一个消费者实例。
3.7 持久化
依赖文件系统(持久化到本地),数据持久化到log
3.8 效率
解决”small IO problem“:
使用”message set“组合消息。
server使用"chunks of messages"写到log。consumer一次获取大的消息块。解决”byte copying“:
在producer、broker和consumer之间使用统一的binary message format。
使用系统的pagecache。
使用sendfile传输log,避免拷贝。端到端的批量压缩(End-to-end Batch Compression),Kafka支持GZIP和Snappy压缩协议。
异步批量发送
批量发送:配置不多于固定消息数目一起发送并且等待时间小于一个固定延迟的数据。
3.9 目标 && 应用场景
- 高吞吐量来支持高容量的事件流处理
- 2.支持从离线系统加载数据
- 低延迟的消息系统
3.10 Push vs Pull
1)producer push data to broker,consumer pull data from broker
2)consumer pull的优点:consumer自己控制消息的读取速度和数量。
3)consumer pull的缺点:如果broker没有数据,则可能要pull多次忙等待,Kafka可以配置consumer long pull一直等到有数据。
3.11 三种消息发送语义(Message Delivery Semantics)
- At most once—Messages may be lost but are never redelivered.
- At least once—Messages are never lost but may be redelivered.
- Exactly once—this is what people actually want, each message is delivered once and only once.
Producer:有个”acks“配置可以控制接收的leader的在什么情况下就回应producer消息写入成功。
Consumer:
读取消息,写log,处理消息。如果处理消息失败,log已经写入,则无法再次处理失败的消息,对应”At most once“。
读取消息,处理消息,写log。如果消息处理成功,写log失败,则消息会被处理两次,对应”At least once“。
读取消息,同时处理消息并把result和log同时写入。这样保证result和log同时更新或同时失败,对应”Exactly once“。
Kafka默认保证at-least-once delivery,容许用户实现at-most-once语义,exactly-once的实现取决于目的存储系统,kafka提供了读取offset,实现也没有问题。
3.12 Zookeeper协调控制
1)管理broker与consumer的动态加入与离开。
2)触发负载均衡,当broker或consumer加入或离开时会触发负载均衡算法,使得一个consumer group内的多个consumer的订阅负载平衡。
3)维护消费关系及每个partition的消费信息。
全系统分布式,即所有的Producer、Broker和Consumer都默认有多个,均为分布式的。Producer和Broker之间没有负载均衡机制。Broker和Consumer 之间利用ZooKeeper进行负载均衡。所有的Broker和Consumer都会在Zookeeper中进行注册,且Zookeeper会保存他们的一些元数据信息。如果某个Broker和Consumer发生了变化,那么所有其他的Broker和Consumer都会得到通知。
kafka高并发原理
//www.greatytc.com/p/12d59d9951f3
- 写高并发:写到缓存中,系统自动 刷到磁盘。
2.读高并发:零拷贝技术