zoukankan      html  css  js  c++  java
  • kafka设计思想

    动机###

    • 为了做一个公共、统一、可以支持庞大数据量、实时的平台。
    • 需要具备高吞吐量来支持庞大的事件流
    • 可以处理积压数据,可以缓存数据,用来支持周期性从线下load进来的数据
    • 系统为了处理更多的消息,不得不低延时提交数据???
    • 我们想让系统支持,分区、分布式、实时处理新增以及衍生的消息,因此设计了分区和消费模式。
    • 因为是分布式,所以需要支持容错机制
    • 当满足以上支持条件后,kafka更像是一个日志数据库。

    持久化###

    • kafka使用磁盘来存储和缓存消息。
    • 线性读写的速度是随机读写的6000倍
    • http://queue.acm.org/detail.cfm?id=1563874,在这篇文章中介绍,线性读写磁盘的速度近乎赶得上随机内存访问
    • kafka是基于jvm之上的,因此也有如下两个弊端
    • 数据对象要比数据占用更多的空间,有的时候会是原数据大小的一倍
    • 垃圾回收越来越复杂,特别是随着堆的增加,垃圾回收会越来越慢
    • 基于以上两个原因,我们选择磁盘存储和缓存数据。
    • 数据存储于磁盘,可以避免掉GC
    • 数据缓存于磁盘,当服务down掉后,重启可以重新运行,数据不丢失,如果缓存于内存,数据将会丢失,即使down掉前刷入磁盘,重新从磁盘load进内存也将花费很多时间。
    • 所有的日志数据一旦进来,立即刷入磁盘,并不会先尽量使用内存。
    • 传统的消息队列都会使用B树来管理消息,以便用来随机读取。B树 时间复杂度 0(log n),但是这个并不适用于磁盘操作。磁盘寻道大概要花费10ms,并且寻道不是并行的。
    • 使用无线空间的磁盘,kafka可以提供很多传统消息服务没有的特性。例如,在kafka中当消息被消费后不试图删除消息,我们可以保存消息一段时间(通常是一周),这样消费端就可以更灵活的消费消息。

    性能###

    • 排除掉磁盘读写过低的性能问题,还有两个性能问题。
    • 过多的微小的IO操作
    • 序列化
    • 为了降低IO的次数,kafka添加了消息集,这样可以一次性的将消息推送进服务端,而不像传统的消息服务,每次只能推送单条消息。这样还有一个好处,就是讲网络消耗均分,不会集中在一点。同样消费端也可以一次消费取大量的消息。数据块越大,线性读写的优势就越明显。
    • 序列化是消耗性能的另一个问题,为解决这个问题,kafka引入标准二进制消息协议,生产者将消息序列化后传给服务端。因此在生产者、消费者、服务端都是公用的,并且在传输过程中,消息是不可更改的。消息服务端只是维护这些消息二进制文件。
    • linux 从文件到socket流。 磁盘->kernel->user space -> kernel(socker buffer)-> nic buffer
    • sendfile 可以避免重复copy数据,可以直接从包缓存到网络,只有NICbuffer是必须的。这样可以提高消费消息的效率
    • kafka提供了数据压缩,基于消息集合的压缩

    生产者###

    • 负载均衡
    • kafka的消息是直接传送给broker的,不经过任何中间路由,为此,所有的kafka节点需要返回,哪个节点是存活的,主节点和消息的分片都在哪。然后生产者直接请求分片即可。(与hdfs的设计相同)
    • kafka提供基础分片方式,通过key进行hash。
    • 异步发送

    异步发送是为了满足一次性传输大的消息集合。通过异步的方式可以提高吞吐量。

    消费者###

    • 推送和拉取的抉择
    • kafka采用拉取的方式来消费消息。
    • 拉取方式可以配合消息集使用。
    • 拉取消息的缺陷是为了更快的响应,需要不停地轮询消息队列,即便当前消息队列没有消息。如果当前拉取数据时消息队列中没有消息,则kafka会在拉取时阻塞,知道有数据。(保持长连接)
    • 除此之外还有一些别消息传输,例如:生产者,生产并存储消息进生产自身磁盘中,当消费者拉取消息的时候,服务端从生产者服务器拉取。不过这种方式不适合多生产者。数据非常散,不易管理。
    • 记录消费位置
    • 大部分消息系统会将消息是否已消费,消费到哪了,记录在broker中。这有很多弊端:每当一个一个消息被消费后,服务端除了自己要记录下来以外,还需要等待消费的ack确认。因此,这种设计在集群化的消息系统中效率是很低下的,这种设计又是必须的,因为服务端需要知道哪些消息已经被消费了,可以删除这些消息了,这样才能保证broker中的数据足够小。
    • 常规的消息系统为了需要维护消息的多种状态(已发送,已确认),并且有消费多次的可能性(消费消息后发送ack失败)
    • kafka将消息进行分区,每个分区只有一个消费者。拉取的方式只是为消费者记录一个位置即可。
    • kakfa提供重复消费消息的功能。
    • 加载离线数据
    • kafka可以作为离线数据,用作hadoop MR的输入。

    消息传递的真谛###

    • kafka通过在消息上标记唯一key来避免重复传输。(当网络出现故障后,重新传入数据,通过key可以判断当前数据是否已经存在。)
  • 相关阅读:
    Hitachi Programming Contest 2020 E Odd Sum Rectangle
    CF1060F Shrinking Tree
    UR #19
    AGC041F Histogram Rooks
    JOISC2020 Legendary Dango Maker
    Dinic 二分图匹配 / Hopcroft-Karp 算法 复杂度简单证明
    Codechef March Challenge 2020 Division 1 BREAK
    Tomorrow will be fine.
    JOISC2019 穿越时空 Bitaro
    POI2011 Periodicity
  • 原文地址:https://www.cnblogs.com/isenhome/p/5459674.html
Copyright © 2011-2022 走看看