如何快速入门Kafka消息队列?

  • 回答 (9)
  • 关注 (0)
  • 查看 (1334)

最近经常听到这个名词,但是不知道如何入门,我看到腾讯云也有相关的产品Ckafka产品,所以来问问~

婷槟沃婷槟沃提问于
你想要的cccJava/Python/IOS爱好者,骑行+跑步。。。哦,对了,还养了两只猫。回答于

来点干货~Kafka 的详细设计及其生态系统

Apache Kafka 的核心要素有中介者,订阅主题,日志,分区还有集群,还包括像 MirrorMaker 这样的有关工具。

Kafka 生态系统由 Kafka Core,Kafka Streams,Kafka Connect,Kafka REST Proxy 和 Schema Registry 组成。Kafka 生态系统的其他组件多数都来自 Confluent,它们并不属于 Apache。

Kafka Stream 是一套用于转换,聚集并处理来自数据流的记录并生成衍生的数据流的一套 API,Kafka Connect 是一套用于创建可复用的生产者和消费者(例如,来自 DynamoDB 的更改数据流

)的连接器的 API,Kafka REST Proxy 则用于通过 REST(HTTP)生产者和消费者,Schema Registry 则用于管理那些使用 Avro 来记录 Kafka 数据的模式,而 Kafka MirrorMaker 用于将集群的数据复制到另一个集群里去。

Jean-Paul Azar 在 Cloudurable 工作。后者提供了 Kafka 培训,Kafka 咨询,Kafka 支持 并为在 AWS 中设置 Kafka 集群提供了支持服务。

Kafka 生态系统:Connect Source,Connect Sink 和 Kafka Streams 的图表

Kafka Connect Sources 是 Kafka 记录的来源,而 Kafka Connect Sinks 则是这一记录的目的地。

Kafka 生态系统:Kafka REST Proxy 和 Confluent Schema Registry

Kafka Streams —— Kafka 的数据流处理

Kafka Stream API 基于核心的 Kafka 原语而构建,并有着自己的生命周期。Kafka Streams 能够实时地处理数据流,并为实现数据流处理器提供了支持。数据流处理器会从输入的主题中获取连续的数据流,并对输入执行一些处理,转换和聚合操作,并最终生成一个或多个输出流。例如,视频播放器应用程序会接收观看视频和视频暂停事件的输入流,并输出用户偏好数据流,然后基于最近的用户活动或许多用户的共同活动来产生新的视频推荐单,以查看最近有哪些新的热门视频。Kafka Stream API 还解决了无序记录,跨数据流聚合,连接来自多个流的数据,有状态计算等等难题。

Kafka 生态系统:Kafka Stream 和 Kafka Connect

Kafka 生态系统总结

什么是 Kafka Streams?

Kafka Streams 支持数据流的实时处理。它可以在聚合多个数据流,连接来自多个流的数据,进行有状态的计算等等。

什么是 Kafka Connect?

Kafka Connect 是一套连接器的 API,用于创建可复用的生产者和消费者(例如,来自 DynamoDB 的更改数据流)。Kafka Connect Sources 是 Kafka 记录数据的来源。Kafka Connect Sinks 是这一记录的目的地。

什么是 Schema Registry?

Schema Registry 用于管理那些使用 Avro 来处理 Kafka 记录的模式。

什么是 Kafka Mirror Maker?

Kafka MirrorMaker 用于将集群里的数据复制到另一个群集。

什么时候会用到 Kafka REST Proxy?

Kafka REST Proxy 用于通过 REST(HTTP)生产者和消费者。你可以使用它来轻松集成现有的代码。

如果还不知道 Kafka 是什么,那么请参阅 ”什么是 Kafka?”。

Kafka 架构:底层设计

不得不说,这篇文章实际上就是我们关于 Kafka 架构的系列文章的一个摘要,这个系列包括 Kafka 订阅主题架构Kafka 生产者架构Kafka 消费者架构还有 Kafka 生态系统架构这些文章。

本文也在很大程度上受了 Kafka 设计这篇文章的启发。不妨把本文看成一个精选版。

Kafka 的设计动机

最初 LinkedIn 的工程师造出 Kafka 的缘由是为了给实时分析提供支持,它也因此被设计成了一个对数据流进行实时处理的分析系统提供支持的一个工具。同时 Linkedln 也将 Kafka 开发成了一个统一的实时处理数据流输入数据的平台。Kafka 的目标是建立一个高吞吐量的数据流平台,为日志聚合,用户活动这样的大容量事件流提供支持。

