消息队列的作用

异步、削峰填谷、解耦

基本概念

  1. producer
    生产者在默认情况下把消息均衡地分布到主题的所有分区上:

    • 直接指定消息的分区

    • 根据消息的key散列取模得出分区

    • 轮询指定分区。

  2. consumer
    消费者通过偏移量来区分已经读过的消息,从而消费消息。把每个分区最后读取的消息偏移量保存在Zookeeper 或Kafka上,如果消费者关闭或重启,它的读取状态不会丢失。

  3. broker
    连接生产者和消费者,单个broker可以轻松处理数千个分区以及每秒百万级的消息量。

    • broker接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。

    • broker为消费者提供服务,响应读取分区的请求,返回已经提交到磁盘上的消息。

  4. topic
    通过主题进行分类,类似数据库中的表。

  5. consumer group
    消费组保证每个分区只能被一个消费者使用,避免重复消费。如果群组内一个消费者失效,消费组里的其他消费者可以接管失效消费者的工作再平衡,重新分区。

  6. partition

    • Topic可以被分成若干分区分布于kafka集群中,方便扩容

    • 单个分区内是有序的,partition设置为一才能保证全局有序

  7. offset

    • 生产者offset,消息写入的时候,每一个分区都有一个offset,即每个分区的最新最大的offset。

    • 消费者offset,不同消费组中的消费者可以针对一个分区存储不同的Offset,互不影响。

  8. 副本Replicas

    每个主题被分为若干个分区,每个分区有多个副本。

  9. 集群

    每隔分区都有一个首领,当分区被分配给多个broker时,会通过首领进行分区复制。

  10. LogSegment

    • 一个分区由多个LogSegment组成,

    • 一个LogSegment由.log .index .timeindex组成

    • .log追加是顺序写入的,文件名是以文件中第一条message的offset来命名的

    • .Index进行日志删除的时候和数据查找的时候可以快速定位。

    • .timeStamp则根据时间戳查找对应的偏移量。

kafka特点

  1. 高吞吐量、低延迟:kafka每秒可以处理几十万条消息,它的延迟最低只有几毫秒,每个topic可以分多个partition,由多个consumer group对partition进行conse操作

  2. 可扩展性:kafka集群支持热扩展

  3. 持久性、可靠性:消息被持久化到本地磁盘,并且支持数据备份防止数据丢失

  4. 容错性:允许集群中节点失败(若副本数量为n,则允许n-1个节点失败)

  5. 高并发:支持数千个客户端同时读写

kafka为什么快

  1. 分布式架构:可以将数据分布到多个节点上进行处理,从而实现数据的水平扩展和负载均衡,能够处理大量的消息数据

  2. 零拷贝:在数据传输过程中,避免将数据从内核空间复制到用户空间,直接将数据从发送方的内存映射到接受方的内存,避免了数据的多次复制和传输,提高了数据传输的效率。

  3. 批量发送:支持批量发送,即将多个消息一起发送到服务器端,减少了网络传输的开销,同时也减少了磁盘I/O次数,提高了数据传输的效率。

  4. 数据压缩:可以将消息在发送前进行压缩,减小消息体积,提高网络传输的效率。

  5. 消息存储:采用持久化的消息存储方式,将消息保存到磁盘中,保证了数据的可靠性和恢复性,同时也避免了内存容量的限制。

    总结:kafka速度的秘诀在于,他把所有的消息都变成一个批量的文件,并且进行合理的批量压缩,减少网络IO损耗,通过mmap提高IO速度,写入数据的时候由于单个Partion是末尾添加所以速度最优;读取数据的时候配合sendfile直接暴力输出。

kafka设计

  1. 磁盘性能

    1. 持久化,kafka对消息的存储和缓存严重依赖文件系统,顺序磁盘访问在某些情况下比随机内存访问还要快,kafka的持久化队列建立在简单的读取和向文件后追加的两种操作,这种架构优点在于所有操作复杂度都是O(1),而且读写操作不会阻塞。

    2. kafka建立在JVM之上,JVM对象内存开销很高,随着堆中数据增加,java垃圾回收会变慢,相比于维护尽可能多的 in-memory cache,并且在空间不足的时候匆忙将数据 flush 到文件系统,我们把这个过程倒过来。所有数据一开始就被写入到文件系统的持久化日志中,而不用在 cache 空间不足的时候 flush 到磁盘。实际上,这表明数据被转移到了内核的 pagecache 中。

  2. 支持批量发送,可以配置批量的大小和延迟时间(比如64K,10ms)

    1. 通过少许的延迟来极大的提升性能,这个简单的优化对速度有着数量级的提升。

    2. 批处理允许更大的网络数据包,更大的顺序读写磁盘操作,连续的内存块等等。

    3. 减少了网络多次传输的开销

    4. 减少了磁盘I/O次数,大量的小型操作I/O

  3. 零拷贝

    1. 使用linux的sendFile系统调用减少了数据拷贝和上下文切换

    2. 传统的读写操作需要四次copy操作,两次系统调用,4次上下文切换,kafka只需要一次copy,从pagecache到NIC缓冲区。

  4. 数据压缩

    1. 某些情况下,数据传输的瓶颈不是CPU,也不是磁盘,而是网络带宽。kafka以高效的批处理格式支持一批消息可以压缩到一起发送到服务器。这批消息将以压缩格式写入,并且在日志中保持压缩,只会在consumer消费时解压缩。

  5. 分布式架构,支持集群部署,多个分区。

kafka是如何保证可靠性和一致性

  1. 写入确认机制ACK,0,1,all

  2. 复制机制,每个分区的副本被复制到多个broker上,当主副本故障时,kafka自动将副本升到主副本,不会导致数据丢失

  3. ISR 机制,Kafka维护一个ISR列表,其中包含了所有和主副本保持同步的副本,只有ISR列表中的副本才能被选举为主副本。

  4. 消费者确认机制,ack