Kafka基础

一、kafka概述、介绍

1、kafka是一种高吞吐量的分布式发布订阅消息系统

2、kafka是流处理平台,提供了消息的发布订阅消息队列

3、kafka解决解耦、异步通信场景

①解耦:如上图

  注册模块和发短信模块的之间是强耦合的,短信发送模块down之后,注册模块也会失效

  而使用消息队列后,注册模块成功后就会返回,发送短信可以慢慢消费消息队列。当短信发送服务出现故障后不影响注册业务的正常使用。

②异步通信:如上图

  用户注册,会先调用注册模块,耗时30ms,用户注册模块在数据库写入注册信息成功后会调用发送短信业务,耗时30ms。这时就有60ms消耗

  使用消息队列后,用户在注册模块注册成功后,耗时30ms,注册模块将消息写入消息队列耗时5ms。这时只有35ms消耗

 4、kafka解决削峰场景

 应用调用计算,若此时请求很多,消息队列会进行一个缓冲,避免过多请求同时进行流处理

流处理结束后网数据库中写数据,消息队列会进行缓冲,避免过多请求同时打到数据库

二、架构和概念

1、消息队列消费的两种方式

     ①至多一次,只能有一个消费者去消费消息,并且消息在消费之后会删除

  ②没有限制,可以有多个消费者同时去消费同一消息,消费完后会记录每一个消费者的偏移量offset,下次各消费者根据偏移量继续进行消费

2、kafka集群以Topic(主题)形式负责分类集群中的消息(一个集群有多个topic)

  每条消息只能属于一个topic

  每个消息用:key(消息主键)/value(消息的值)/时间戳(消息产生时间)构成

  每个消息只属于一个topic中的一个分区,判断消息属于哪个分区,将消息key值hash后%分区数得到的结果决定了这则消息分配到哪个分区

  每一个分区中会有一个Broker作为该分区的leader,负责该分区的读和写操作,其他Broker担当该分区的follower。

3、topic、partition、broker、kafka Leader、kafka Follower各自的含义

  topic:主题。kafka集群以topic方式分类集群中的消息,一个集群可以有多个topic

  partition:可以理解为topic的分区。一个topic中可以有多个partition。

        topic比喻为高速路,partition比喻为高速上的快中慢车道,kafka产生的消息进入partition后不可以变化车道

  broker:每个broker可以理解为kafka集群中的节点。partition存在broker节点上,每个partition会有多个副本,每个副本存在不同的broker上

  kafka Leader、kafka Follower:不论是producer端还是consumer端发往partition的请求,皆通过leader数据副本所在的broker进行处理。

                 当broker发生故障时,对于leader数据副本在该broker的所有partition将会变得暂时不可用。

                 Kafka将会自动在其他数据副本中选择出一个leader,用于接收客户端的请求。

三、分区&日志

1、kafka保证了分区内部消息的前后顺序,但是不能保证所有分区之间消息的前后顺序,Partition分区中数字越大消息越新

  kafka可以适用于高并发场景,分区数越大,kafka中能承受的写入消息越多

注意:如果生产者生产的消息有key,使用默认的key取哈希值的策略往partition中分配消息

   如果生产者生产的消息中没有key,则使用轮询的策略往partition中分配消息

   这部分代码需要实现implements Partitioner接口

四、 生产者消费者组

1、消费者在消费数据的时候默认会定期提交消费的偏移量,这样就保证所有消息至少可以被消费者消费一次,可以通过以下两个参数配置

  enable.auto.commit = true

  auto.commit.interval.ms = 5000  5s提交一次

 偏移量为当前偏移量数字+1。如:当前消费到第15个消息,kafka在记录偏移量时会记录为16,下次消费时从16开始消费

  注意:若该消费者为新加入成员,默认为lastest。也可以设置偏移量为lastest|earliest|none三种模式,一旦消费过消息,那么此时再次设置偏移量是不起作用的      

  

2、kafka中消费者使用consumer group名称标记自己

消费者A和消费者B分别为两个不同的consumer group

  消费者A中c1会监听分区中p0和p1,c2会监听p2和p3,c1与c2分别监听不同的分区,保证消息不会被重复消费。同一组内的消费者只能均分分区

  消费者B中有四个consumer,四个分区,每个consumer负责一个分区