LinkedIn 对 Kafka 有着分布式化,支持分片和负载均衡这些方面的扩展需求,而这种扩展需求促成了 Kafka 的分区和消费者模型。与此同时,Kafka 还通过使用分区分布式提交日志扩展了其读写功能。其中 Kafka 的分片(sharding)被称为分区(Kinesis,类似于 Kafka,将它称为分区 “碎片”)。

根据维基百科所说,“数据库碎片(shard)是数据库或搜索引擎中的数据的一个水平分区。每个单独的分区都会被看作一个碎片或数据库碎片。为了分摊负载,每个碎片又会被保存在一个单独的数据库服务器实例里面。

Kafka 旨在处理来自离线系统的,周期性的大批量数据加载,以及传统的低延迟消息传递场景。

这里提一下 MOM(面向消息的中间件),其例子有 IBM MQSeries,JMS,ActiveMQ 还有 RabbitMQ。像许多 MOM 一样,Kafka 会通过复制副本和主导权选举这些方式保持对节点故障的宽容性。但是 Kafka 的设计更像是一个分布式数据库事务日志,而不是传统的消息传递系统。与许多 MOM 不同,Kafka 的复制机制是内置在底层设计中的,并不是一个衍生出来的想法。

持久化存储:依靠文件系统

Kafka 依靠文件系统来缓存或保存记录。

采用顺序写入方式的硬盘驱动器的磁盘性能很快(非常快)。这里需要介绍一下 JBOD(磁盘簇,Just a Bunch Of Disks)。带有 6 个 7200rpm SATA RAID-5 阵列的 JBOD 配置约为 600MB / 秒。跟 Cassandra 表一样,Kafka log(日志)也是只写(write-only)结构。这意味着数据会被附加到 log 的末尾。在使用硬盘的时候,顺序读写操作会更快速,并且可以预测,还可以通过操作系统进行重点优化。在使用机械硬盘(HDD)时,顺序磁盘访问可能还会快过随机内存访问,甚至是固态硬盘(SSD)。

虽然 JVM 垃圾回收的开销可能会很高,不过 Kafka 在很大程度上是凭借操作系统来进行缓存的,而这是一个大容量、快速且稳定的缓存。现代的操作系统会用上所有可用的内存来进行磁盘缓存,而且基于操作系统的文件缓存几乎没有在操作系统层面上的开销。尽管缓存一致性很难实现,但 Kafka 还是靠着稳定的操作系统实现了高速缓存一致性。凭借操作系统进行缓存还可以减少缓冲区副本的数量。由于 Kafka 倾向于进行连续的磁盘读取,使用操作系统的预读缓存可以让读取操作快得令人难忘。

Cassandra,Netty 和 Varnish 都使用了类似的技术。这些东西在 Kafka 文档中都有很好的说明,并且在 Varnish 有一个更有趣的解释。

大容量快速机械硬盘及长时间连续存取

Kafka 倾向于用长时间的顺序磁盘访问来执行读写操作。就跟 Cassandra,LevelDB,RocksDB 还有其他项目一样,Kafka 会使用一种对日志进行结构化存储和压缩的方式,而不是磁盘上随时可变的 BTree。另外,Kafka 会给应删除的记录标记一个墓碑,而不是立即删除记录,这也跟 Cassandra 一样。

现在的硬盘已经在某种程度上具有了无穷无尽的存储空间,并且读写速度还挺快,因此 Kafka 就能提供一些在消息传递系统里不常有的功能,例如持久保留旧消息。这一灵活性使得 Kafka 能有很多有趣的应用。

Kafka 生产者的负载均衡

生产者会向任一 Kafka 中介者查询 ”哪一个中介者具有订阅主题数据的分区的主导权” 这一元数据,这样就能省掉转发消息的路由层了。这一主导权信息能让生产者直接向相应分区的主导者发送记录。

生产者的客户端会控制生产者将消息发布到哪个分区,并且可以根据某些应用程序逻辑指定所发送的分区。生产者可以通过索引,轮询调度(round - robin)或使用自己在应用程序里定义的分区逻辑来为记录分区。

Kafka 生产者的记录分批

Kafka 生产者也支持给记录分为一个个批次。批次的大小可以通过设置每个批次里面记录的总字节数上限来配置。在记录凑不够一批的时候,Kafka 的生产者也能自动地在一定时间后将记录发送出去。

