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可以判断当前数据是否已经存在。)
posted @ 2016-05-04 20:27  逸新  阅读(446)  评论(0编辑  收藏  举报