Kafka笔记

(1) Producer : 生产者,也就是发送消息的一方。生产者负责创建消息, 然后将其投递到Kafka 中。
(2) Consumer:消费者,也就是接收消息的一方。消费者连接到Kafka 上并接收消息,进而进行相应的业务逻辑处理。
(3) Broker :服务代理节点。对于Kafka 而言, Broker 可以简单地看作一个独立的Kafka服务节点或Kafka 服务实例。大多数情况下也可以将Broker 看作一台Kafka 服务器,前提是这台服务器上只部署了一个Kafka 实例。一个或多个Broker 组成了一个Kafka 集群。Broker接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。broker为消费者提供服务,对读取分区的请求作出响应,返回已经提交到磁盘上的消息。偏移量是另一种元数据,是个不断递增的整数值,添加在消息里,每个分区里消息的偏移量都唯一。

在Kafka 中还有两个特别重要的概念一一主题( Topic )与分区( Partition )。Kafka 中的消息以主题为单位进行归类,生产者负责将消息发送到特定的主题(发送到Kafka 集群中的每一条消息都要指定一个主题),而消费者负责订阅主题并进行消费。

主题是一个逻辑上的概念,它还可以细分为多个分区,一个分区只属于单个主题,很多时候也会把分区称为主题分区( Topic-Partition )。同一主题下的不同分区包含的消息是不同的,分区在存储层面可以看作一个可追加的日志( Log )文件,消息在被追加到分区日志、文件的时候都会分配一个特定的偏移量( offset )。offset 是消息在分区中的唯一标识, Kafka 通过它来保证消息在分区内的顺序性,不过offset 并不跨越分区,也就是说, Kafka 保证的是分区有序而不是主题有序

Kafka 为分区引入了多副本( Replica ) 机制, 通过增加副本数量可以提升容灾能力。同一分区的不同副本中保存的是相同的消息(在同一时刻,副本之间并非完全一样),副本之间是“ 一主多从”的关系,其中leader 副本负责处理读写请求, follower 副本只负责与leader 副本的消息同步。副本处于不同的broker 中,当leader 副本出现故障时,从follower 副本中重新选举新的leader 副本对外提供服务。Kafka 通过多副本机制实现了故障的自动转移,当Kafka 集群中某个broker 失效时仍然能保证服务可用。

分区中的所有副本统称为AR ( Assigned Replicas ) 。所有与leader 副本保持一定程度同步的副本(包括leader 副本在内〕组成ISR On-Sync Replicas ) , ISR 集合是AR 集合中的一个子集。消息会先发送到leader 副本,然后follower 副本才能从leader 副本中拉取消息进行同步,同步期间内follower 副本相对于leader 副本而言会有一定程度的滞后。前面所说的“ 一定程度
的同步”是指可忍受的滞后范围,这个范围可以通过参数进行配置。与leader 副本同步滞后过多的副本(不包括leader 副本)组成OSR ( Out-of-Sync Replicas ),由此可见, AR=ISR+OSR 。在正常情况下, 所有的follower 副本都应该与leader 副本保持一定程度的同步,即AR=ISR,
OSR 集合为空。

Kafka 消费端也具备一定的容灾能力。Consumer 使用拉( Pull )模式从服务端拉取消息,并且保存消费的具体位置, 当消费者看机后恢复上线时可以根据之前保存的消费位置重新拉取需要的消息进行消费,这样就不会造成消息丢失。

  • 使用场景
  1. 活动跟踪
  2. 传递消息
  3. 度量指标和日志记录
  4. 提交日志
  5. 流处理

Kafka安装指南

磁盘写入速度越快,生成消息的延迟就越低。

网络吞吐量决定了Kafka能够处理的最大数据流量。

运行Kafka的JVM不需要太大内存,剩余系统内存可以做页面缓存提高读取速度。

CPU要求不太高。

 

发送消息

  • 发后即忘

