大数据之kafka-02.搞定kafka专业术语

02.搞定kafka专业术语

在kafka的世界中有不少概念和术语是须要咱们提早理解而且熟练掌握的,下面来盘点一下。mysql

以前咱们提到过,kafka属于分布式的消息引擎系统,主要功能是提供一套完善的消息发布与订阅方案。在kafka中,发布订阅的对象是主题(topic),能够为每一个业务、每一个应用、甚至是每一类数据都建立专属的主题。sql

向主题发布消息的客户端应用程序成为生产者(producer),生产者一般持续不断地向一个或多个主题发送消息,而订阅这些主题获取消息的客户端应用程序就被称之为消费者(consumer)。和生产者相似,消费者也能同时订阅多个主题。咱们把生产者和消费者统称为客户端(clients)。你能够同时运行多个生产者和消费者实例,这些实例不断地向kafka集群中的多个主题生产和消费消息。数据库

有客户端天然也就有服务端。kafka的服务器端由被称为broker的服务进程构成,即一个kafka集群由多个broker组成,broker负责接收和处理客户端发来的请求,以及对消息进行持久化。虽然多个broker进程可以运行在同一台机器上,但更常见的作法是将不一样的broker分散运行在不一样的机器上。这样即使集群中的某一台机器宕机,运行在其之上的broker进程挂掉了,其余机器上的broker也依旧能对外提供服务。这其实就是kafka提供高可用的手段之一。服务器

在实现高可用的另外一个手段就是备份机制(replication)。备份的思想很简单,就是把相同的数据拷贝到多台机器上,而这些相同的数据拷贝就叫作副本(replica)。副本的数量是能够配置的,这些副本保存着相同的数据,但却有不一样的角色和做用。kafka定义了两种副本,领导者副本(leader replica)和追随者副本(follower replica)。前者对外提供服务,这里的对外指的是与客户端进行交互;然后者只是被动地追随领导者副本而已,不与外界进行交互。固然了,不少其余系统中追随者副本是能够对外提供服务的,好比mysql,从库是能够处理读操做的,也就是所谓的"主写从读",可是在kafka中追随者副本不会对外提供服务,至于为何咱们做为思考题解答。对了,关于领导者--追随者,以前实际上是叫作主(master)--从(slave),可是不建议使用了,由于slave有奴隶的意思,政治上有点不合适,因此目前大部分的系统都改为leader-follower了。架构

副本的工做机制很简单:生产者向主题写的消息老是往领导者那里,消费者向主题获取消息也都是来自于领导者。也就是不管是读仍是写,针对的都是领导者副本,至于追随者副本,它只作一件事情,那就是向领导者副本发送请求,请求领导者副本把最新生产的消息发送给它,这样便可以保持和领导者的同步。app

虽然有了副本机制能够保证数据的持久化或者数据不丢失,但没有解决伸缩性的问题。伸缩性即所谓的scalability,是分布式系统中很是重要且必须谨慎对待的问题。什么事伸缩性呢?咱们拿副原本说,虽然如今有了领导者副本和追随者副本,但假若领导者副本积累了太多的数据以致于单台broker都没法容纳了,此时应该怎么办?有个很天然的想法就是,可否把数据分割成多分保存在不一样的broker上?没错,kafka就是这么设计的。负载均衡

这种机制就是所谓的分区(partition)。若是了解其余的分布式系统,那么可能据说过度片、分区域等提法,好比MongoDB和ElasticSearch中的sharding、Hbase中的region,其实它们都是相同的原理,只是partition是最标准的名称。分布式

kafka中的分区机制指定的是将每一个主题划分为多个分区,每一个分区都是一组有序的消息日志。生产者生产的每一条消息只会被发到一个分区中,也就说若是向有两个分区的主题发送一条消息,那么这条消息要么在第一个分区中,要么在第二条分区中。而kafka的分区编号是从0开始的,若是某个topic有100个分区,那么它们的分区编号就是从0到99。性能

到这里可能会有疑问,那就是刚才提到的副本如何与这里的分区联系在一块儿呢?实际上,副本是在分区这个层级定义的。每一个分区下能够配置若干个副本,其中只能有1个领导者副本和N-1个追随者副本。生产者向分区写入消息,每条消息在分区中的位置由一个叫位移(offset)的数据来表征。分区位移老是从0开始,假设一个生产者向一个空分区写入了10条消息,那么这10条消息的位移依次是0、一、二、...、9。spa

至此咱们能完整地串联起kafka的三层消息架构

  • 第一层是主题层,每一个主题能够配置M个分区,每一个分区又能够配置N个副本
  • 第二层是分区层,每一个分区的N个副本中只能有一个副原本充当领导者角色,对外提供服务;其余的N-1个副本只是追随者副本,用来提供数据冗余之用。
  • 第三层是消息层,分区中包含若干条消息,每条消息的位移从0开始,依次递增。
  • 最后客户端程序只能与分区的领导者副本进行交互

