Kafka
基本介绍
Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以收集并处理用户在网站中的所有动作流数据以及物联网设备的采样信息。
Kafka提供了消息的订阅与发布的消息队列,一般用作系统间解耦、异步通信、削峰填谷等作用。还提供了Kafka streaming插件包实现了实时在线流处理,Kafka Streaming计算是运行在应用端,具有简单、部署方便的优点。
消息队列
消息队列工作模式大致分为两类
- 至多一次:消息生产者将数据写入消息系统,然后由消费者负责去拉去消息服务器中的消息,一旦消息被确认消费之后 ,由消息服务器主动删除队列中的数据,这种消费方式一般只允许被一个消费者消费,并且消息队列中的数据不允许被重复消费。
- 没有限制:生产者发布完数据以后,该消息可以被多个消费者同时消费,并且同一个消费者可以多次消费消息服务器中的同一个记录(消息服务器一般可以长时间存储海量消息)。
Topic
Topic存放结构
- Kafka集群以Topic形式负责分类集群中的Record每一个Record属于一个Topic。每个Topic底层都会对应一组分区的日志用于持久化Topic中的Record。同时在Kafka集群中,Topic的每一个日志的分区都一定会有1个Borker担当该分区的Leader,其他的Broker担当该分区的follower,Leader负责分区数据的读写操作,follower负责同步该分区的数据。这样如果分区的Leader宕机,该分区的其他follower会选取出新的leader继续负责该分区数据的读写。其中集群中对Leader的监控和Topic的部分元数据是存储在Zookeeper中。
生产消息数据存储
- Kafka中所有消息是通过Topic为单位进行管理,每个Kafka中的Topic通常会有多个订阅者,负责订阅发送到该Topic中的数据。Kafka负责管理集群中每个Topic的一组日志分区数据。
- 生产者将数据发布到相应的Topic。Kafka负责选择将哪个记录分发送到Topic中的哪个Partition。
- 每组日志分区是一个有序的不可变的的日志序列,分区中的每一个Record都被分配了唯一的序列编号称为是offset,Kafka 集群会持久化所有发布到Topic中的Record信息,该Record的持久化时间是通过配置文件指定,默认是168小时。Kafka底层会定期的检查日志文件,然后将过期的数据从log中移除。
消费者消费数据
- 消费者消费Topic中数据的时候,每个消费者会维护本次消费对应分区的偏移量,消费者会在消费完一个批次的数据之后,会将本次消费的偏移量提交给Kafka集群,因此对于每个消费者而言可以随意的控制改消费者的偏移量。因此在Kafka中,消费者可以从一个topic分区中的任意位置读取队列数据,由于每个消费者控制了自己的消费的偏移量,因此多个消费者之间彼此相互独立。
Topic分区优点
- 允许日志扩展到超出单个服务器所能容纳的大小。每个单独的分区都必须适合托管它的服务器,但是一个Topic可能有很多分区,它可以处理任意数量的数据。
- 每个服务器充当其某些分区的Leader,也可能充当其他分区的Follwer,集群中的负载得到了很好的平衡。
Consumer
消费组
- 消费者使用Consumer Group名称标记自己,并且发布到Topic的每条记录都会传递到每个订阅Consumer Group中的一个消费者实例。如果所有Consumer实例都具有相同的Consumer Group,那么Topic中的记录会在该ConsumerGroup中的Consumer实例进行均分消费;如果所有Consumer实例具有不同的ConsumerGroup,则每条记录将广播到所有Consumer Group进程。
- 每个Consumer Group均由许多Consumer实例组成,具有可伸缩性和容错能力。Kafka会将Topic按照分区的方式均分给一个Consumer Group下的所有实例,如果ConsumerGroup下有新的成员介入,那么新介入的Consumer实例会去接管ConsumerGroup内其他消费者负责的某些分区,如果ConsumerGroup下的有其他Consumer实例宕机,则由ConsumerGroup其他实例接管。
- 由于Kafka的Topic的分区策略,因此Kafka仅提供分区中记录的有序性,相同Topic的不同分区记录之间无顺序。如果需要记录全局有序,可以通过只有一个分区Topic来实现,同时每个ConsumerGroup只有一个Consumer进程。
数据存储特性
磁盘写入特性
- Kafka可以,支持每秒百万级的写入请求,Kafka会把收到的消息都写入到硬盘中,防止丢失数据。为了优化写入速度Kafka采用了顺序写入和MMFile技术。
- 为了提高读写硬盘的速度,Kafka就是使用顺序I/O。这样省去了大量的内存开销以及节省了IO寻址的时间。但是单纯的使用顺序写入也不可能和内存进行对比,因此Kafka的数据并不是实时的写入硬盘中。
- Kafka利用了操作系统分页存储来利用内存提高I/O效率,Memory Mapped Files称为内存映射文件(在64位操作系统中一般可以表示20G的数据文件),工作原理是直接利用操作系统的Page实现文件到物理内存的直接映射。完成MMF映射后,用户对内存的所有操作会被操作系统自动的刷新到磁盘上,极大地降低了IO使用率。
磁盘读取特性
- 在读取时,使用了数据零拷贝技术,磁盘的数据无需拷贝到用户空间,而是直接将数据通过内核空间传递输出。
零拷贝:
- 1、文件在磁盘中数据被copy到内核缓冲区
- 2、从内核缓冲区copy到内核与socket相关的缓冲区。
- 3、数据从socket缓冲区copy到相关协议引擎发送出去
DMA读取:本质DMA替代CPU干活,解放CPU。
- 1.用户进程调用读取等系统调用向操作系统发出IO请求,请求读取数据到自己的内存缓冲区中。自己进入阻塞状态。
- 2.操作系统收到请求后,进一步将IO请求发送DMA。然后让CPU干别的活去。
- 3.DMA进一步将IO请求发送给磁盘。
- 4.磁盘驱动器收到DMA的IO请求,把数据从磁盘读取到驱动器的缓冲中。当驱动器的缓冲区被读满后,向DMA发起中断信号告知自己缓冲区已满。
- 4.DMA收到磁盘驱动器的信号,将磁盘驱动器的缓存中的数据拷贝到内核缓冲区中。此时不占用CPU。这个时候只要内核缓冲区的数据少于用户申请的读的数据,内核就会一直重复步骤3跟步骤4,直到内核缓冲区的数据足够多为止。
- 5.当DMA读取了足够多的数据,就会发送中断信号给CPU。
- 6.CPU收到DMA的信号,知道数据已经准备好,于是将数据从内核拷贝到用户空间,系统调用返回。