分批发送非常有利于有效利用网络 IO 性能,并可以大幅提高吞吐量。

为了权衡取得高吞吐量和高延迟这两者的影响,我们也可以按需配置等待凑够一批的缓冲时间。不过,在系统有着大量使用需求的情况下,有的时候也可以达成平均吞吐量又高总体延迟又低的效果。

分批发送能让我们把更多字节的数据累积在一起再发送,能让 Kafka 中介者省掉不少次规模较大的 I/O 操作,还能提高压缩的效率。为了取得更高的吞吐量,Kafka 生产者也能设置基于时间和大小进行的缓冲。生产者会把多条记录合成一批发送。相比于逐一发送记录,这种方式还能减少发送网络请求的数量。

Kafka 生产者的分批

private static Producer<Long, String> createProducer() { 
    Properties props = new Properties(); 
    props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, BOOTSTRAP_SERVERS); 
    props.put(ProducerConfig.CLIENT_ID_CONFIG, "KafkaExampleProducer"); 
    props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, LongSerializer.class.getName()); 
    props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName(); 
    
    // 按记录内容的总字节数计算的批次大小,设为 0 就相当于不分批
    props.put(ProducerConfig.BATCH_SIZE_CONFIG, 32768); 
    
    // 在当前记录凑不满一个批次来发送的时候,至多等待多少毫秒来凑满 
    props.put(ProducerConfig.LINGER_MS_CONFIG, 20); 
     
    // 生产者能用来缓存等待分批发送给 Kafka 中介者的记录的存储空间的字节数
    // 如果数据发送的速度超出了中介者的处理速度,那么生产者会阻塞分区和发送的过程
    // 这段空间会用于存放压缩还有正在发送的记录
    props.put(ProducerConfig.BUFFER_NENORY_CONFI6, 67_108_864); 
    
    // 控制生产者在缓冲区空间耗尽,抛出 BufferExhaustedException 之前
    // 阻塞分区和发送过程多少毫秒
    props.put(ProducerConfig.MAX_BLOCK_MS_CONFIG, 1000); 
    
    // 以下略
}

Kafka 压缩

大型数据流平台的瓶颈并不总是在于 CPU 或磁盘,而通常在于网络带宽。云端以及很多集成化和虚拟化的环境甚至还有更多的跟网络带宽有关的问题,毕竟在这些情景中,多个服务可以共享一张网卡。此外,在数据中心和别的数据中心还有整个 WAN (广域网)进行交互的时候,网络带宽的问题还会更加突出。

分批处理会有利于进行高效的压缩,并进一步达成更高的网络 IO 吞吐量。

Kafka 提供了端到端的分批压缩,而不只是一次压缩一个记录。这样 Kafka 便有效地压缩了整批记录。对同一个消息批次可以只压缩并发送到 Kafka 中介者或服务器一次,并以压缩的形式写入日志分区。你还能通过设置压缩的方式,让 Kafka 中介者在将压缩的记录发送给消费者之前不进行解压。

Kafka 支持使用 GZIP,Snappy 和 LZ4 压缩协议。

拉取 vs. 推送/流式传输

Kafka 消费者能向中介者拉取数据。其他系统的中介者也能将数据或流数据推送给消费者。消息的传递系统通常是一个基于消息拉取的系统(像 SQS,以及大多数 MOM 都在使用拉取方式)。在使用拉取式的系统时,如果消费者处理速度赶不上消息增加的速度,它也可以在能赶上来之后再拉取新消息。

由于 Kafka 采用了拉取方式,因此它积极地实行了数据的分批处理。Kafka 像许多基于拉取的系统一样会实施长时间的轮询(SQS,Kafka 都这样做)。这一方式意味着在消费者会向中介者发出请求,并在这之后一直保持连接并等待响应。

一个基于拉取方式的系统必须由消费者进行数据的拉取并对其进行处理,并且在拉取和真正获取数据之间总是有一段延迟。

在另一方面,基于推送方式系统会主动将数据发送给消费者(像 scribe,flume,reactive streams,RxJava 还有 Akka)。基于推送或数据列的系统在应对处理速度赶不上或断开了连接的消费者方面有些问题。当数据的消费速度低于生产速度时,推送系统中的消费者很可能会被数据压垮。有些基于推送的系统会使用基于背压策略的退避协议,让消费者能发出 “处理速度跟不上“ 的信号。具体可以参考 reactive stream。在有着等待消费者发送对消息的确认的需求时,如何避免压垮消费者,以及消费者如何从处理速度赶不上的状态恢复过来这一问题会变得十分棘手。