它只管往Kafka 中发送消息而并不关心消息是否正确到达。在大多数情况下,这种发送方式没有什么问题, 不过在某些时候( 比如发生不可重试异常时〉会造成消息的丢失。这种发送方式的性能最高,可靠性也最差。

  • 同步

同步发送的方式可靠性高,要么消息被发送成功,要么发生异常。如果发生异常,则可以捕获并进行相应的处理,而不会像“发后即忘”的方式直接造成消息的丢失。不过同步发送的方式的性能会差很多,需要阻塞等待一条消息发送完之后才能发送下一条。

  • 异步

一般是在send()方法里指定一个Callback 的回调函数,Kafka 在返回响应时调用该函数来实现异步的发送确认使用Callback 的方式非常简洁明了, Kafka 有响应时就会回调, 要么发送成功,要么抛出异常。

StringSerializer序列化

  1. configure方法确定编码类型
  2. serialize方法将String 类型转为byte[ ]类型

如果Kafka 客户端提供的几种序列化器都无法满足应用需求,则可以选择使用如Avro 、JSON 、Thri鱼、ProtoBuf 和Protos阳ff 等通用的序列化工具来实现, 或者使用自定义类型的序列化器来实现。

分区器

消息在通过send ()方法发往broker的过程中, 有可能需要经过拦截器(Interceptor)、序列化器(Serializer )和分区器(Partitioner)的一系列作用之后才能被真正地发往broker 。拦截器一般不是必需的,而序列化器是必需的。消息经过序列化之后就需要确定它发往的分区,如果消息ProducerRecord 中指定了partition字段,那么就不需要分区器的作用,因为partition代表的就是所要发往的分区号。

如果key 不为null ,那么默认的分区器会对key 进行哈希(采用MurmurHash2 算法,具备高运算性能及低碰撞率),最终根据得到的哈希值来计算分区号, 拥有相同key 的消息会被写入同一个分区。如果key 为null ,那么消息将会以轮询的方式发往主题内的各个可用分区,会是所有分区中的任意一个。

生产者拦截器

生产者拦截器既可以用来在消息发送前做一些准备工作, 比如按照某个规则过滤不符合要求的消息、修改消息的内容等, 也可以用来在发送回调逻辑前做一些定制化的需求,比如统计类工作。

onSend()方法来对消息进行相应的定制化操作。

KafkaProducer 会在消息被应答( Acknowledgement )之前或消息发送失败时调用生产者拦截器的onAcknowledgement()方法,优先于用户设定的Callback 之前执行。这个方法运行在Producer 的I/O 线程中,所以这个方法中实现的代码逻辑越简单越好, 否则会影响消息的发送速度。

close()方法主要用于在关闭拦截器时执行一些资源的清理工作。

整体架构

整个生产者客户端由两个线程协调运行,这两个线程分别为主线程Sender线程(发送线程)。在主线程中由KafkaProd ucer创建消息,然后通过可能的拦截器、序列化器和分区器的作用之后缓存到消息累加器(RecordAccumulator,也称为消息收集器)中。Sender线程负责从RecordAccumulator中获取消息并将其发送到Kafka中。

RecordAccumulator 主要用来缓存消息以便Sender 线程可以批量发送,进而减少网络传输的资源消耗以提升性能。如果生产者发送消息的速度超过发送到服务器的速度,则会导致生产者空间不足,这个时候KafkaProducer 的send()方法调用要么被阻塞,要么抛出异常。

Sender 从RecordAccumulator 中获取缓存的消息之后,会进一步将原本<分区, Deque<Producer Batch>>的保存形式转变成<Node, List< ProducerBatch>的形式,其中Node 表示Kafka集群的broker 节点。在转换成<Node, List<ProducerB atch>>的形式之后, Sender 还会进一步封装成<Node,Request>的形式,这样就可以将Request 请求发往各个Node了。请求在从Sender 线程发往Kafka 之前还会保存到InF lightRequests 中, InFlightRequests 保存对象的具体形式为Map<Nodeld, Deque<Request>>,它的主要作用是缓存了已经发出去但还没有收到响应的请求。

InFlightRequests 还可以获得leastLoadedNode,即所有Node 中负载最小的。那一个选择leastLoadedNode发送请求可以使它能够尽快发出,避免因网络拥塞等异常而影响整体的进度。

 

acks参数

  1. acks = 1 。默认值即为1。生产者发送消息之后,只要分区的leader 副本成功写入消息,那么它就会收到来自服务端的成功响应。如果消息无法写入leader 副本,比如在leader 副本崩溃、重新选举新的leader 副本的过程中,那么生产者就会收到一个错误的响应,为了避免消息丢失,生产者可以选择重发消息。如果消息写入leader 副本并返回成功响应给生产者,且在被其他follower 副本拉取之前leader 副本崩溃,那么此时消息还是会丢失,因为新选举的leader 副本中并没有这条对应的消息。acks 设置为1 ,是消息可靠性和吞吐量之间的折中方案。
  2. acks = 0 。生产者发送消息之后不需要等待任何服务端的响应。如果在消息从发送到写入Kafka 的过程中出现某些异常,导致Kafka 并没有收到这条消息,那么生产者也无从得知,消息也就丢失了。在其他配置环境相同的情况下, acks 设置为0 可以达到最大的吞吐量。
  3. acks = -1 或acks = all 。生产者在消息发送之后,需要等待ISR 中的所有副本都成功写入消息之后才能够收到来自服务端的成功响应。在其他配置环境相同的情况下,acks 设置为1 (all)可以达到最强的可靠性。但这并不意味着消息就一定可靠,因为JSR 中可能只有leader 副本,这样就退化成了acks=1 的情况。


 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值