kafka理解(一)

kafka 的partition相当于一个个可追加的具有偏移量的日志文件,消费者根据不同的分区策略将不同的消息发送到不同的分区内。
offset不跨越分区,kafka的分区有序,而不是主题有序

kafka引入了多副本机制,以提升容灾能力。同一分区的不同副本中保存的消息相同,(在很短时间内,并不相同)
leader 副本负责读写请求,follower副本只负责与leader副本的消息同步。

生产者消费者只与leader副本进行交互,follower副本只负责消息的同步。很多时候follower副本中的消息相对于leader副本有一定的滞后

分区中的所有副本统称为AR,所有与leader副本保持一定程度同步的副本(包括自身)称为ISR,消息会先发送到leader副本,然后follower
才能从leader副本中拉取消息进行同步,同步期间内follower副本相对于leader副本而言会有一定程度的滞后。这个滞后范围可以通过参数进行配置

与leader副本同步滞后过多的副本,(不包括leader副本)组成osr,isr又称在副本同步队列里面的副本。osr称为被踢出副本同步队列的副本。
正常情况下osr=空,AR=ISR AR公式 AR= ISR+OSR

leader副本负责维护和跟组ISR集合中所有follower副本的滞后状态,当follower副本落后太多或者失效时,leader副本会把它从ISR集合中剔除。如果OSR集合中有follower副本追上
了leader副本,那么leader副本会将它从OSR集合中转移到ISR集合。默认情况下,当leader副本发生故障时,只有ISR集合中的副本才有资格被选举为新的leader。
而在OSR集合中的副本没有任何机会(可以通过修改配置参数进行修改)

ISR与HW和LEO也有紧密的关系。HW是high watermark的缩写,即高水位,它标识了一个特定的消息偏移量,消费者只能拉取到这个offset之前的消息

LEo 是logEndOffset 的缩写,它标识当前日志文件中下一条待写入消息的offset,LEO的大小相当于当前日志分区中最后一条消息的offset值+1,。
分区ISR集合中的每个副本都会维护自身的LEO,而ISR集合中最小的LEO为分区总的HW,即对于消费者而言只能消费HW之前的消息。
这样做的好处是,一旦leader宕机,其它副本成为leader后,不至于重复消费或者消费不到

由此可见,kafka的复制既不是完全的同步复制,也不是单纯的异步复制。事实上,同步复制要求所有能工作的follower副本都复制完,这条消息才会被确认为已经提交成功。
这种复制方式极大的影响了性能。而在异步复制的方式下,follower副本同步从leader中复制数据,数据只要被leader副本写入就被认为已经提交成功。这种情况下,如果
follower副本没有复制完而落后于leader,leader又突然宕机,会造成数据的丢失。kafka使用的这种ISR的方式有效的权衡了数据可靠性和性能之间的关系。

kafka创建topic
bin/kafka-topics.sh --zookeeper localhost:2181 --create --topic mykafka --replication-factor 3 --partition 4

kafka查看topic
bin/kafka-topics.sh --zookeeper localhost:2181 --describe --topic mykafka

bin/kafka-topics.sh --zookeeper localhost:2181 --list

kafka控制台的生产者和消费者
bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic mykafka

bin/kafka-console-producer.sh --broker-list localhost:9092 --topic mykafka

kafka生产者分为两个线程协调运行,主线程和sender线程

在主线程中由kafkaproducer创建消息,然后通过可能的拦截器,序列化器,分区器,缓存消息到消息累加器(消息收集器)
sender线程负责从消息累加器将消息发送到kafka中。

消息收集器的作用主要是用来缓存消息,以便sender线程可以批量发送,进而减少网络传输的资源消耗以提升性能。
缓存大小默认为32MB,如果生产者发送消息的速度超过发送服务器的速度,会导致生产者空间不足。这个时候,send方法
会被阻塞或者异常,取决于max.block.ms的配置,该参数的默认值为60秒

