Kafka介绍
从事Java开发三年了,但是一直没写过什么分享,在项目组同事的建议下,在接下来的几篇中给大家介绍一下Kafka,主要让大家对它的使用、配置有个大概的认识。本人喜欢看书,但是不爱看实体书,因为不方便,图灵社区(http://www.ituring.com.cn/)和亚马逊是我经常关顾的,给大家推荐一下。接下来让我们进入正题。
Kafka是最初由Linkedin公司开发,是一个分布式、支持分区的(partition)、多副本的(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是可以实时的处理大量数据以满足各种需求场景:比如基于hadoop的批处理系统、低延迟的实时系统、storm/Spark流式处理引擎,web/nginx日志、访问日志,消息服务等等,用scala语言编写,Linkedin于2010年贡献给了Apache基金会并成为顶级开源项目。
以上是百度百科对Kafka的介绍,我想强调的就是“分布式消息系统”,这是它的本质(MQ即message queue)。它是一个JMS的实现,但并没有完全的遵守该规范。JMS消息通常有两种类型:
P2P:发送端将消息发送到消息队列,不用管接收端的行为,接受端只需要去消息队列中取消息,如果有消息就取出来进行消费,没有就进行等待。
Publish-Subscribe:发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息,而且为了消费消息,订阅者必须保持运行的状态
Kafka只支持发布订阅模式,不支持P2P。但是Kafka是发布订阅中的佼佼者,吞吐量可以很大。我们熟知的ActiveMq支持以上两种模式,但是吞吐量确不如Kafka。Kafka和一般的JMS的实现有点不太一样的是它的消费者消费消息的时候没有确认机制,它是通过偏移量(offset)来确定消费者是从什么位置去读取消息的。这也造成了一个问题,那就是在分区“再均衡”的时候可能会造成消息的重复消费,需要在程序中做幂等处理。现在你可能不太明白,后面的文章会重点讲解。
相关概念
1、Topics/logs
一个Topic可以认为是一类消息,每个topic将被分成多个partition的消息都会被直接追加到log文件的尾部,每条消息在文件中的位置称为offset(偏移量),offset为一个long型数字,它是唯一的标记一条消息。kafka没有提供索引机制来存储offset,因为kafka中不对消息进行“随机读写”。
kafka和ActiveMQ不同的是:即使消息被消费,消息仍然不会被立即删除,日志文件将会根据broker中的配置要求,保留一定的时间之后删除;比如log文件保留2天,之后不管消息是否被消费,文件都会被删除。可以达到减少磁盘IO开支的效果。
2、Partitions
每个server(kafka实例)负责partitions中消息的读写操作;此外kafka还可以配置partitions需要备份的个数(replicas),每个partition将会被备份到多台机器上,以提高可用性。每个partition都有一个server为“leader”;leader负责所有的读写操作,如果leader失效,那么将会有其他follower来接管(成为新的leader);follower只是简单的跟进与leader,同步消息即可。leader server承载了全部的请求压力,因此从集群整体考虑,有多少个partitions就有多少个leader,kafka将leader均衡分散在每个实例上,确保整体的性能稳定。
3、Producers
将消息发布到指定的Topic中,同时Producer也能决定将消息归属到哪个partitions,比如基于“round-robin”方式,或者通过其他的一些算法等。
4、Consumers
每个consumer属于一个consumer group。发送到Topic的消息,只会被订阅此Topic的每个group中的一个consumer消费。
如果所有的consumer都具有相同的group(属于queue模式),消息将会在consumer之间负载均衡。
如果所有的consumer都具有不同的group(属于“发布-订阅”模式),消息将会广播给所有的消费者。
一个partition中的消息只会被group中的一个consumer消费,一个consumer可以消费多个partitions中的消息。kafka只能保证一个partitions中的消息被某个consumer消费是顺序的。
kafka的设计原理决定,对于一个topic,同一个group中不能有多余partitions个数的consumer同时消费,否则将某些consumer无法得到消息。