kafka设计思想 一

目录

1 动机

2 持久化

1 动机

我们设计的 Kafka 能够作为一个统一的平台来处理大公司可能拥有的所有实时数据馈送。要做到这点,我们必须考虑相当广泛的用例。

Kafka 必须具有高吞吐量来支持高容量事件流,例如实时日志聚合。

Kafka 需要能够正常处理大量的数据积压,以便能够支持来自离线系统的周期性数据加载。

这也意味着系统必须处理低延迟分发,来处理更传统的消息传递用例。

我们希望支持对这些馈送进行分区,分布式,以及实时处理来创建新的分发馈送等特性。由此产生了我们的分区模式和消费者模式。

最后,在数据流被推送到其它数据系统进行服务的情况下,我们要求系统在出现机器故障时必须能够保证容错。

为支持这些使用场景导致我们设计了一些独特的元素,使得 Kafka 相比传统的消息系统更像是数据库日志。我们将在后面的章节中概述设计中的部分要素。

2 持久化

Kafka 对消息的存储和缓存严重依赖于文件系统。人们对于“磁盘速度慢”的普遍印象,使得人们对于持久化的架构能够提供强有力的性能产生怀疑。事实上,磁盘的速度比人们预期的要慢的多,也快得多,这取决于人们使用磁盘的方式。而且设计合理的磁盘结构通常可以和网络一样快。

关于磁盘性能的关键事实是,磁盘的吞吐量和过去十年里磁盘的寻址延迟不同。因此,使用6个7200rpm、SATA接口、RAID-5的磁盘阵列在JBOD配置下的顺序写入的性能约为600MB/秒,但随机写入的性能仅约为100k/秒,相差6000倍以上。因为线性的读取和写入是磁盘使用模式中最有规律的,并且由操作系统进行了大量的优化。现代操作系统提供了 read-ahead 和 write-behind 技术,read-ahead 是以大的 data block 为单位预先读取数据,而 write-behind 是将多个小型的逻辑写合并成一次大型的物理磁盘写入。关于该问题的进一步讨论可以参考 ACM Queue article,他们发现实际上顺序磁盘访问在某些情况下比随机内存访问还要快

为了弥补这种性能差异,现代操作系统在越来越注重使用内存对磁盘进行 cache。现代操作系统主动将所有空闲内存用作 disk caching,代价是在内存回收时性能会有所降低。所有对磁盘的读写操作都会通过这个统一的 cache。如果不使用直接I/O,该功能不能轻易关闭。因此即使进程维护了 in-process cache,该数据也可能会被复制到操作系统的 pagecache 中,事实上所有内容都被存储了两份。

此外,Kafka 建立在 JVM 之上,任何了解 Java 内存使用的人都知道两点:

  1. 对象的内存开销非常高,通常是所存储的数据的两倍(甚至更多)。
  2. 随着堆中数据的增加,Java 的垃圾回收变得越来越复杂和缓慢。

受这些因素影响,相比于维护 in-memory cache 或者其它结构,使用文件系统和 pagecache 显得更有优势--我们可以通过自动访问所有空闲内存将可用缓存的容量至少翻倍,并且通过存储紧凑的字节结构而不是独立的对象,有望将缓存容量再翻一番。这样使得32GB的机器缓存容量可以达到28-30GB,并且不会产生额外的 GC 负担。此外,即使服务重新启动,缓存依旧可用,而 in-process cache 则需要在内存中重建(重建一个10GB的缓存可能需要10分钟),否则进程就要从 cold cache 的状态开始(这意味着进程最初的性能表现十分糟糕)。这同时也极大的简化了代码,因为所有保持 cache 和文件系统之间一致性的逻辑现在都被放到了 OS 中,这样做比一次性的进程内缓存更准确、更高效。如果你的磁盘使用更倾向于顺序读取,那么 read-ahead 可以有效的使用每次从磁盘中读取到的有用数据预先填充 cache。

这里给出了一个非常简单的设计:相比于维护尽可能多的 in-memory cache,并且在空间不足的时候匆忙将数据 flush 到文件系统,我们把这个过程倒过来。所有数据一开始就被写入到文件系统的持久化日志中,而不用在 cache 空间不足的时候 flush 到磁盘。实际上,这表明数据被转移到了内核的 pagecache 中。

这种 pagecache-centric 的设计风格出现在一篇关于 Varnish 设计的文章中。

消息系统使用的持久化数据结构通常是和 BTree 相关联的消费者队列或者其它用于存储消息源数据的通用随机访问数据结构。BTree 是最通用的数据结构,可以在消息系统能够支持各种事务性和非事务性语义。虽然 BTree 的操作复杂度是 O(log N),但成本也相当高。通常我们认为 O(log N) 基本等同于常数时间,但这条在磁盘操作中不成立。磁盘寻址是每10ms一跳,并且每个磁盘同时只能执行一次寻址,因此并行性受到了限制。因此即使是少量的磁盘寻址也会很高的开销。由于存储系统将非常快的cache操作和非常慢的物理磁盘操作混合在一起,当数据随着 fixed cache 增加时,可以看到树的性能通常是非线性的——比如数据翻倍时性能下降不只两倍。

所以直观来看,持久化队列可以建立在简单的读取和向文件后追加两种操作之上,这和日志解决方案相同。这种架构的优点在于所有的操作复杂度都是O(1),而且读操作不会阻塞写操作,读操作之间也不会互相影响。这有着明显的性能优势,由于性能和数据大小完全分离开来——服务器现在可以充分利用大量廉价、低转速的1+TB SATA硬盘。虽然这些硬盘的寻址性能很差,但他们在大规模读写方面的性能是可以接受的,而且价格是原来的三分之一、容量是原来的三倍。

在不产生任何性能损失的情况下能够访问几乎无限的硬盘空间,这意味着我们可以提供一些其它消息系统不常见的特性。例如:在 Kafka 中,我们可以让消息保留相对较长的一段时间(比如一周),而不是试图在被消费后立即删除。正如我们后面将要提到的,这给消费者带来了很大的灵活性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kafka设计思想主要包括以下几个方面: 1. 高吞吐量:Kafka设计为一个高吞吐量的消息系统,能够处理大规模的数据流。它通过有效地利用磁盘和内存,并实现了零拷贝技术,来提供极高的数据吞吐能力。 2. 分布式架构:Kafka采用分布式的架构,可以在多台服务器上运行多个实例组成一个集群。每个实例都负责一部分的数据和请求处理,从而实现了数据的水平扩展和负载均衡。 3. 分区和复制:Kafka将每个主题(topic)分成一个或多个分区(partition),每个分区可以在不同的服务器上进行复制。这样既能够提高系统的可靠性和容错性,又能够支持大规模数据的并行处理。 4. 持久化存储:Kafka使用了持久化的消息存储机制,在消息发送后会将消息写入磁盘进行持久化存储。这样可以保证即使在消息发送后发生故障,消息也不会丢失。 5. 灵活的消费模型:Kafka支持多种消费模型,包括发布-订阅模型和消息队列模型。在发布-订阅模型中,一个消息可以被多个消费者订阅并处理;在消息队列模型中,每个消费者只能消费一个消息。 6. 高并发性:Kafka能够支持大规模的并发读写操作,可以同时处理数千个客户端的请求。它通过多线程和分区的方式来实现高并发操作。 通过以上设计思想Kafka能够提供高性能、可靠性和可扩展性的消息传输和处理能力,广泛应用于日志收集、实时分析、数据流处理等场景。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值