那么kafka是如何持久化数据的呢?总的来讲,kafka使用消息日志(log)来保存数据,一个日志就是磁盘上一个只能追加写(append-only)消息的物理文件。由于只能追加写入,故避免了缓慢的随机I/O操做,改成性能较好的顺序I/O操做,这也是实现kafka高吞吐量特性的一个重要手段。不过若是不停地向一个日志写入消息,最终也会耗尽全部的磁盘空间,所以kafka必然要按期地删除消息以回收磁盘。怎么删除?简单来讲就是经过日志段(log segment)机制。在kafka底层,一个日志又进一步细分红多个日志段,消息被追加写到当前最新的日志段中,当写满了一个日志段后,kafka会自动切分出一个新的日志段,并将老的日志段封存起来。kafka在后台还有定时任务会按期地检查老的日志段是否可以被删除,从而实现回收磁盘的目的。

这里再重点说一下消费者,以前说过有两种消息模型,即点对点模型(peer to peer, p2p)和分布订阅模型。这里面的点对点指的是同一条消息只能被下游的一个消费者消费,其余消费者不能染指。在kafka中实现这种p2p模型的方法就是引入了消费者组(consumer group)。所谓的消费者组,指的是多个消费者实例共同组成一个组来消费一个主题。这个主题中的每一个分区都只会被消费者组里面的一个消费者实例消费,其余消费者实例不能消费它。为何要引入消费者组呢?主要是为了提高消费者端的吞吐量,多个消费者实例同时消费,加速了整个消费端的吞吐量(TPS)。关于消费者组的机制,后面会详细介绍,如今只须要知道消费者组就是多个消费者组成一个组来消费主题里面的消息、而且消息只会被组里面的一个消费者消费便可。此外,这里的消费者实例能够是运行消费者应用的进程,也能够是一个线程,它们都称为一个消费者实例(consumer instance)。

消费者组里面的消费者不只瓜分订阅主题的数据,并且更酷的是它们还能彼此协助。假设组内某个实例挂掉了,kafka可以自动检测,而后把这个Failed实例以前负责的分区转移给其余活着的消费者。这个过程就是大名鼎鼎的"重平衡(rebalance)"。嗯,其实便是大名鼎鼎,也是臭名昭著,由于由重平衡引起的消费者问题比比皆是。事实上,目前不少重平衡的bug,整个社区都无力解决。

每一个消费者在消费消息的过程当中,必然须要有个字段记录它当前消费到了分区的哪一个位置上,这个字段就是消费者位移(consumer offset)。注意,咱们以前说一个主题能够有多个分区、每一个分区也是用位移来表示消息的位置。可是这两个位移彻底不是一个概念,分区位移表示的是分区内的消息位置,它是不变的,一旦消息被成功写入一个分区上,那么它的位置就是固定了的。而消费者位移则不一样,它多是随时变化的,毕竟它是消费者消费进度的指示器嘛。另外每一个消费者都有着本身的消费者位移,所以必定要区分这两类位移的区别。一个是分区位移,另外一个是消费者位移。

小结:

  • 生产者,producer向主题发布新消息的应用程序
  • 消费者,consumer从主题订阅新消息的应用程序
  • 消息,recordkafka是消息引擎,这里的消息就是指kafka处理的主要对象
  • 主题,topic主题是承载消息的逻辑容器,在实际使用中多用来区分具体的业务,即不一样的业务对应不一样的主题。
  • 分区,partition一个有序不变的消息序列,每一个主题下能够有多个分区。分区编号从0开始,分布在不一样的broker上面,实现发布于订阅的负载均衡。生产者将消息发送到主题下的某个分区中,以分区偏移(offset)来标识一条消息在一个分区当中的位置(惟一性)
  • 分区位移,offset表示分区中每条消息的位置信息,是一个单调递增且不变的值
  • 副本,replicakafka中同一条数据可以被拷贝到多个地方以提供数据冗余,这即是所谓的副本。副本还分为领导者副本和追随者副本,各自有各自的功能职责。读写都是针对领导者副原本的,追随者副本只是用来和领导者副本进行数据同步、保证数据冗余、实现高可用。
  • 消费者位移,consumer offset表示消费者消费进度,每一个消费者都有本身的消费者位移
  • 消费者组,consumer group多个消费者实例共同组成的一个组,同时消费多个分区以实现高吞吐。
  • 重平衡,rebalance消费者组内某个消费者实例挂掉以后,其它消费者实例自动从新分配订阅主题分区的过程。重平衡是kafka消费者端实现高可用的重要手段

思考:为何kafka不像mysql那样支持主写从读呢?

由于kafka的主题已经被分为多个分区,分布在不一样的broker上,而不一样的broker又分布在不一样的机器上,所以从某种角度来讲,kafka已经实现了负载均衡的效果。不像mysql,压力都在主上面,因此才要从读;另外,kafka保存的数据和数据库的数据有着实质性的差异,kafka保存的数据是流数据,具备消费的概念,并且须要消费者位移。因此若是支持从读,那么消费端控制offset会更复杂,并且领导者副本同步到追随者副本须要时间的,会形成数据不一致的问题;另外对于生产者来讲,kafka是能够经过配置来控制是否等待follower对消息确认的,若是支持从读的话,那么也须要全部的follower都确认了才能够回复生产者,形成性能降低,并且follower出现了问题也很差处理。

相关文章
相关标签/搜索