zookeeper,kafka的复习内容

Kafka的特性如下:

1)高吞吐、低延迟:Kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分为多个partition,consumer group对partition进行consumer操作。

2)可扩展性:Kafka集群支持热扩展。

3)持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失。

4)容错性:允许集群中节点失败。

高并发:支持数千个客户端同时读写。

Kafka设计思想

2.1 Kafka broker leader选举:Kafka broker集群受zookeeper管理。所有的Kafka broker节点一起去zookeeper上注册一个临时系欸但,因为只有一个Kafka broker会注册成功,其他的都会失败,所以这个成功在zookeeper上注册临时节点的这个Kafka broker会成为Kafka broker controller,其他的Kafka broker称为Kafka broker follower。这个controller会监听其他的Kafka broker的所有信息,如果这个Kafka broker controller宕机了,在zookeeper上面的那个临时节点就会消失,此时所有的Kafka broker又会一起去zookeeper上注册一个临时节点,只有一个会成功。

2.2 consumer group:各个consumer(consumer线程)可以组成一个组(consumer group),partition中的每个message只能被组中的一个consumer消费,如果一个message可以被多个consumer消费的话,那么这些consumer必须在不同的组。Kafka不支持一个partition中的message由两个或两个以上的同一个consumer group下的consumer thread来处理。这里的多个consumer的消费都必须是顺序读取partition里面的message,新启动的consumer默认从partition队列最头端最新的地方开始阻塞的读message。Kafka为了保证吞吐量,只允许同一个consumer group下的一个consumer线程去访问一个partition。如果觉得效率不够高,可以加partition的数量来横向扩展,再添加新的consumer thread去消费。如果多个不同业务都需要这个topic的数据,起多个consumer group,都顺序读取message,offset的值互不影响。这样没有锁竞争,充分发挥了横向的扩展性,吞吐量极高。

当启动一个consumer group去消费一个topic的时候,无论topic里面有多少个partition,这个consumer group下面的所有consumer thread一定会消费所有的partition。

2.3 consumer:consumer处理partition里面的message的时候是顺序读取的。所以必须维护着上一次读到哪里的offset信息。high level API,offset存于zookeeper中,low level API的offset由自己维护。一般来说都是使用high level api的。comsumer的delivery gurantee,默认是读完message先commit再处理message,autocommit默认是true,这时候先commit就会更新offset+1,一旦处理失败,offset已经+1,这个时候就会丢失message;也可以配置成读完消息处理再commit,这种情况下consumer端的响应就会比较慢,需要等处理完才行。

一般情况下,一定是一个consumer group处理一个topic的message。best practice是这个consumer group里面的consumer的数据等于topic里面partition的数量,这样效率是最高的,一个consumer thread处理一个partition。如果这个consumer group里面的consumer数量小于topic里面的partition的数量,就会有consumer thread同时处理多个partition(这个是Kafka自动的机制,我们不用指定),但是总之这个topic里面的所有partition都会被处理到。同一个consumer group下的consumer不能处理同一个patition,不同的consumer group可以处理同一个topic,一定会处理重复的。一般这种情况是两个不同的业务逻辑,才会启动两个consumer group来处理一个topic。

2.4 Delivery Mode:kafka producer发送message不用维护offset信息,因为这个时候offset就相当于一个自增id,producer就尽管发送message就好了。而且Kafka与AMQ不同,AMQ大都用在处理业务逻辑上,而Kafka大都是日志,所以Kafka的producer一般都是大批量batch发送message,向这个topic一次性发送一大批message,load balance到一个partition上。

2.5 topic&partition:topic相当于传统消息系统MQ中的一个队列queue,producer端发送的message必须指定是发送到哪个topic,但是不需要指定topic下的哪个partition,因为kafka会把收到的message进行load balance,均匀的分布在这个topic下的不同的partition。物理存储上,这个topic会分成一个或多个partition,每个partition相当于是一个子queue。在物理结构上,每个partiton对应一个物理的目录(文件夹),文件夹命名是[topicname]_[partition]_序号,一个topic可以有无数多的partition,根据业务需求和数据量来设置。在kafka配置文件中可随之更改num.partitons参数来配置更改topic的partition数量,在创建topic时通过参数指定partition数据。topic创建后通过kafka提供的工具也可以修改partition数量。一般来说,一个topic的partition数量大于等于Broker的数量,可以提高吞吐率;同一个partition的replica尽量分散到不同的机器,高可用。

当新增一个partition的时候,partition里面的message不会重新进行分配,原来的partition里面的message数据不会变,新增加的这个partition刚开始是空的,随后进入这个topic的message就会重新参与所有partition的load balance。

partiton replica:每个partition可以在其他的kafka broker节点上存副本,以便某个kafka broker节点宕机不会影响这个kafka集群。存replica副本的方式是按照kafka broker的顺序存。例如有5个kafka broker节点,某个topic有3个partition,每个partition存2个副本,那么partition1存broker1、broker2,partition2存broker2、broker3…..以此类推。(replica副本数目不能大于kafka broker节点的数目,否则报错。)这样如果某个broker宕机,其实整个kafka内数据依然是完整的。但是,replica副本数越高,系统算然越稳定,但是带来资源和性能上的下降;replica副本少的画,也会造成系统丟数据的风险。

1)怎样传送消息:producer先把message发送到partition leader,再由leader发送给其他partition follower;

