Kafka系统的角色php
Broker :一台kafka服务器就是一个broker。一个集群由多个broker组成。一个broker能够容纳多个topichtml
topic: 能够理解为一个MQ消息队列的名字java
Partition:为了实现扩展性,一个很是大的topic能够分布到多个 broker(即服务器)上,一个topic能够分为多个partition,每一个partition是一个有序的队列。partition中的每条消息 都会被分配一个有序的id(offset)。kafka只保证按一个partition中的顺序将消息发给consumer,不保证一个topic的总体 (多个partition间)的顺序。也就是说,一个topic在集群中能够有多个partition,那么分区的策略是什么?(消息发送到哪一个分区上,有两种基本的策略,一是采用Key Hash算法,一是采用Round Robin算法)
算法
ookeeper在Kakfa中扮演的角色Kafka将元数据信息保存在Zookeeper中,可是发送给Topic自己的数据是不会发到Zk上的,不然Zk就疯了。
apache
kafka使用zookeeper来实现动态的集群扩展,不须要更改客户端(producer和consumer)的配置。broker会在zookeeper注册并保持相关的元数据(topic,partition信息等)更新。服务器
而客户端会在zookeeper上注册相关的watcher。一旦zookeeper发生变化,客户端能及时感知并做出相应调整。这样就保证了添加或去除broker时,各broker间仍能自动实现负载均衡。这里的客户端指的是Kafka的消息生产端(Producer)和消息消费端(Consumer)
架构
Broker端使用zookeeper来注册broker信息,以及监测partition leader存活性.并发
Consumer端使用zookeeper用来注册consumer信息,其中包括consumer消费的partition列表等,同时也用来发现broker列表,并和partition leader创建socket链接,并获取消息.app
Zookeer和Producer没有创建关系,只和Brokers、Consumers创建关系以实现负载均衡,即同一个Consumer Group中的Consumers能够实现负载均衡负载均衡
入门
一、简介
Kafka is a distributed,partitioned,replicated commit logservice。它提供了相似于JMS的特性,可是在设计实现上彻底不一样,此外它并非JMS规范的实现。kafka对消息保存时根据Topic进行归类,发送消息者成为Producer,消息接受者成为Consumer,此外kafka集群有多个kafka实例组成,每一个实例(server)成为broker。不管是kafka集群,仍是producer和consumer都依赖于zookeeper来保证系统可用性集群保存一些meta信息。
<ignore_js_op>
二、Topics/logs
一个Topic能够认为是一类消息,每一个topic将被分红多个partition(区),每一个partition在存储层面是append log文件。任何发布到此partition的消息都会被直接追加到log文件的尾部,每条消息在文件中的位置称为offset(偏移量),offset为一个long型数字,它是惟一标记一条消息。它惟一的标记一条消息。kafka并无提供其余额外的索引机制来存储offset,由于在kafka中几乎不容许对消息进行“随机读写”。
<ignore_js_op>
kafka和JMS(Java Message Service)实现(activeMQ)不一样的是:即便消息被消费,消息仍然不会被当即删除.日志文件将会根据broker中的配置要求,保留必定的时间以后删除;好比log文件保留2天,那么两天后,文件会被清除,不管其中的消息是否被消费.kafka经过这种简单的手段,来释放磁盘空间,以及减小消息消费以后对文件内容改动的磁盘IO开支.
对于consumer而言,它须要保存消费消息的offset,对于offset的保存和使用,有consumer来控制;当consumer正常消费消息时,offset将会"线性"的向前驱动,即消息将依次顺序被消费.事实上consumer可使用任意顺序消费消息,它只须要将offset重置为任意值..(offset将会保存在zookeeper中,参见下文)
kafka集群几乎不须要维护任何consumer和producer状态信息,这些信息有zookeeper保存;所以producer和consumer的客户端实现很是轻量级,它们能够随意离开,而不会对集群形成额外的影响.
partitions的设计目的有多个.最根本缘由是kafka基于文件存储.经过分区,能够将日志内容分散到多个server上,来避免文件尺寸达到单机磁盘的上限,每一个partiton都会被当前server(kafka实例)保存;能够将一个topic切分多任意多个partitions,来消息保存/消费的效率.此外越多的partitions意味着能够容纳更多的consumer,有效提高并发消费的能力.(具体原理参见下文).
三、Distribution
一个Topic的多个partitions,被分布在kafka集群中的多个server上;每一个server(kafka实例)负责partitions中消息的读写操做;此外kafka还能够配置partitions须要备份的个数(replicas),每一个partition将会被备份到多台机器上,以提升可用性.
基于replicated方案,那么就意味着须要对多个备份进行调度;每一个partition都有一个server为"leader";leader负责全部的读写操做,若是leader失效,那么将会有其余follower来接管(成为新的leader);follower只是单调的和leader跟进,同步消息便可..因而可知做为leader的server承载了所有的请求压力,所以从集群的总体考虑,有多少个partitions就意味着有多少个"leader",kafka会将"leader"均衡的分散在每一个实例上,来确保总体的性能稳定.
Producers
Producer将消息发布到指定的Topic中,同时Producer也能决定将此消息归属于哪一个partition;好比基于"round-robin"方式或者经过其余的一些算法等.
Consumers
本质上kafka只支持Topic.每一个consumer属于一个consumer group;反过来讲,每一个group中能够有多个consumer.发送到Topic的消息,只会被订阅此Topic的每一个group中的一个consumer消费.
若是全部的consumer都具备相同的group,这种状况和queue模式很像;消息将会在consumers之间负载均衡.
若是全部的consumer都具备不一样的group,那这就是"发布-订阅";消息将会广播给全部的消费者.
在kafka中,一个partition中的消息只会被group中的一个consumer消费;每一个group中consumer消息消费互相独立;咱们能够认为一个group是一个"订阅"者,一个Topic中的每一个partions,只会被一个"订阅者"中的一个consumer消费,不过一个consumer能够消费多个partitions中的消息.kafka只能保证一个partition中的消息被某个consumer消费时,消息是顺序的.事实上,从Topic角度来讲,消息仍不是有序的.
kafka的设计原理决定,对于一个topic,同一个group中不能有多于partitions个数的consumer同时消费,不然将意味着某些consumer将没法获得消息.
Guarantees
1) 发送到partitions中的消息将会按照它接收的顺序追加到日志中
2) 对于消费者而言,它们消费消息的顺序和日志中消息顺序一致.
3) 若是Topic的"replicationfactor"为N,那么容许N-1个kafka实例失效.
2、使用场景
一、Messaging
对于一些常规的消息系统,kafka是个不错的选择;partitons/replication和容错,可使kafka具备良好的扩展性和性能优点.不过到目前为止,咱们应该很清楚认识到,kafka并无提供JMS中的"事务性""消息传输担保(消息确认机制)""消息分组"等企业级特性;kafka只能使用做为"常规"的消息系统,在必定程度上,还没有确保消息的发送与接收绝对可靠(好比,消息重发,消息发送丢失等)
二、Websit activity tracking
kafka能够做为"网站活性跟踪"的最佳工具;能够将网页/用户操做等信息发送到kafka中.并实时监控,或者离线统计分析等
三、Log Aggregation
kafka的特性决定它很是适合做为"日志收集中心";application能够将操做日志"批量""异步"的发送到kafka集群中,而不是保存在本地或者DB中;kafka能够批量提交消息/压缩消息等,这对producer端而言,几乎感受不到性能的开支.此时consumer端可使hadoop等其余系统化的存储和分析系统.
它的架构包括如下组件:
话题(Topic):是特定类型的消息流。消息是字节的有效负载(Payload),话题是消息的分类名或种子(Feed)名。
生产者(Producer):是可以发布消息到话题的任何对象。
服务代理(Broker):已发布的消息保存在一组服务器中,它们被称为代理(Broker)或Kafka集群。
消费者(Consumer):能够订阅一个或多个话题,并从Broker拉数据,从而消费这些已发布的消息。
Kafka存储策略
1)kafka以topic来进行消息管理,每一个topic包含多个partition,每一个partition对应一个逻辑log,有多个segment组成。
2)每一个segment中存储多条消息(见下图),消息id由其逻辑位置决定,即从消息id可直接定位到消息的存储位置,避免id到位置的额外映射。
3)每一个part在内存中对应一个index,记录每一个segment中的第一条消息偏移。
4)发布者发到某个topic的消息会被均匀的分布到多个partition上(或根据用户指定的路由规则进行分布),broker收到发布消息往对应partition的最后一个segment上添加该消息,当某个segment上的消息条数达到配置值或消息发布时间超过阈值时,segment上的消息会被flush到磁盘,只有flush到磁盘上的消息订阅者才能订阅到,segment达到必定的大小后将不会再往该segment写数据,broker会建立新的segment。
Kafka删除策略
1)N天前的删除。
2)保留最近的MGB数据。
Kafka broker
与其它消息系统不一样,Kafka broker是无状态的。这意味着消费者必须维护已消费的状态信息。这些信息由消费者本身维护,broker彻底无论(有offset managerbroker管理)。
从代理删除消息变得很棘手,由于代理并不知道消费者是否已经使用了该消息。Kafka创新性地解决了这个问题,它将一个简单的基于时间的SLA应用于保留策略。当消息在代理中超过必定时间后,将会被自动删除。
这种创新设计有很大的好处,消费者能够故意倒回到老的偏移量再次消费数据。这违反了队列的常见约定,但被证实是许多消费者的基本特征。
如下摘抄自kafka官方文档:
Kafka Design
目标
1) 高吞吐量来支持高容量的事件流处理
2) 支持从离线系统加载数据
3) 低延迟的消息系统
持久化
1) 依赖文件系统,持久化到本地
2) 数据持久化到log
效率
1) 解决”small IO problem“:
使用”message set“组合消息。
server使用”chunks of messages“写到log。
consumer一次获取大的消息块。
2)解决”byte copying“:
在producer、broker和consumer之间使用统一的binary message format。
使用系统的pagecache。
使用sendfile传输log,避免拷贝。
端到端的批量压缩(End-to-end Batch Compression)
Kafka支持GZIP和Snappy压缩协议。
The Producer
负载均衡
1)producer能够自定义发送到哪一个partition的路由规则。默认路由规则:hash(key)%numPartitions,若是key为null则随机选择一个partition。
2)自定义路由:若是key是一个user id,能够把同一个user的消息发送到同一个partition,这时consumer就能够从同一个partition读取同一个user的消息。
异步批量发送
批量发送:配置很少于固定消息数目一块儿发送而且等待时间小于一个固定延迟的数据。
The Consumer
consumer控制消息的读取。
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一直等到有数据。
Consumer Position
1)大部分消息系统由broker记录哪些消息被消费了,但Kafka不是。
2)Kafka由consumer控制消息的消费,consumer甚至能够回到一个old offset的位置再次消费消息。
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,实现也没有问题。
复制(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里)。
日志压缩(Log Compaction)
1)针对一个topic的partition,压缩使得Kafka至少知道每一个key对应的最后一个值。
2)压缩不会重排序消息。
3)消息的offset是不会变的。
4)消息的offset是顺序的。
Distribution
Consumer Offset Tracking
1)High-level consumer记录每一个partition所消费的maximum offset,并按期commit到offset manager(broker)。
2)Simple consumer须要手动管理offset。如今的Simple consumer Java API只支持commit offset到zookeeper。
Consumers and Consumer Groups
1)consumer注册到zookeeper
2)属于同一个group的consumer(group id同样)平均分配partition,每一个partition只会被一个consumer消费。
3)当broker或同一个group的其余consumer的状态发生变化的时候,consumer rebalance就会发生。
Zookeeper协调控制
1)管理broker与consumer的动态加入与离开。
2)触发负载均衡,当broker或consumer加入或离开时会触发负载均衡算法,使得一个consumer group内的多个consumer的订阅负载平衡。
3)维护消费关系及每一个partition的消费信息。
生产者代码示例: