Rec: FuRenjie
kafka维护了一个topics,是消息类别或队列的基本单位 向topics发送消息的进程叫生产者 从topics订阅并处理消息的叫消费者 kafka是运行在由多个叫broker的服务组成的集群中。
所有服务器端与客户端交互使用了简单高效的TCP协议,官方提供了java的客户端,但实际上支持C,C++,python,Go,Ruby,Clojure,PHP,Erlang,Node.js等多种语言
topics
一个topic是一个用于发布消息的分类或feed名,kafka集群使用分区的日志,如下图所示。每个分区都是有顺序且不变的消息序列。commit的log可以不断追加。消息在每个分区中都分配了一个叫offset的id序列来唯一识别分区中的消息。
无论发布的消息是否被消费,kafka都会持久化一定时间(可配置)。 在每个消费者都持久化这个offset在日志中。通常消费者读消息时会使offset值线性的增长,但实际上其位置是由消费者控制,它可以按任意顺序来消费消息。比如复位到老的offset来重新处理。 这种联系可以使kafka消费变得很轻量级。不会集群或是其他消费者造成较大影响。 采用日志分区用于以下几种目的: 1.允许log规模超过一定大小以便适合单一的服务器。每个独立的分区log必须符合它对应的服务器,而一个topic可以有多个分区log这样可以处理任意多的数据。 2.他们代表了一个平行单元(不仅仅是这般)
分布式
分区日志分布在kafka集群的各个服务器上,每个服务器都共享这些日志。每个分区都是有多个复本并分布在指定数量(可配置)的服务器上。 每个分区都有个角色为leader的服务器,可以有0到多个角色为follower的服务器。leader处理对应分区上所有的读写请求。follower被动的复制leader。如果leader挂了,其中一个follower会自动变成新的leader.
生产者和消费者
生产者可以发布数据到它指定的topic中,并可以指定在topic里哪些消息分配到哪些分区(比如简单的轮流分发各个分区或通过指定分区语义分配key到对应分区) 传统消费一般是通过queue方式(消息依次被感兴趣的消费者接受)和发布订阅的方式(消息被广播到所有感兴趣的消费者)。kafka采用一种更抽象的方式:消费组(consumer group)来囊括传统的两种方式。首先消费者标记自己一个消费组名。消息将投递到每个消费组中的某一个消费者实例上。如果所有的消费者实例都有相同的消费组,这样就像传统的queue方式。如果所有的消费者实例都有不同的消费组,这样就像传统的发布订阅方式。消费组就好比是个逻辑的订阅者,每个订阅者由许多消费者实例构成(用于扩展或容错)。 相对于传统的消息系统,kafka拥有更强壮的顺序保证。传统的队列虽然在服务器端保证了消息的顺序,但是在投递给客户端的时候是异步的。所以消息可能会不是按顺序的到达不同消费者。或者采用exclusive消费者方式来保证顺序,但是显然这不能达到并行处理的目的(类似rabbitmq,通过异步将消息一批一批发送给每个client,但是若某个client挂了,该client拿到的消息不能得到消费,又会重新被服务器端给分配,导致其他client收到的消息不是按顺序的)。kafka由于topic采用了分区,故能够很好在多个消费者进程操作时保证顺序性和负载均衡。如下图所示:
它通过分配指定分区给消费组进而给一个消费者。可以保证此时一个消费者只会读一个分区,自然消息也就是顺序的。但是注意消费者实例的数量不能多于分区数。并且kafka只在对应的分区提供全局顺序。不对全局消息提供顺序。如果有这种需求,可以指定这个topic只有一个分区(意味着只有一个消费进程)。
使用场景
1.消息投递:能够很好的代替传统的message broker.它提供了更强大的吞吐量,内建分区,复本,容错等机制来解决大规模消息处理型应用程序。 2.web活动追踪:通过按类型将每个web动作发送到指定topic,然后由处理器去订阅各种topic,处理器包括实时处理,实时监控,加载到hadoop或其他离线存储系统用于离线处理等。 3.kafka常用于监控操作的数据到管道,比如从聚合和统计分布式应用到产生运营数据提要 4.日志聚集到指定区域(如HDFS或文件服务器等)用来处理 5.流处理。将消息分阶段进行聚合,强化或传递到其他topic
kafka保证: 1.生产者发送消息到指定的分区都是按顺序追加进去的 2.消费者实例是按消息持久化的顺序看到消息的 3.对于一个topic有n个复本,能保证n-1个服务器挂掉都不会导致任何提交的消息丢失。