注意:此时p0既被消费A组中c1监管,又被消费B组中c1监管,会不会同一消息被消费两次呢?

  不会,每个消费组代表不同服务,不同服务消费同一消息不会造成消息重复消费的情况

总结:topic分区数量越大,同一时间消息的写入能力越大。

   消息较多时,若同一时间消费者组中消费者数量足够多,并发处理消息能力也就越强。

五、顺序写入与零拷贝 

1、kafka为什么写入请求可以轻松支持每秒百万级?

  ①使用了顺序IO  

  ②使用了mmap,写到内核就算成功,不需要写到磁盘

    如下图:内核空间(操作系统下的空间)、用户空间(操作系统之上的空间)

2、kafka为什么支持高速写出?

  使用了零拷贝技术

  零拷贝:数据从磁盘通过DMA拷贝到内存空间,内存空间拷贝数据到缓冲区,缓冲区通过网络发送出去

  零拷贝没有经过用户空间

10、kafka中offset的三种偏移量

  latest:将最近的消息设置为偏移量

  earliest:将最早的消息设置为偏移量

  none:如果未找到消费者组先前的偏移量就抛出异常

 11、acks:kafka生产者在发送完消息后会要求Broker在规定时间内给出响应,如果在规定时间内未收到响应,会进行消息重发

  acks=1:leader会将消息写到本地日志,写完会进行响应。不会等到所有follower都同步成功才响应。若follower还未同步消息,leader已经完成响应并且挂掉,会造成消息丢失(面试问到kafka写丢失的原因之一)

  acks=0:provider发送消息后没有收到回应就会认为此时已经完成消息传递,这种情况不能保证服务器已经收到消息(不可靠,但是效率高。应用在一些要求性能但是不要求数据准确的场景中)

  acks=all:在leader收到消息,且所有follower同步成功后才会进行响应,这种场景下数据不会丢失(应用在消息必须准确的场景下)

  注意:如果生产者在规定时间内没有得到kafka的Leader的Ack应答,kafka可以开启reties机制

     request.timeout.ms = 30000

     retries = 2147483647

  启用reties机制可能会产生消息重复的情况,如消息已经写到分区文件中,但此时可能由于网络或其他原因导致ack失败,这时如果触发重试机制,则分区文件中可能会有两条相同的消息

  场景:下订单后,将订单消息写到kafka分区文件中,若此时触发重试机制则会有两条下订单消息,那么在库存做减法时就会导致页面中显示库存与实际仓库中库存不一致的情况

  解决方法:幂等性

12、幂等性:消息只能持久化到topic中一次

  幂等时针对生产者角度的特性,保证生产者发送的消息不会丢失,而且不会重复

  kafka会给生产者生成一个唯一的pid,在发送消息时会将pid、序列号与消息捆绑在一起发送。序列号是单调递增的,仅当broker接收到的消息在pid相同情况下序列号比当前大1时才会接收消息,否则会认为是重复消息

  默认情况下kafka的幂等性是关闭的:enable.idempotence = false

  若要打开幂等性,即设置幂等性为true时,必须开启retries=true(消息重发)和ack=all(主节点保存数据且至少有一个从节点副本也保存,保证数据不丢)

  

 13、生产者事务:幂等性只能保证一条记录在分区发送的原子性,如果要保证多条记录之间的完整性,就要开启kafka事务的操作

  生产者开启事务,消费者必须将事务隔离级别设置为read_committed

  好处:生产者发送生产的消息时,若出现异常事务没有提交。此时消费者的隔离级别为读已提交,此时消费者不会读到生产者产生的消息

                           若消费者的隔离级别为读未提交,此时消费者可以读到生产者产生的消息

   

 14、生产者&消费者事务

  

 业务处理1既要作为消费者接收topic1中的消息,又要作为生产者将消息传递给topic2。此处业务处理1既作为生产者又作为消费者

  

  

 上图代码模拟了第一张图片的场景

  ①生产者产生消息发送给topic1

  ②业务处理1拿到topic1中的消息,判断如果不为null,开启事务,进行业务处理

  ③业务处理如果没有异常,角色变为生产者,则提交事务,发送消息给topic2,提交消费者的偏移量

 

作者:http://cnblogs.com/lyc-code/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权力。

原文地址:https://www.cnblogs.com/lyc-code/p/15037977.html