kafka

作者: 神呐_宽恕我把 | 来源:发表于2020-02-27 10:33 被阅读0次

    Kafka的优点如下:

    ①解耦:在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。

    消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口。

    这允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。

    ②冗余(副本):有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。

    消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。

    许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。

    ③扩展性:因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。不需要改变代码、不需要调节参数。扩展就像调大电力按钮一样简单。

    ④灵活性&峰值处理能力:在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见;如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。

    使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。

    ⑤可恢复性:系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。

    ⑥顺序保证:在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。Kafka 保证一个 Partition 内的消息的有序性。

    ⑦缓冲:在任何重要的系统中,都会有需要不同的处理时间的元素。例如,加载一张图片比应用过滤器花费更少的时间。

    消息队列通过一个缓冲层来帮助任务最高效率的执行,写入队列的处理会尽可能的快速。该缓冲有助于控制和优化数据流经过系统的速度。

    ⑧异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

    一.Receiver模式

    1.会开启一个Receiver接收器接收Kafka的数据,但是一个Receiver效率低,多个Receiver又需要手动合并union数据,很麻烦

    2.如果Receiver挂了,会导致数据丢失,如果开启WAL预写日志,效率又低

    3.Receiver使用的是Kafka的高阶(高层/封装)API,offset由Receiver维护在ZK中, Spark也会维护一份在Checkpoint中,可能会不一致

    二.Direct模式

    1.SparkStreaming直接连接Kafka的各个分区,速度非常快

    2.Direct模式使用的是Kafka的低阶(底层)API,offset默认由Spark维护在Checkpoint中,offset也可以由程序员手动维护在MySQL/Redis中, 这样可以保证数据Exactly Once(精准一次)

    问题

    就是副本分区当中的数据与leader当中的数据存在差别的问题如何解决,这个就是Partition tolerance的问题。

    kafka为了解决Partition tolerance的问题,使用了ISR的同步策略,来尽最大可能减少Partition tolerance的问题

    每个leader会维护一个ISR(a set of in-sync replicas,基本同步)列表

    ​ ISR列表主要的作用就是决定哪些副本分区是可用的,也就是说可以将leader分区里面的数据同步到副本分区里面去,决定一个副本分区是否可用的条件有两个

    replica.lag.time.max.ms=10000    副本分区与主分区心跳时间延迟

    replica.lag.max.messages=4000    副本分区与主分区消息同步最大差

    什么情况下一个 broker 会从 isr中踢出去

    leader会维护一个与其基本保持同步的Replica列表,该列表称为ISR(in-sync Replica),每个Partition都会有一个ISR,而且是由leader动态维护 ,如果一个follower比一个leader落后太多,或者超过一定时间未发起数据复制请求,则leader将其重ISR中移除 。

    kafka 为什么那么快(实现高吞吐率)

    顺序读写:Kafka 将消息写入到了分区 Partition 中,而分区中的消息又是顺序读写的。顺序读写要快于随机读写。

    零拷贝:生产者、消费者对于 Kafka 中的消息是采用零拷贝实现的。

    批量发送:Kafka 允许批量发送模式。

    消息压缩:Kafka 允许对消息集合进行压缩。

    kafka producer如何优化打入速度

    增加线程

    提高 batch.size

    增加更多 producer 实例

    增加 partition 数

    设置 acks=-1 时,如果延迟增大:可以增大 num.replica.fetchers(follower 同步数据的线程数)来调解;

    跨数据中心的传输:增加 socket 缓冲区设置以及 OS tcp 缓冲区设置。

    kafka的message格式是什么样的

    一个Kafka的Message由一个固定长度的header和一个变长的消息体body组成

    header部分由一个字节的magic(文件格式)和四个字节的CRC32(用于判断body消息体是否正常)构成。

    当magic的值为1的时候,会在magic和crc32之间多一个字节的数据:attributes(保存一些相关属性,

    比如是否压缩、压缩格式等等);如果magic的值为0,那么不存在attributes属性

    body是由N个字节构成的一个消息体,包含了具体的key/value消息

    kafka中consumer group 是什么概念

    同样是逻辑上的概念,是Kafka实现单播和广播两种消息模型的手段。同一个topic的数据,会广播给不同的group;同一个group中的worker,只有一个worker能拿到这个数据。换句话说,对于同一个topic,每个group都可以拿到同样的所有数据,但是数据进入group后只能被其中的一个worker消费。group内的worker可以使用多线程或多进程来实现,也可以将进程分散在多台机器上,worker的数量通常不超过partition的数量,且二者最好保持整数倍关系,因为Kafka在设计时假定了一个partition只能被一个worker消费(同一group内)。

    Kafka中的消息是否会丢失和重复消费?

    要确定Kafka的消息是否丢失或重复,从两个方面分析入手:消息发送和消息消费。

    1、消息发送

             Kafka消息发送有两种方式:同步(sync)和异步(async),默认是同步方式,可通过producer.type属性进行配置。Kafka通过配置request.required.acks属性来确认消息的生产:

    0---表示不进行消息接收是否成功的确认;

    1---表示当Leader接收成功时确认;

    -1---表示Leader和Follower都接收成功时确认;

    综上所述,有6种消息生产的情况,下面分情况来分析消息丢失的场景:

    (1)acks=0,不和Kafka集群进行消息接收确认,则当网络异常、缓冲区满了等情况时,消息可能丢失;

    (2)acks=1、同步模式下,只有Leader确认接收成功后但挂掉了,副本没有同步,数据可能丢失;

    2、消息消费

    Kafka消息消费有两个consumer接口,Low-level API和High-level API:

    Low-level API:消费者自己维护offset等值,可以实现对Kafka的完全控制;

    High-level API:封装了对parition和offset的管理,使用简单;

    如果使用高级接口High-level API,可能存在一个问题就是当消息消费者从集群中把消息取出来、并提交了新的消息offset值后,还没来得及消费就挂掉了,那么下次再消费时之前没消费成功的消息就“诡异”的消失了;

    解决办法:

            针对消息丢失:同步模式下,确认机制设置为-1,即让消息写入Leader和Follower之后再确认消息发送成功;异步模式下,为防止缓冲区满,可以在配置文件设置不限制阻塞超时时间,当缓冲区满时让生产者一直处于阻塞状态;

            针对消息重复:将消息的唯一标识保存到外部介质中,每次消费时判断是否处理过即可。

    为什么Kafka不支持读写分离?

    在 Kafka 中,生产者写入消息、消费者读取消息的操作都是与 leader 副本进行交互的,从 而实现的是一种主写主读的生产消费模型。

    Kafka 并不支持主写从读,因为主写从读有 2 个很明 显的缺点:

    (1)数据一致性问题。数据从主节点转到从节点必然会有一个延时的时间窗口,这个时间 窗口会导致主从节点之间的数据不一致。某一时刻,在主节点和从节点中 A 数据的值都为 X, 之后将主节点中 A 的值修改为 Y,那么在这个变更通知到从节点之前,应用读取从节点中的 A 数据的值并不为最新的 Y,由此便产生了数据不一致的问题。

    (2)延时问题。类似 Redis 这种组件,数据从写入主节点到同步至从节点中的过程需要经 历网络→主节点内存→网络→从节点内存这几个阶段,整个过程会耗费一定的时间。而在 Kafka 中,主从同步会比 Redis 更加耗时,它需要经历网络→主节点内存→主节点磁盘→网络→从节 点内存→从节点磁盘这几个阶段。对延时敏感的应用而言,主写从读的功能并不太适用。

    Kafka中是怎么体现消息顺序性的?

    kafka每个partition中的消息在写入时都是有序的,消费时,每个partition只能被每一个group中的一个消费者消费,保证了消费时也是有序的。

    整个topic不保证有序。如果为了保证topic整个有序,那么将partition调整为1.

    消费者提交消费位移时提交的是当前消费到的最新消息的offset还是offset+1?

    offset+1

    Kafka 判断一个节点是否还活着有那两个条件?

    (1)节点必须可以维护和 ZooKeeper 的连接,Zookeeper 通过心跳机制检查每个节点的连接

    (2)如果节点是个 follower,他必须能及时的同步 leader 的写操作,延时不能太久

    Kafka 消息是采用 Pull 模式,还是 Push 模式?

    Kafka 最初考虑的问题是,customer 应该从 brokes 拉取消息还是 brokers 将消息推送到

    consumer,也就是 pull 还 push。在这方面,Kafka 遵循了一种大部分消息系统共同的传统

    的设计:producer 将消息推送到 broker,consumer 从 broker 拉取消息

    一些消息系统比如 Scribe 和 Apache Flume 采用了 push 模式,将消息推送到下游的

    consumer。这样做有好处也有坏处:由 broker 决定消息推送的速率,对于不同消费速率的

    consumer 就不太好处理了。消息系统都致力于让 consumer 以最大的速率最快速的消费消

    息,但不幸的是,push 模式下,当 broker 推送的速率远大于 consumer 消费的速率时,

    consumer 恐怕就要崩溃了。最终 Kafka 还是选取了传统的 pull 模式

    Pull 模式的另外一个好处是 consumer 可以自主决定是否批量的从 broker 拉取数据。Push

    模式必须在不知道下游 consumer 消费能力和消费策略的情况下决定是立即推送每条消息还

    是缓存之后批量推送。如果为了避免 consumer 崩溃而采用较低的推送速率,将可能导致一

    次只推送较少的消息而造成浪费。Pull 模式下,consumer 就可以根据自己的消费能力去决

    定这些策略

    Pull 有个缺点是,如果 broker 没有可供消费的消息,将导致 consumer 不断在循环中轮询,

    直到新消息到 t 达。为了避免这点,Kafka 有个参数可以让 consumer 阻塞知道新消息到达

    (当然也可以阻塞知道消息的数量达到某个特定的量这样就可以批量发

    Kafka 存储在硬盘上的消息格式是什么?

    消息由一个固定长度的头部和可变长度的字节数组组成。头部包含了一个版本号和 CRC32校验码。

    消息长度: 4 bytes (value: 1+4+n)

    版本号: 1 byte

    CRC 校验码: 4 bytes

    具体的消息: n bytes

    一个Kafka的Message由一个固定长度的header和一个变长的消息体body组成

    header部分由一个字节的magic(文件格式)和四个字节的CRC32(用于判断body消息体是否正常)构成。

    当magic的值为1的时候,会在magic和crc32之间多一个字节的数据:attributes(保存一些相关属性,

    比如是否压缩、压缩格式等等);如果magic的值为0,那么不存在attributes属性

    body是由N个字节构成的一个消息体,包含了具体的key/value消息

    数据有序

    一个消费者组里它的内部是有序的

    消费者组与消费者组之间是无序的

    kafaka 生产数据时数据的分组策略

    生产者决定数据产生到集群的哪个 partition 中

    每一条消息都是以(key,value)格式

    Key 是由生产者发送数据传入

    所以生产者(key)决定了数据产生到集群的哪个 partition

    相关文章

      网友评论

          本文标题:kafka

          本文链接:https://www.haomeiwen.com/subject/fthcnctx.html