主线程发送过来的消息都会被追加到消息累加器中的某个双端队列中,在消息累加器中为每个分区维护了一个双端队列,队列的内容就是
produceBatch,queue(producebatch)消息写入使,追加到尾部,sender取消息时,从头部读取。

produceBatch指的是一个消息批次,这样可以减少网络请求以提升整体的吞吐量。

消息在网络上都是以字节的形式传输的,在发送之前需要创建一块内存区域来保存对应的消息。在kafka生产者客户端中,通过ByteBuffer
实现消息内存的创建和释放,不过频繁的创建和释放比较耗费资源。在消息累加器的内部还有一个bufferPool,它主要是用来实现
bytebuffer的复用,以实现缓存的高效管理。不过bufferpool只针对特定大小的bytebuffer进行管理。而其他大小的bytebuffer不会缓存到
bufferpool中,这个特定大小是由batch.size参数来指定,默认16k,我们可以适当调大该参数来多缓存一些消息。

当一条消息(producerecord)流入消息累加器,会先虚招与消息分区对应的双端队列,(没有则新建),在从这个双端队列的尾部获取一个
produceBatch(没有则新建),查看producebatch中是否还可以写入这个新的producebatch,如果可以则心如,如果不可以则需要创建一个新的
producebatch。在新建producebatch时评估这条消息的大小是否超过batch.size参数的大小,如果不超过,那么就以batch.size参数的大小来创建
producebatch,这样在使用完这段内存区域之后,可以通过bufferpool的管理来进行服用,如果超过就以评估的大小来创建producebatch,这段
内存区域不会被复用。

sender从消息累加器中获取缓存的消息之后会进一步将原本<分区,queue>的保存形式转化为<node,List>
node 指的是对应的broker节点,对于网络连接来说,生产者客户端是与具体的broker节点建立的连接,也就是向具体的broker节点发送消息。
而不关心,消息属于哪个分区。而对于kafkaproduceer的应用逻辑而言,我们只关注向哪个分区中发送哪些消息,所以这里有一个应用层逻辑面
到网络层面逻辑的转换。

然后sender会进一步封装成<node,request>的形式,这样就可以将request发送到各个node了,这里的request值的是kafka的各种协议请求。对于
消息发送而言就是具体的producerequest.

请求在从sender线程发往kafka之前还会保存到inflighrequests中,inflightrequest保存对象为Map<nodeId,deque>)主要作用是缓存已经
发送出去但是还没有收到相应的请求(NodeId是一个String类型,表示节点的id编号),并且还可以配置最多缓存的请求数。默认值为5
通过比较deque的size和该参数来判断是否已经堆积了很多未响应的消息。

inflightrequest还可以获取 leastloadednode,也就是所有node中负载最小的那一个。然后选择负载最小的进行发送。避免因为网络阻塞等引起
异常。

acks=1 默认值为1,生产者发送消息之后,只要分区的leader副本成功写入消息,那么它就会收到来自服务端的成功响应。如果消息无法写入leader副本,
比如在leader副本崩溃、重新选举新的leader副本过程中,消息就会丢失。是消息可靠性和吞吐量之间的折中方案
acks=0 不需要等待服务端的响应。消息会丢失,但是可以达到最大的吞吐量。
acks=-1,需要所有的副本都成功,最可靠。

retries用来配置生产者重试的次数,默认值为0,即在发生异常的时候不进行任何重试动作。消息从生产者发出到写入服务器可能发生一些临时异常
如网络抖动,leader选举等。
retry.backoff.ms两次重试之间的时间间隔。

kafka topic集合订阅的方式subscribe(collection)、正则表达式(pattern)、和指定分区的订阅方式assign(collection)
这三种状态互斥,一个消费者只能使用其中的一种
通过subscribe()方法订阅主题具有消费者自动再均衡的功能,在多个消费者情况下可以根据分区分配侧罗来自动分配各个消费者与分区的关系。
当消费组内的消费者增加或者减少时。分区分配关系会自动调整,以实现消费负载均衡。
而通过assign()方法订阅分区时,是不具备消费者自动均衡的功能的,其实这一点从assign()方法的参数中就可以看出。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值