2)在想producer发送ack前需要保证有多少个replica已经收到该消息:根据ack配的个数而定

3)怎样处理某个replica不工作的情况;如果这个不工作的partition re在ack列表中的话,producer发送的message的时候会等待这个不工作的partition replica写message成功,但是会等到time out,然后返回失败因为某个ack列表中的partition replica没有响应,此时kafka会自动的把这个不工作的partition replica从ack列表中移除,以后的producer发送message的时候就不会有这个ack列表下的这个不工作的partition replica了。

4)怎样处理failed replica恢复回来的情况:如果这个partition replica之前不在ack列表中,那么启动后重新受Zookeeper管理即可,之后producer发送message的时候,partition leader会继续发送message到这个parition follower上。

partition leader与follower:partition也有leader和follower之分。leader是主partition,producer写kafka的时候先写partition leader,再由partition leader push给其他的partitionfollower.partition leader与follower的信息受zookeeprt控制,一旦partition leader所在的broker节点宕机,zookeeper会在其他的broker的partition follower上选择follower变为partition leader.

2.6 topic分配partition和partition replica的算法:1.将broker(size=n)和待分配的partition排序;2.将第i个partition分配到第(i%n)个broker上;3.将第i个partition的第j个replica分配到(i+j)%n个broker上。

2.7 消息投递可靠性:一个消息如何算投递成功,Kafka提供了三种模式:第一种是什么也不管,发出去就当作成功,不能保证消息成功投递到broker。

2.8 partition ack:当ack=1,表示producer写partition leader成功后,broker就返回成功,无论其他的partition follower是否写成功。当ack=2,表示producer写partition leader和其他一个follower成功的时候,broker就返回成功,无论其他的partition follower是否写成功。当ack=-1(或partition数量)的时候,表示只有producer全部写成功的时候,才算成功。这里需要注意的是,当ack=1,一旦有broker宕机导致partition的follower和leader切换,会导致丢数据。

2.9 message持久化:Kafka会把消息持久化到本地文件系统中,并且保持极高的效率。众所周知IO读取是非常耗资源的、性能最慢的,这也是为什么数据的瓶颈经常在io上,需要换SSD硬盘的原因。但是Kafka作为吞吐量极高的MQ,却可以非常高效的将message持久化到文件。这是因为Kafka是顺序写入的时间复杂度,速度非常快,也是高吞吐量的原因。由于message的写入持久化是顺序写入,因此message在被消费的时候也是按顺序被消费的,保证partition的message是顺序消费的。

2.10 push and pull:Kafka中的producer和consumer采用的是push and pull模式,即producer只管向broker push消息,consumer只管从broker pull消息,两者对消息的产生和消费是异步的。

2.11 实时数据和离线数据:Kafka既支持离线数据也支持实时数据,因为Kafka的message持久化到文件,并且可以设置有效期,因此可以把Kafka作为一个高效的存储来使用,可以作为离线数据供后面的分析。当然作为分布式实时消息系统,大多数情况下开始用于实时的数据处理的,但是当consumer消费能力下降的时候可以通过message的持久化到文件再淤积数据在Kafka。

Kafka文件存储机制

3.1持久化:Kafka使用文件存储消息,这就直接决定Kafka在性能上严重依赖文件系统的本身特性。且无论在任何OS下,对文件系统本身的优化是非常艰难的。文件缓存/直接映射等是常见的手段。因为Kafka是对日志文件进行append操作,因此磁盘检索的开支是较小的;同时为了减少磁盘写入的次数,broker会将消息暂时buffer起来,当消息的个数达到一定阈值时,再flush到磁盘,这样减少了磁盘io调用的次数。对于Kafka而言,较高性能的磁盘,将会带来更加直接的性能提升。

3.2性能:除磁盘IO之外,我们还需要考虑网络IO,这直接关系到Kafka的吞吐量问题。Kafka并没有提供太多高超的技巧;对于producer端,可以将消息buffer起来,当消息的条数达到一定阈值时,批量发送给broker;对于consumer端也是一样,批量fetch多条消息。不过消息量的大小可以通过配置文件来指定。对于consumer端也是一样,批量fetch多条消息。不过消息量的大小可以通过配置文件来指定。其实对于producer/consumer/broker三者而言,CPU的开支应该都不大,因此启用消息压缩机制是一个良好的策略。压缩需要消耗少量的cpu资源,不过对于Kafka而言,网络IO更应该需要考虑。可以将任何在网络上传输的消息都经过压缩。Kafka支持gzip/snappy等多种压缩方式。

3.3 消息传输一致:Kafka提供3中消息传输一致性语义:最多一次、最少一次、恰好一次

at most once:消费者fetch消息,然后保存offset,然后处理消息;当client保存offset之后,但是在消息处理过程中consumer进程失效(crash),导致部分消息未能继续处理。那么此后可能其他consumer会接管,但是因为offset已经提前保存,那么新的consumer将不能fetch到offset之前的消息。

at least once:消费者fetch消息,然后处理消息,然后保存offset。如果消息处理成功之后,但是在保存offset阶段zookeeper异常或者consumer失效,导致保存offset操作未能执行成功,这就导致接下来再次fetch时可能获得上次已经处理过的消息。

exactly once:最少1次+消费者的输出中额外增加已处理消息最大编号:由于已处理消息最大编号的存在,不会出现重复处理消息的情况。





猜你喜欢

转载自blog.csdn.net/m0_37847176/article/details/80015328
今日推荐