基于推送或流式传输的系统可以立即发送请求或者累积请求并按批发送(或者是这两者的结合,并引入背压策略),而基于推送的系统总是会立即推送数据。消费者也可以把已经发送给它的数据累积在一起进行处理,这也有利于减少消息处理的延迟。不过,如果消费者在处理数据之后断开了连接,那么中介者该怎么知道消费者是不是依然在线,以及什么时候能再给消费者发送数据呢?这一问题的解决在推送或流式传输系统里面并不简单,而 Kafka 则通过使用拉取式系统解决了这些复杂问题。

传统的面向消息的中间件对消费者消息的状态追踪

对大多数 MOM(面向消息的中间件)而言,中介者会负责保持对发给消费者的消息的追踪,特别是要找出那些被标记为已处理的消息。这也不是一件容易的事情。

大多数 MOM 系统的目标是让中介者在消息得到了消费之后能快速删除数据。注意,这里的大多数 MOM 是在磁盘体积很小、功能不强、价格还贵的时候设计编写的。

这种类型的消息追踪(或者叫确认功能)说起来容易但做起来很难,因为中介者必须维护大量状态才能跟踪每条消息的发送还有确认状态,然后才能从中决定何时删除或重发消息。

Kafka 对发给消费者的消息的状态追踪

注意,Kafka 的订阅主题的内容会被分为若干个有序的分区。每条消息在这个有序分区中都有一个相对于某个原点的偏移量。每当进行消费的时候,对每个订阅主题的分区,一个消费者分组里面只会有一个消费者会来进行消费。

这一分区的布局意味着中介者会追踪数据在分区中的偏移量,而不是跟别的 MOM 一样去追踪每一条消息的状态,而且 Kafka 只需要追踪每个消费者组所消费的最后一组消息的数据的偏移量,还有其存储分区本身的偏移量。这种追踪偏移量的方式所要维护的数据量相比传统方式要少很多。

消费者会定期地向 Kafka 中介者发送偏移量的定位数据(消费者分组,还有分区偏移),中介者则会将此偏移数据存储到一个存放偏移量的主题中。

偏移式的消息确认与其他一些 MOM 相比成本要低得多。此外,消费者也能在这种模式下更加灵活地进行消费,甚至可以回退到更早的偏移量的消息(也就是重放)。如果消费者出故障了,那么就能在修复并重启消费者之后把消息重放一遍,毕竟 Kafka 可以持久地保存主题的日志数据。这种回退功能正是 Kafka 的优良特色。

消息传递语义

有三种消息传递语义:至多一次、至少一次、只有一次。传递最多一次的消息可能会丢失,但永远不会收到重复消息。传递至少一次的消息是永远不会丢失的,但可能会收到重复消息。只传递一次的消息则即确保了消息不会丢失,又确保了不会收到重复消息。只有一次这种方式的传递效果最好,但其开销较大,并且需要生产者和消费者记录更多的状态。

Kafka 消费者和消息传递语义

回想一下,所有副本都具有每一项的偏移量都相同的日志分区,并且每个消费者组都会在维护它们在每个订阅主题分区里面的日志中所处的位置。

就实现层面上来说,“最多一次” 意味着消费者会在读取消息之后将它在分区中的偏移量发送给中介者,让后者把偏移量保存起来,然后再处理消息。这一模式的问题在于消费者在从把偏移量发给了中介者到开始处理消息这段时间内可能会出故障,然后在消费者重启之后会继续从这一偏移量开始接收新消息,但它出故障之前读取的那条消息却不会得到处理。

“至少一次” 意味着消费者在读取并处理消息之后才会向中介者发送偏移量。这一模式的问题在于消费者在从处理完消息到发送偏移量之间这段时间也可能会出故障。然后在消费者重启之后,消费者就会收到并处理它在出故障之前已经处理过的消息。实际上,“至少一次” 是最常用的消息传递模式,不过它需要开发者确保消息具有幂等性(idempotent),即接收相同消息两次或以上的效果跟接收一次消息没有区别。

