kafka学习笔记

来源:互联网 发布:linux 虚拟机内存占用 编辑:程序博客网 时间:2024/05/21 16:23
1.消息队列的特点
生产者消费者模式
先进先出(FIFO)顺序保证
可靠性保证
  • -自己不丢数据(数据不经过内存,直接存储到磁盘)
  • -消费者不丢数据:“至少一次,严格一次”

2.消息队列常用场景:
  • 系统间解耦(queue模型、publish-subscribe模型)
  • 峰值压力缓冲
  • 异步通信

3.kafka
一个高吞吐的分布式消息系统(publish-subscribe模型)
kafka架构
  • producer:消息生产者
  • consumer:消息消费者
  • broker:kafka集群的server,负责处理消息读写请求,存储消息
  • topic:消息队列/分类
broker就是代理,在kafka cluster这一层里,其实就是有很多个broker
topic相当于queue
上图中没有画ZooKeeper,这个架构里面有些元信息是存储在ZooKeeper上面的额,整个集群和ZooKeeper有很大关系

4.kafka的消息存储和生产消费模型
  • 一个topic分成多个partition
  • 每个partition内部消息强有序,其中的每个消息有一个序号叫offset
  • 一个partition对应一个broker,一个broker可以管多个partition
  • 消息不经过内存缓冲,直接写入文件
  • 根据时间策略删除(默认是7天),而不是消费完就删除
  • producer自己决定往哪个partition写消息,可以是轮询的负载均衡,或者是基于hash的partition策略

consumer自己维护消费到哪个offset
每个consumer都有对应的group
group内是queue消费模型
--各个consumer消费不同的partition
--因此一个消息在group内只消费一次
group间是publish-subscribe模型
--各个group各自独立消费,互不影响
--因此一个消息在被每个group消费一次

5.kafka特点
消息系统的特点:生产者消费者模型,FIFO
高性能:单节点支持上千个客户端,百MB/s的吞吐
持久性:消息直接持久化到普通磁盘且性能好
分布式:数据副本冗余,流量负载均衡,可扩展
很灵活:消息长时间持久化+client维护消费状态
1)负载均衡
  • producer根据用户指定的算法,将消息发送到指定的partition
  • 存在多个partiiton,每个partition有自己的replica,每个replica分布在不同的Broker节点上
  • 多个partition需要选取出lead partition,lead partition负责读写,并由zookeeper负责fail over
  • 通过zookeeper管理broker与consumer的动态加入与离开
2)当需要增加broker结点时,新增的broker会向zookeeper注册,而producer及consumer会根据注册在zookeeper上的watcher感知这些变化,并及时作出调整。

6.Kafka与其他消息队列对比
RabbitMQ:分布式,支持多种MQ协议,重量级
ActiveMQ:与RabbitMQ类似
ZeroMQ:以库的形式提供,持久性差
redis:单机、纯内存,持久性差
kafka:分布式、较长时间持久化,高性能,轻量灵活
注:ZeroMQ是一个socket的通信库,它是以库的形式提供的,需要写程序来实现消息系统,它只管内存和通信那一块,持久化也得自己写。storm0.9之前,那些spout和bolt,bolt和bolt之间那些底层的通信就是由ZeroMQ来通信的,它并不是一个消息队列,就是一个通信库,在0.9之后呢,因为license的原因,ZeroMQ就由Netty取代了,Netty本身就是一个网络通信库嘛,所以说更合适是在通信库这一层,不应该是MessageQueue这一层

消费状态谁来维护Client vs.Server

kafka写磁盘是顺序的,所以不断的往前产生,不断的往后写,kafka还使用了sendFile的0拷贝技术,提高速度,而且还用到了批量读写,每次网络传输量不会特别小,RTT(Round-Trip-TIme)的开销就微不足道了,对文件的操作不会是很小的IO,也会是比较大的IO

7.零拷贝
零拷贝是指计算机操作的过程中,CPU不需要为数据在内存之间的拷贝消耗资源。而它通常是指在网络发送文件时,不需要讲文件内容拷贝到用户空间而直接在内核空间中传输到网络的方式

Linux中的sendfile()以及Java NIO中的FileChannel.transferTo()方法都实现了零拷贝的功能,而在Netty中也通过在FileRegion中包装了NIO的FileChannel.transferTo()方法实现了零拷贝