kafka 的设计原理(Kafka设计原理分析)
1、基本概念
Kafka:A distributed streaming platform,是一种高吞吐量的分布式发布订阅消息系统,使用scala编写。kafka是一个分布式的,分区的消息(commit log)服务。
2、组件
Topic:是一个高层次的抽象概念,kafka按照Topic分类来维护消息;
Producter:将发布publish消息到Topic的进程称之为生产者producter;
Consumer:将订阅subscribe topic 并且处理Topic中消息的进程称之消费者consumer;
Broker:kafka以集群的方式运作,集群中的每一台服务器称之为一个代理broker;
可以将Topic理解为是一个类别的名称,所有的message发送到Topic下面,对于一个Topic,kafka集群按照如下方式维护一个分区(partition,可以将其理解为一个队列Queue)日志文件
partition是一个有序的message序列,这些message按顺序添加到一个叫做commit log的文件中,
每个partition中的消息都有一个唯一的编号,称之为offset.用来唯一标识某个分区中的message;
每个partition,都对应一个commit-log,一个partition中的message的offset都是唯一的,但是不同的partition中的message的offset可能是相同。
每个consumer是基于自己在commit log中的消费进度(offset)来进行工作的,在kafka中,offset由consumer来维护,一般情况下,我们按照顺序逐条消费commit log中的消息,当然我们也可以通过指定offset来重复消费某些消息,或者跳过某些消息。这意味着kafka中的consumer对集群的影响是非常小的,添加一个或者减少一个consumer,对于集群或者其他consumer来说,都是没有影响的,因为每个consumer维护各自的offset.
对log进行分区(partitioned),有几个目的,首先,当log文件大小超过文件系统的限制时,可以自动炒粉,每个partition对应的log都受到所在机器的文件系统大小的限制,但是一个topic中是可以有多个分区的,因为可以处理任意数据的数据,其次,是为了提高并行度.
Distribution
log的partitions分布在kafka集群中的不同broker上,每个broker可以请求备份其他broker上的partition数据,kafka集群支持配置一个partition备份的数量,即多个副本。
针对每个partition的多个副本(在多个broker上),都有一个broker起到 leader 的作用,其他broker作为follwers,leader处理所有针对这个partition的读写请求,而flowers被动复制leader的结果,如果这个leader失效了,其中的一个flower将自动的变成新的leader,每个broker都是自己所管理的partiton的leader,同时又是其他broker所管理partitons的flowers,kafka通过这种方式来达到负载均衡。
log的partitions分布在kafka集群中的不同broker上,每个broker可以请求备份其他broker上的partition数据,kafka集群支持配置一个partition备份的数量,即多个副本。
针对每个partition的多个副本(在多个broker上),都有一个broker起到 leader 的作用,其他broker作为follwers,leader处理所有针对这个partition的读写请求,而flowers被动复制leader的结果,如果这个leader失效了,其中的一个flower将自动的变成新的leader,每个broker都是自己所管理的partiton的leader,同时又是其他broker所管理partitons的flowers,kafka通过这种方式来达到负载均衡
Producters
生产者将消息发送到topic中,同时负责选择将message发送到topic的哪一个partition中,如果不指定partition,则通过round-robin(轮询)做简单的负载均衡,也可以根据消息中的某一个关键字来进行区分
Consumers
传统的消息传递模式有2种,队列(queuing)和广播(public-subscribe);在queuing中,多个consumer从服务器中读取数据,消息只会到达一个consumer,而public-subscribe模型中,消息会被广播给所有的comsumer.
consumer实例可运行在不同的进程上,也可以在不同的物理机器上。
如果所有的consumer都位于同一个consumer group下,这就类似于传统的queue模式,并在众多的consumer instance之间进行负载均衡。
如果所有的consumer都有着自己唯一的consumer group,这就类似于传统的public-subscribe模型。
传统的消息传递模式有2种,队列(queuing)和广播(public-subscribe);在queuing中,多个consumer从服务器中读取数据,消息只会到达一个consumer,而public-subscribe模型中,消息会被广播给所有的comsumer。
kafka基于这2中模式,提供了一种comsumer的抽象概念,consumer group,每个comsumer都要标记自己属于哪一个consumer group;发布到topic中的message会被传递到consumer group中的一个comsumer实例。
如果所有的consumer都位于同一个consumer group下,这就类似于传统的queue模式,并在众多的consumer instance之间进行负载均衡。
如果所有的consumer都有着自己唯一的consumer group,这就类似于传统的public-subscribe模型。
更一般的情况是,通常一个topic会有几个consumer group,每个consumer group都是一个逻辑上的订阅者(logical subscriber),每个consumer group由多个consumer instance组成,从而达到可扩展和容灾的功能,这并没有什么特殊的地方,仅仅是将public-subscribe模型中的运行在当个进程上的consumer替换成一个consumer group。如下
消费顺序
kafka比传统的消息系统有着更强的顺序保证。在传统的情况下,服务器按照顺利保留消息到队列,如果有多个consumer来消费队列中的消息,服务器会按接收消息的顺序向外提供消息,但是,尽管服务器是按照顺序提供消息,但是消息传递到每一个consumer是异步的,这可能会导致消费的consumer获取到消息的时间可能比后消费的consumer获取到消息的时间长,导致不能保证顺序性。这表明,当进行并行消费的时候,消息在多个consumer之间可能会失去顺序性,这时候,消息系统通常会采取一种“exclusive consumer”的概念,来确保同一时间内只有一个consumer能够从队列中进行消费,但是这实际上意味着消息处理的过程中是不支持并行的。
kafka在这方面做得更好。通过Topic中并行度的概念,即partition,kafka可以同时提供顺序性保证和多个consumer同时消费时的负载均衡,实现的原理是通过将一个topic中的不同partition分配给一个consumer group中的不同consumer instance,一个partiton对应一个instance,如上图中的consumer groupA。通过这种方式,我们可以保证一个partition在同一时刻只有一个consumer instance在消费消息,从而保证顺序;虽然一个topic中有多个partition,但是一个consumer group中同时也有多个consumer instance,通过合理的分配,依然能够保证负载均衡。需要注意的是,一个consumer group中的consumer instance的数量不能比一个topic 中的partition的数量多(防止重复消费);
kafka只在partition的范围内保证消息消费的局部顺序性,不能在同一个topic中的多个partition中保证总的消费顺序性。如果需要在总体上保证消费的顺序的的需求的话,那么我们可以将topic的partition数量设置为1,将consumer group中的consumer instance数量也设置为1。
kafka比传统的消息系统有着更强的顺序保证。在传统的情况下,服务器按照顺利保留消息到队列,如果有多个consumer来消费队列中的消息,服务器会按接收消息的顺序向外提供消息,但是,尽管服务器是按照顺序提供消息,但是消息传递到每一个consumer是异步的,这可能会导致消费的consumer获取到消息的时间可能比后消费的consumer获取到消息的时间长,导致不能保证顺序性。这表明,当进行并行消费的时候,消息在多个consumer之间可能会失去顺序性,这时候,消息系统通常会采取一种“exclusive consumer”的概念,来确保同一时间内只有一个consumer能够从队列中进行消费,但是这实际上意味着消息处理的过程中是不支持并行的。
kafka在这方面做得更好。通过Topic中并行度的概念,即partition,kafka可以同时提供顺序性保证和多个consumer同时消费时的负载均衡,实现的原理是通过将一个topic中的不同partition分配给一个consumer group中的不同consumer instance,一个partiton对应一个instance,如上图中的consumer groupA。通过这种方式,我们可以保证一个partition在同一时刻只有一个consumer instance在消费消息,从而保证顺序;虽然一个topic中有多个partition,但是一个consumer group中同时也有多个consumer instance,通过合理的分配,依然能够保证负载均衡。需要注意的是,一个consumer group中的consumer instance的数量不能比一个topic 中的partition的数量多(防止重复消费);
kafka只在partition的范围内保证消息消费的局部顺序性,不能在同一个topic中的多个partition中保证总的消费顺序性。如果需要在总体上保证消费的顺序的的需求的话,那么我们可以将topic的partition数量设置为1,将consumer group中的consumer instance数量也设置为1。
Producters
生产者将消息发送到topic中,同时负责选择将message发送到topic的哪一个partition中,如果不指定partition,则通过round-robin(轮询)做简单的负载均衡,也可以根据消息中的某一个关键字来进行区分,
Consumers
传统的消息传递模式有2种,队列(queuing)和广播(public-subscribe);在queuing中,多个consumer从服务器中读取数据,消息只会到达一个consumer,而public-subscribe模型中,消息会被广播给所有的comsumer。
kafka基于这2中模式,提供了一种comsumer的抽象概念,consumer group,每个comsumer都要标记自己属于哪一个consumer group;发布到topic中的message会被传递到consumer group中的一个comsumer实例。
consumer实例可运行在不同的进程上,也可以在不同的物理机器上。
如果所有的consumer都位于同一个consumer group下,这就类似于传统的queue模式,并在众多的consumer instance之间进行负载均衡。
如果所有的consumer都有着自己唯一的consumer group,这就类似于传统的public-subscribe模型。
更一般的情况是,通常一个topic会有几个consumer group,每个consumer group都是一个逻辑上的订阅者(logical subscriber),每个consumer group由多个consumer instance组成,从而达到可扩展和容灾的功能,这并没有什么特殊的地方,仅仅是将public-subscribe模型中的运行在当个进程上的consumer替换成一个consumer group。如下
消费顺序
kafka比传统的消息系统有着更强的顺序保证。在传统的情况下,服务器按照顺利保留消息到队列,如果有多个consumer来消费队列中的消息,服务器会按接收消息的顺序向外提供消息,但是,尽管服务器是按照顺序提供消息,但是消息传递到每一个consumer是异步的,这可能会导致消费的consumer获取到消息的时间可能比后消费的consumer获取到消息的时间长,导致不能保证顺序性。这表明,当进行并行消费的时候,消息在多个consumer之间可能会失去顺序性,这时候,消息系统通常会采取一种“exclusive consumer”的概念,来确保同一时间内只有一个consumer能够从队列中进行消费,但是这实际上意味着消息处理的过程中是不支持并行的。
kafka在这方面做得更好。通过Topic中并行度的概念,即partition,kafka可以同时提供顺序性保证和多个consumer同时消费时的负载均衡,实现的原理是通过将一个topic中的不同partition分配给一个consumer group中的不同consumer instance,一个partiton对应一个instance,如上图中的consumer groupA。通过这种方式,我们可以保证一个partition在同一时刻只有一个consumer instance在消费消息,从而保证顺序;虽然一个topic中有多个partition,但是一个consumer group中同时也有多个consumer instance,通过合理的分配,依然能够保证负载均衡。需要注意的是,一个consumer group中的consumer instance的数量不能比一个topic 中的partition的数量多(防止重复消费);
kafka只在partition的范围内保证消息消费的局部顺序性,不能在同一个topic中的多个partition中保证总的消费顺序性。如果需要在总体上保证消费的顺序的的需求的话,那么我们可以将topic的partition数量设置为1,将consumer group中的consumer instance数量也设置为1。
Guarantees
容灾,备份。
从较高的层面上来说的话,kafka提供了一下的保证:
发送到一个topic中的message会按照发送的顺序添加到commit log中,意思是,如果消息M1 M2由同一个producer发送,M1比M2发送早的话,那么在commit log中,M1的offset就会比M2的offset小;
一个consumer在commit log中可以按照发送顺序来消费message,如果一个topic的备份因子(replication factor)设置为N,那么kafka可以容忍N-1个服务器的失败,而存储在commit log中的消息不会丢失
kafka分区leader选举原理:
kafka集群,在配置的时间范围内,维护所有的由producter生成的消息,而不管这些消息有没有被消费。例如日志保留时间(log retention)时间被设置为2天,kafka会维护最近2天生产的所有消息,而2天前的消息会被丢弃。kafka的性能与保留的数据量的大小没有关系,因此保存大量的数据(日志信息)不会有什么影响。
每个consumer是基于自己在commit log中的消费进度(offset)来进行工作的,在kafka中,offset由consumer来维护,一般情况下,我们按照顺序逐条消费commit log中的消息,当然我们也可以通过指定offset来重复消费某些消息,或者跳过某些消息。这意味着kafka中的consumer对集群的影响是非常小的,添加一个或者减少一个consumer,对于集群或者其他consumer来说,都是没有影响的,因为每个consumer维护各自的offset。
对log进行分区(partitioned),有几个目的,首先,当log文件大小超过文件系统的限制时,可以自动炒粉,每个partition对应的log都受到所在机器的文件系统大小的限制,但是一个topic中是可以有多个分区的,因为可以处理任意数据的数据,其次,是为了提高并行度
Distribution
log的partitions分布在kafka集群中的不同broker上,每个broker可以请求备份其他broker上的partition数据,kafka集群支持配置一个partition备份的数量,即多个副本。
针对每个partition的多个副本(在多个broker上),都有一个broker起到 leader 的作用,其他broker作为follwers,leader处理所有针对这个partition的读写请求,而flowers被动复制leader的结果,如果这个leader失效了,其中的一个flower将自动的变成新的leader,每个broker都是自己所管理的partiton的leader,同时又是其他broker所管理partitons的flowers,kafka通过这种方式来达到负载均衡。
Producters
生产者将消息发送到topic中,同时负责选择将message发送到topic的哪一个partition中,如果不指定partition,则通过round-robin(轮询)做简单的负载均衡,也可以根据消息中的某一个关键字来进行区分.
Consumers
传统的消息传递模式有2种,队列(queuing)和广播(public-subscribe);在queuing中,多个consumer从服务器中读取数据,消息只会到达一个consumer,而public-subscribe模型中,消息会被广播给所有的comsumer。
kafka基于这2中模式,提供了一种comsumer的抽象概念,consumer group,每个comsumer都要标记自己属于哪一个consumer group;发布到topic中的message会被传递到consumer group中的一个comsumer实例。
consumer实例可运行在不同的进程上,也可以在不同的物理机器上。
如果所有的consumer都位于同一个consumer group下,这就类似于传统的queue模式,并在众多的consumer instance之间进行负载均衡。
如果所有的consumer都有着自己唯一的consumer group,这就类似于传统的public-subscribe模型。
更一般的情况是,通常一个topic会有几个consumer group,每个consumer group都是一个逻辑上的订阅者(logical subscriber),每个consumer group由多个consumer instance组成,从而达到可扩展和容灾的功能,这并没有什么特殊的地方,仅仅是将public-subscribe模型中的运行在当个进程上的consumer替换成一个consumer group。如下
kafka比传统的消息系统有着更强的顺序保证。在传统的情况下,服务器按照顺利保留消息到队列,如果有多个consumer来消费队列中的消息,服务器会按接收消息的顺序向外提供消息,但是,尽管服务器是按照顺序提供消息,但是消息传递到每一个consumer是异步的,这可能会导致消费的consumer获取到消息的时间可能比后消费的consumer获取到消息的时间长,导致不能保证顺序性。这表明,当进行并行消费的时候,消息在多个consumer之间可能会失去顺序性,这时候,消息系统通常会采取一种“exclusive consumer”的概念,来确保同一时间内只有一个consumer能够从队列中进行消费,但是这实际上意味着消息处理的过程中是不支持并行的。
kafka在这方面做得更好。通过Topic中并行度的概念,即partition,kafka可以同时提供顺序性保证和多个consumer同时消费时的负载均衡,实现的原理是通过将一个topic中的不同partition分配给一个consumer group中的不同consumer instance,一个partiton对应一个instance,如上图中的consumer groupA。通过这种方式,我们可以保证一个partition在同一时刻只有一个consumer instance在消费消息,从而保证顺序;虽然一个topic中有多个partition,但是一个consumer group中同时也有多个consumer instance,通过合理的分配,依然能够保证负载均衡。需要注意的是,一个consumer group中的consumer instance的数量不能比一个topic 中的partition的数量多(防止重复消费);
kafka只在partition的范围内保证消息消费的局部顺序性,不能在同一个topic中的多个partition中保证总的消费顺序性。如果需要在总体上保证消费的顺序的的需求的话,那么我们可以将topic的partition数量设置为1,将consumer group中的consumer instance数量也设置为1。