“只有一次“ 意味着消费者需要把消息处理和提交偏移量这两步并为一个原子性的事务,即如果偏移量发送失败,那么消息处理步骤也要回退。这一事务的实现需要在读取消息和保存处理消息的输出结果这两步之间进行一个二阶段的提交。或者,消费者也可以把偏移量和处理消息的输出存放在同一个地方,这样就可以通过查看这一位置存放的是偏移量还是处理的输出来判断偏移量有没有发送成功了。

Kafka 提供了前两种模式的实现,至于第三种模式的实现则要我们对消费者做一些修改。

Kafka 生产者的耐久度及消息确认

Kafka 也为耐久度提供了可操作的可预测的语义。在发布消息时,消息会被 “提交” 到日志中,这意味着所有 ISR(In-Sync Replicas,处于同步状态的副本)都会接受消息。只要至少有一个这样的副本在,这种提交策略就能很好地工作,这也有利于确保系统的耐久性。

生产者在收到对消息的确认之前会一直重发消息,而不管它所发送的消息有没有经过中介者。这就违反了 “只有一次” 还有 “至多一次” 的消息传递语义。

生产者的连接可能会在发送完毕等待确认的过程中断开,然后生产者在重新连接之后会无法确定它所发送的消息有没有被消费者成功处理,然后它就会把消息再发一遍。这种重新发送的逻辑使得引入消息序列号还有幂等消息处理(收到重复消息也没问题)成为了一个重要事项。直到 2017 年 6 月,Kafka 才实现了生产者因故障重启之后不会重复发送消息的一套机制。

生产者耐久度

生产者可以标明它的耐久度级别,而这一耐久度级别是由生产者对它发出的消息需要多大程度的确认来区分的。设置高程度的确认水平可以确保所有副本都保存了它发出的消息。

耐久度级别有:

生产者发送消息后不用等待确认(0);

生产者发送消息后需要等待来自一个分区主导者的确认(1);

生产者发送消息后需要等待来自所有副本的确认(-1,默认设置)。

对生产者的改进(2017 年 6 月发布的更新之一)

Kafka 现在为生产者端的 “只有一次” 交付、性能改善以及对多个分区的原子写操作提供了支持。他们通过让生产者随消息发送一个序列的 ID 实现了这一点。中介者会持续检查生产者是否已经发送了这个序列。如果生产者把这个序列又发送了一遍,它就会得到对这一重复的消息的确认,但这一消息不会保存到日志里面。采用这一改进功能不需要更改目前所用的 API。

Kafka 生产者对日志的原子性写操作(2017 年 6 月发布的更新之一)

Kafka 的另一个改进是 Kafka 生产者能进行对多个分区的原子写操作。原子写操作意味着 Kafka 消费者只能看到生产者已经写进去并完成了提交的日志(可以设置一些具体属性)。Kafka 会有一个协调者来为订阅主题日志记上一个标记,以表示已被成功处理的事务。事务协调者和事务日志会共同维护原子写操作的状态。

原子写操作需要用上新的生产者 API 来产生事务。这有一个使用新的生产者 API 的例子:

用来产生事务的新版生产者 API

producer.initTransaction();
try {
  producer.beginTransaction();
  producer.send(debitAccountMessage);
  producer.send(creditOtherAccountMessage);
  producer.sentOffsetsToTxn(...);
  producer.commitTransaction();
} catch (ProducerFencedTransactionException pfte) {
  // ...
  producer.close();
} catch (KafkaException ke) {
  // ...
  producer.abortTransaction();
}

Kafka 副本机制(Replication,或称复制机制)

在 Kafka 中, 对每个订阅主题的分区,都会有一些 Kafka 节点(数量可以自行设置)持有其副本。Kafka 的副本模型是一个自带的功能,而不像多数消息中间件那样把它视作一个插件式的功能,因为 Kafka 从一开始就引入了分区还有多节点特性。每个订阅主题的分区都会对应一个主导者以及若干从属者(也可能没有从属者)。

主导者还有从属者都被称为副本。主导者还有从属者节点的数量被称为副本因子。分区的主导权会在 Kafka 中介者之间平均地分摊。消费者只能从主导者那里读取消息。生产者也只能把消息发给主导者。

从属者的订阅主题日志分区会与主导者的日志分区保持同步,它会像一个普通的 Kafka 消费者一样从它们的主导者那里按批拉取记录。

Kafka 中介者出现故障的情景

Kafka 会持续追踪 Kafka 中介者的在线状态。为了表明自己处于这一状态,Kafka 中介者必须使用 ZooKeeper 的心跳机制来维护一个 ZooKeeper 会话,并且必须让所有的从属者的日志记录与主导者保持同步,而不会落后过多。

