kafka的基本概念
- kafka特点1:是基于发布订阅模式,而非pear-pear模式,消费者可以有多个,实质是一个生产者-消费者模型,用来处理数据流。
- kafka特点2:处理数据高效并实时
- kafka特点3:数据流在分布式集群中安全复制存储
总之:kafka是用于构建实时的数据管道和流应用程序。具备横向扩展,容错等优点。
kafka名词解释
- Broker:一个kafka服务器节点就是一个Broker,消息被持久化到Broker上。broker只管数据存储,不管是谁生产,不管是谁消费。在集群中每个broker都有一个唯一brokerid,不得重复。
- Topic:消息的一个主题,每生产的一条消息都对应一个Topic,这样就可以将消息归类,消费者就可以选择性的消费了。
- producer:消息生产者,有服务端console类型的,可以在控制台输入生产消息,也有和编程语言集成的API,可以在工程中生产消息。
- consumer:消费者,和生产者类似,也有服务端console类型的,可以在控制台接收消息,也有API接口控制在项目中自己消费消息。一个消费者是一个线程。
- consumerGroup:消费者组,消费端消费消息的时候是以group为单位消费,一个topic下的消息可以被不同的group消费。以group消费是为了不同业务可以都消费消息,而且当有新增消费需求的时候,直接增加consumer group即可。
consumerGroup组员之间不能重复消费。
- partition:kafka是面对分布式系统的,同时一个topic对应partition,一个partition有多个副本,会从所有的副本中选取一个leader出来。所有读写操作都是通过leader副本来进行的。一个partition是个有序队列。
partition的目录中有多个segment组合(index,log)一个Topic对应多个partition[0,1,2,3],一个partition对应多个segment组合。一个segment有默认的大小是1G,消息都在segment上面存储。
- partition中每个message只能被consumer group中的一个consumer消费。而且一个consumergroup里面的所有consumer都必须按顺序读取partition中的message,新启动的consumer默认从partition队列的头开始阻塞得读message.
- kafka吞吐量大的原因:
- kafka针对一个partition,不是通过多个consumer thread加悲观锁来防止重复消费,而是一个partition只能同时被一个consumer thread消费,如果消息数量太大觉得效率不高要增大吞吐量,直接横向扩展partition数量,同时增加一个consumer group下的consumer thread数量即可。这样没有锁竞争,充分发挥了横向的扩展性,吞吐量极高。
- kafka分布式并发的读和写都非常快,写的性能体现在以o(1)的时间复杂度进行顺序写入。读的性能体现在以o(1)的时间复杂度进行顺序读取, 对topic进行partition分区,consume group中的consume线程可以以很高能性能进行顺序读。
效率最优配置:
consumer group下的consumer thread的数量等于partition数量,这样效率是最高的。
Consumer怎么消费kafka的topic的所有的partition的message的呢?
kafka消息是顺序读取,必须维护上一次读到哪里的offset信息。维护offset有两套机制,high level API的offset存于Zookeeper中;low level API的offset由自己维护。
- 当使用high level api的时候
offset是维护在Zookeeper上,先拿message处理,再定时自动commit offsite+1(也可以改成手动), 并且kakfa处理message是没有锁操作的。
因此如果处理message失败,此时还没有commit offsite+1,当consumer thread重启后会重复消费这个message。
但是作为高吞吐量高并发的实时处理系统,at least once的情况下,至少一次会被处理到,是可以容忍的。 - 如果无法容忍,就得使用low level api来自己程序维护这个offsite信息,那么想什么时候commit offsite+1就自己搞定了。
- 消息生产端不用维护offset,因为消息offset默认是自增的。Kafka的producer一般都是大批量的batch发送message,向这个topic一次性发送一大批message,load balance到一个partition上,一起插进去,offsite作为自增id自己增加就好。
At Least模型
因为消息的读取进度由offset提供,offset可以由消费者自己维护也可以维护在zookeeper里,但是当消息消费后consumer挂掉,
offset没有即时写回,就有可能发生重复读的情况,这种情况同样可以通过调整commit offset周期、阈值缓解,甚至消费者自己把消费和commit offset做成一个事务解决,
但是如果你的应用不在乎重复消费,那就干脆不要解决,以换取最大的性能。
consumer API
Kafka提供了两套consumer api,分为high-level api和sample-api。
- Sample-api 是一个底层的API,它维持了一个和单一broker的连接,并且这个API是完全无状态的,每次请求都需要指定offset值,因此,这套API也是最灵活的。
在kafka中,当前读到哪条消息的offset值是由consumer来维护的,因此,consumer可以自己决定如何读取kafka中的数据
。比如,consumer可以通过重设offset值来重新消费已消费过的数据。不管有没有被消费,kafka会保存数据一段时间,这个时间周期是可配置的,只有到了过期时间,kafka才会删除这些数据.
- High-level API
High level api是consumer读的partition的offsite是存在zookeeper上。High level api 会启动另外一个线程去每隔一段时间,offsite自动同步到zookeeper上。
换句话说,如果使用了High level api, 每个message只能被读一次,一旦读了这条message之后,无论我consumer的处理是否ok。
High level api的另外一个线程会自动的把offiste+1同步到zookeeper上。如果consumer读取数据出了问题,offsite也会在zookeeper上同步。
因此,如果consumer处理失败了,会继续执行下一条。因此,Best Practice是一旦consumer处理失败,直接让整个conusmer group抛Exception终止
,但是最后读的这一条数据是丢失了,因为在zookeeper里面的offsite已经+1了。
等再次启动conusmer group的时候,已经从下一条开始读取处理了。
- Low level API
consumer读的partition的offsite在consumer自己的程序中维护。不会同步到zookeeper上。
但是为了kafka manager能够方便的监控,一般也会手动的同步到zookeeper上。
kafka如何保证数据的完全生产
ack机制:broker表示发来的数据已确认接收无误,表示数据已经保存到磁盘。
- 0:不等待broker返回确认消息
- 1:等待topic中某个partition leader保存成功的状态反馈
- -1:等待topic中某个partition 所有副本都保存成功的状态反馈
kafka生产的Log
摘录了一下大神的博客,如下:
kafka的选举机制
- 首先Kafka会将接收到的消息分区(partition),每个主题(topic)的消息有不同的分区。
这样一方面消息的存储就不会受到单一服务器存储空间大小的限制,另一方面消息的处理也可以在多个服务器上并行。 - 其次为了保证高可用,每个分区都会有一定数量的副本(replica)。这样如果有部分服务器不可用,副本所在的服务器就会接替上来,保证应用的持续性。
但是,为了保证较高的处理效率,消息的读写都是在固定的一个副本上完成。这个副本就是所谓的Leader,而其他副本则是Follower。而Follower则会定期地到Leader上同步数据。