Kafka 术语与重要配置
kafka (一)术语与重要配置
切记:聪明人要下死功夫!
Apache Kafka 是一款开 源的消息引擎系统。
术语
在 Kafka 中,发布订阅的对象是主题(Topic),你可以为每 个业务、每个应用甚至是每类数据都创建专属的主题。
向主题发布消息的客户端应用程序称为生产者(Producer),生产者程序通常持续不断地 向一个或多个主题发送消息,
而订阅这些主题消息的客户端应用程序就被称为消费者 (Consumer)。和生产者类似,消费者也能够同时订阅多个主题的消息。
我们把生产者和 消费者统称为客户端(Clients)。可以同时运行多个生产者和消费者实例,这些实例会不断地向 Kafka 集群中的多个主题生产和消费消息。
有客户端自然也就有服务器端。Kafka 的服务器端由被称为 Broker 的服务进程构成,即一 个 Kafka 集群由多个 Broker 组成,Broker 负责接收和处理客户端发送过来的请求,以及 对消息进行持久化。虽然多个 Broker 进程能够运行在同一台机器上,但更常见的做法是将 不同的 Broker 分散运行在不同的机器上,这样如果集群中某一台机器宕机,即使在它上面 运行的所有 Broker 进程都挂掉了,其他机器上的 Broker 也依然能够对外提供服务。这其 实就是 Kafka 提供高可用的手段之一。
实现高可用的另一个手段就是备份机制(Replication)。备份的思想很简单,就是把相同的数据拷贝到多台机器上,而这些相同的数据拷贝在 Kafka 中被称为副本(Replica)。副本的数量是可以配置的,这些副本保存 着相同的数据,但却有不同的角色和作用。Kafka 定义了两类副本:领导者副本(Leader Replica)和追随者副本(Follower Replica)。前者对外提供服务,这里的对外指的是与 客户端程序进行交互;而后者只是被动地追随领导者副本而已,不能与外界进行交互。
副本的工作机制也很简单:生产者总是向领导者副本写消息;而消费者总是从领导者副本读 消息。至于追随者副本,它只做一件事:向领导者副本发送请求,请求领导者把最新生产的 消息发给它,这样它能保持与领导者的同步。
kafaka的伸缩性问题 主要采用分区的方法。Kafka 中的分区机制指的是将每个主题划分成多个分区(Partition),每个分区是一组有序的消息日志。生产者生产的每条消息只会被发送到一个分区中,也就是说如果向一个双分 区的主题发送一条消息,这条消息要么在分区 0 中,要么在分区 1 中。Kafka 的分区编号是从 0 开始的,如果 Topic 有 100 个分区,那么它们的分区号就是从 0 到 99。
副本和分区的联系:副本是在分区这个层级定义的。每个分区下可以配置若干个副本,其中只能有 1 个领 导者副本和 N-1 个追随者副本。生产者向分区写入消息,每条消息在分区中的位置信息由 一个叫位移(Offset)的数据来表征。分区位移总是从 0 开始,假设一个生产者向一个空 分区写入了 10 条消息,那么这 10 条消息的位移依次是 0、1、2、…、9。
总结: Kafka 的三层消息架构:
第一层是主题层,每个主题可以配置 M 个分区,而每个分区又可以配置 N 个副本。
第二层是分区层,每个分区的 N 个副本中只能有一个充当领导者角色,对外提供服务; 其他 N-1 个副本是追随者副本,只是提供数据冗余之用。
第三层是消息层,分区中包含若干条消息,每条消息的位移从 0 开始,依次递增。
最后,客户端程序只能与分区的领导者副本进行交互。
Kafka 使用消息日志(Log)来保存数据,一个日志就是磁盘上一个只能追加写(Append-only)消息的物理文件。因为只能追加写入,故避免了缓慢的随机 I/O 操作,改为性能较好的顺序 I/O 写操作,这也是实现 Kafka 高吞吐量特性的一个重要手段。
不过如果你不停地向一个 日志写入消息,最终也会耗尽所有的磁盘空间,因此 Kafka 必然要定期地删除消息以回收 磁盘。简单来说就是通过日志段(Log Segment)机制来进行删除。在 Kafka 底层,一 个日志又近一步细分成多个日志段,消息被追加写到当前最新的日志段中,当写满了一个日志段后,Kafka 会自动切分出一个新的日志段,并将老的日志段封存起来。Kafka 在后台还有定时任务会定期地检查老的日志段是否能够被删除,从而实现回收磁盘空间的目的。
kafka中引入了消费者组的概念,所谓的消费者组,指的是多个消费者实例共同组成一个组来 消费一组主题。这组主题中的每个分区都只会被组内的一个消费者实例消费,其他消费者实 例不能消费它。为什么要引入消费者组呢?主要是为了提升消费者端的吞吐量。多个消费者 实例同时消费,加速整个消费端的吞吐量(TPS)。另外这里的消费者实例可以是运行消 费者应用的进程,也可以是一个线程,它们都称为一个消费者实例(Consumer Instance)。
消费者组里面的所有消费者实例不仅“瓜分”订阅主题的数据,而且它们还能彼此协助。假设组内某个实例挂掉了,Kafka 能够自动检测到,然后把这个 Failed 实例之前负 责的分区转移给其他活着的消费者。这个过程就是 Kafka 中大名鼎鼎的“重平 衡”(Rebalance)。
每个消费者在消费消息的过程中必然需要有个字段记录它当前消费到了分区的哪个位置上, 这个字段就是消费者位移(Consumer Offset)。注意,这和上面所说的位移完全不是一 个概念。上面的“位移”表征的是分区内的消息位置,它是不变的,即一旦消息被成功写入 到一个分区上,它的位移值就是固定的了。而消费者位移则不同,它可能是随时变化的,毕 竟它是消费者消费进度的指示器嘛。另外每个消费者有着自己的消费者位移,因此一定要区 分这两类位移的区别。通常把消息在分区中的位移称为分区位移,而把消费者端的位移称 为消费者位移。
同一时刻,一条消息只能被组中的一个消费者实例消费
消费者组订阅这个主题,意味着主题下的所有分区都会被组中的消费者消费到,如果按照从属关系来说的话就是,主题下的每个分区只从属于组中的一个消费者,不可能出现组中的两个消费者负责同一个分区。
那么,问题来了。如果分区数大于或者等于组中的消费者实例数,那自然没有什么问题,无非一个消费者会负责多个分区,(PS:当然,最理想的情况是二者数量相等,这样就相当于一个消费者负责一个分区);但是,如果消费者实例的数量大于分区数,那么按照默认的策略(PS:之所以强调默认策略是因为你也可以自定义策略),有一些消费者是多余的,一直接不到消息而处于空闲状态。
话又说回来,假设多个消费者负责同一个分区,那么会有什么问题呢?
我们知道,Kafka它在设计的时候就是要保证分区下消息的顺序,也就是说消息在一个分区中的顺序是怎样的,那么消费者在消费的时候看到的就是什么样的顺序,那么要做到这一点就首先要保证消息是由消费者主动拉取的(pull),其次还要保证一个分区只能由一个消费者负责。倘若,两个消费者负责同一个分区,那么就意味着两个消费者同时读取分区的消息,由于消费者自己可以控制读取消息的offset,就有可能C1才读到2,而C1读到1,C1还没处理完,C2已经读到3了,则会造成很多浪费,因为这就相当于多线程读取同一个消息,会造成消息处理的重复,且不能保证消息的顺序,这就跟主动推送(push)无异。
总结
一个消费者可以消费一个topic下的多个分区,但是一个topic下的分区不能被一个消费者组的多个消费者消费。
重要配置
Broker端参数
1 | log.dirs:非常重要的参数,指定了Broker需要使用的若干个文件目录路径。没有默认值。 |
zk负责协调管理并保存 Kafka 集群的所有元数据信息,比如集群都有哪些 Broker 在运行、创建了哪些 Topic,每个 Topic 都有多少分区以及这些分区的 Leader 副本都在哪些机器上等信息。
1 | zookeeper相关配置 |
1 | 与Broker连接相关的,即客户端或其他broker 如何与该broker进行通信的设置。 |
1 | topic管理类 |
1 | 数据留存方面 |
Topic级别参数
Topic 级别参数会覆盖全局 Broker 参数的值,而每个 Topic 都能设置自己的参数值。
1 | retention.ms 规定了该Topic消息被保存的时长,默认7天,即该 Topic 只保存最近 7 天的消息。一旦 设置了这个值,它会覆盖掉 Broker 端的全局参数值。 |
Author: corn1ng
Link: https://corn1ng.github.io/2019/10/01/kafka/kafka1术语与重要配置/
License: 知识共享署名-非商业性使用 4.0 国际许可协议