就中介者的在线状态这一概念来说,ZooKeeper 会话还有记录的同步都是它的必要条件,毕竟这一状态本身就表明了记录应该保持同步。跟主导者保持了同步的副本被称为 ISR。每个主导者都会持续记录跟主导者保持了同步的一组副本,即 ISR 的集合。

如果某个本来是 ISR 的从属者出了问题,使得它存储的进度落后了,那么主导者就会从它的 ISR 集合里除掉这个从属者 。在这里,副本的记录的进度落后的定义是这一副本在 replica.lag.time.max.ms 毫秒的时间之内没能与主导者达成同步。

当所有 ISR 都将消息存进它们的日志之后,该消息就会被看作是 “已提交” 的,而消费者只能看到已提交的消息。Kafka 确保了只要有一个 ISR,已提交的消息就绝不会丢失。

日志分区副本

一个 Kafka 分区就是一个日志副本(replicated log)。日志副本是分布式数据系统的基础。日志副本对基于状态机来实现其他分布式系统很有用。 整个日志副本模型会需要对一系列有序值 “达成共识”。

在主导者在线的时候,所有的从属者只需要按序复制它们的主导者的值即可。如果主导者掉线了,Kafka 会从与主导者同步的从属者中选择一位新的主导者。在生产者已经收到了对其发送的一个消息的提交确认,然后主导者掉线了的情况下,新当选的主导者肯定得持有这个已提交的消息。

若能有更多的 ISR,在主导者出故障的时候能顶替的从属者就越多。

Kafka 和 Quorum 机制

Quorum 机制在这里指的是通过对产生一个新的主导者所需要确认的副本数,还有应该与新主导者比较日志版本的副本数的选择,使得这两种副本的集合会有所重叠,以此来确保可用性。大多数系统都使用了投票流程,并把主导权交给得票多数者。不过,Kafka 为了提高可用性,并没有套用简单的多数票选机制。

在 Kafka 里,新主导者的选择是以持有完整的日志为基础的。如果我们有一个副本因子 3,那么肯定至少有两个 ISR 在主导者声明生产者发送的消息完成了提交之前达成了同步。如果要选出一个新主导者,那么新主导者必须能确保持有所有已经提交的消息,并且只能至多有 2 个副本同时掉线。

在一群从属者里面,必须至少有一个副本持有所有已提交的消息。多数票选的 Quorum 机制有个问题在于只要集群里面有一部分节点同时掉线了,那么就会凑不够满足这一条件的可进行投票操作的集群(副本因子为 2n+1 的情况下只能至多允许 n 个副本同时掉线)。

Kafka ISR 间的 Quorum 机制

Kafka 里的每个主导者都会维护一个 ISR 集合。只有这一集合中的成员才有资格参选新主导者。只有在所有 ISR 都写入新的记录之后,生产者发往分区的记录才能完成提交。ISR 集合被保存在 ZooKeeper 里面,在 ISR 集合产生变化时它会进行相应的操作。

这种类似于 Quorum 的 ISR 机制能让生产者发送消息时不用接收全部节点的多数确认,只需要接收 ISR 的多数确认即可。这种机制还能让副本重新加入到 ISR 集合里面,并且也能在加入之后发送确认。不过副本在重新加入到 ISR 集合之前需要重新达成记录的完全同步。

节点全掉线了,怎么办?

Kafka 只确保了在至少有一个从属者和主导者达成了同步的时候能避免数据的丢失。

如果所有的分区主导者的从属者全都同时掉线了,那么 Kafka 也便无法保证数据不会丢失了。如果分区的所有副本都出了问题,那么在默认情况下,Kafka 会选择第一个重新回到在线状态的副本(不一定是 ISR)来担任新的主导者(前提是要设置 unclean.leader.election.enable = true,不过这是默认值)。相比于一致性,这一选择更重视可用性。

如果在你的使用场景里一致性比可用性更重要,那么可以设置 unclean.leader.election.enable = false。在这样设置之后,如果某个分区的所有副本都掉线了,Kafka 会等待第一个 ISR 成员重新上线(不一定是第一个重新上线的副本)来担任新的主导者。

对生产者耐久度的选择

生产者可以通过将接收确认的需求 ack 设置为:none(0);the leader only(1);all replicas(-1)。

acks = all replicas 是默认值。总而言之,当所有当前的同步复制品(ISR)都收到该消息时,便会发生这种情况。

你可以在一致性和可用性之间进行权衡。如果一致性比可用性更重要,那么可以设置 unclean.leader.election.enable = false 并指定最小的 ISR 集合大小。

最小 ISR 集合大小越大,一致性就能得到越好的保证,但可用性就会越低,因为在 ISR 集合达到最小阈值之前是不能往相应的分区里面写入任何东西的。

配额控制

Kafka 为生产者和消费者设定了它们所能使用的网络带宽的配额。这些配额阻止了生产者和消费者一直占用 Kafka 中介者资源,其中配额限制的对象为客户端 ID 或用户。配额的数据会保存在 ZooKeeper 里面,因此更改配额不需要重启 Kafka 中介者。

Kafka 底层设计和架构总结

如何防止来自消费者的拒绝服务攻击?

用配额来限制消费者的带宽。

默认生产者耐久度(acks)水平是什么?

全部。这意味着所有 ISR 必须将消息写入其日志分区。

如果 Kafka 节点全都掉线了,在默认情况下会发生什么?

Kafka 会选择第一个重新上线的副本(不一定在 ISR集合中)作为新的主导者。因为在默认情况下 Kafka 会更重视可用性,会设置 unclean.leader.election.enable = true

为什么 Kafka 记录分批重要?

这能优化网络和磁盘的 IO 吞吐量。它还能通过压缩整个分批来提高压缩效率。

Kafka 的设计目标是什么?

成为一个高吞吐量,可扩展的数据流数据平台,用于对日志聚合,用户活动等大容量事件流进行实时分析。

截至 2017 年 6 月,Kafka 中的一些新功能有哪些?

生产者的原子性写操作,性能改进以及确保生产者不重复发送消息的机制。

消息传递语义是什么?

有三种消息传递语义:最多一次,至少一次,只有一次。

Jean-Paul Azar 工作于 Cloudurable。Cloudurable 提供的服务有 Kafka 培训,Kafka 咨询,Kafka 支持,以及为在 AWS 中设置 Kafka 集群提供帮助。

回答过的其他问题

人工智能是否可以架构在区块链上?

你想要的cccJava/Python/IOS爱好者,骑行+跑步。。。哦,对了,还养了两只猫。
说到人工智能,就不能回避大数据。机器学习方法依托于大量的数据来完成验证和训练,而当下的数据全都别掌握在大公司手中,不能为个人随意支配,数据市场尚未成型。区块链的几大主要特征,如:分布式节点的共识系统、信息的不可篡改、匿名化、去中心化。 区块链还有一种非常神奇的计算方法叫零知识证明...... 展开详请

物联网与工业互联网有什么区别?

你想要的cccJava/Python/IOS爱好者,骑行+跑步。。。哦,对了,还养了两只猫。
要知道他们的区别是什么,就要先知道他们是什么? 工业互联网,英文简称IIoT,而物联网是IOT,其实单从英文简称来看,就可以大概知道他们的联系,工业物联网网是物联网更大的概念,从编程方向来理解就是物联网是工业物联网的父级,而工业物联网就是继承了物联网的特性,并且拥有自己的属性,而...... 展开详请

我什么都不会呀,看不懂怎么办呀?

你想要的cccJava/Python/IOS爱好者,骑行+跑步。。。哦,对了,还养了两只猫。
任何事情都可以按照正常的学习流程,正常的方法。 但是你问我了,我可以说无可奉告。 但是你总想搞个大新闻的,说腾讯云不给你解决问题然后把我批判一番。 我讲的意思是,要好好学习,不会了再来问,你这直接是伸手要了,我能有什么办法? 你啊,非常熟悉伸手党那套理论,然而……... 展开详请

yum install php-pdo 失败?

你想要的cccJava/Python/IOS爱好者,骑行+跑步。。。哦,对了,还养了两只猫。
你试试用下面的方法解决试试。 yum clean all rpm --rebuilddb yum update 如果不行就尝试更换yum源 cd /etc/yum.repos.d mv CentOS-Base.repo CentOS-Base.repo.bk wget http:...... 展开详请

腾讯工蜂git 托管 ,怎样删除整个git项目?

你想要的cccJava/Python/IOS爱好者,骑行+跑步。。。哦,对了,还养了两只猫。

打开项目,点击设置-高级设置-仓库设置-删除项目即可。

扫码关注云+社区

领取腾讯云代金券