Kafka学习总结

本文为Kafka学习总结

一、Kafka简介

Apache Kafka是分布式发布-订阅消息系统,是一种快速、可扩展的、设计内在就是分布式的,分区的和可复制的提交日志服务
1)同时为发布和订阅提供高吞吐量
2)可进行持久化操作。将消息持久化到磁盘,因此可用于批量消费,例如ETL,以及实时应用程序。通过将数据持久化到硬盘以及副本中以防止数据丢失
3)分布式系统,易于向外扩展。所有的Producer、Broker和Consumer都会有多个,均为分布式的。无需停机即可扩展机器
4)消息被处理的状态是在Consumer端维护,而不是由Server端维护。当失败时能自动平衡
5)支持online和offline的场景

二、Kafka基本概念

在这里插入图片描述
图中:
1)Topic:特指Kafka处理的消息源(feeds of messages)的不同分类

  • 一个Topic可以认为是一类消息,每个Topic将被分成多Partition(区),每个Partition在存储层面是append log文件。任何发布到此Partition的消息都会被直接追加到log文件的尾部,每条消息在文件中的位置称为offset(偏移量),Partition是以文件的形式存储在文件系统中
  • log文件根据Broker中的配置要求,保留一定时间后删除来释放磁盘空间

2)Partition:Topic 物理上的分组,一个Topic可以分为多个Partition,每个Partition是一个有序的队列。Partition中的每条消息都会被分配一个有序的id(offset)

  • Kafka基于文件存储。通过分区,可以将日志内容分散到多个Server上,来避免文件尺寸达到单机磁盘的上限,每个Partition都会被当前Server(Kafka实例)保存
  • 越多的Partition意味着可以容纳更多的Consumer,有效提升并发消费的能力
  • Partition有N个副本(replication)。N个replication中,其中一个replication为leader,其他都为follower,leader处理Partition的所有读写请求,follower定期地去复制leader上的数据。如果leader发生故障或挂掉,一个新leader会被选举并接收客户端的消息写入。通过分区副本,引入了数据冗余,同时也提供了Kafka的数据可靠性
  • 在定义Producer时通过acks参数来指定消息发送到对应分区的几个副本才算消息发送成功:acks = 0意味着消息只要通过网络发送出去,Producer无需等待确认即可发送下一批消息;acks = 1意味着leader成功收到数据并确认后Producer才可发送下一批消息;acks = all或-1意味着所有同步副本都成功收到数据并确认后Producer才可发送下一批消息

3)Message:消息,是通信的基本单位。每个Producer可以向一个Topic(主题)发布一些消息

  • Kafka中的Message是以Topic为基本单位组织的,不同的Topic之间是相互独立的。每个Topic又可以分成几个不同的Partition(每个Topic有几个Partition是在创建Topic时指定的),每个Partition存储一部分Message
  • Partition中的每条Message包含了以下三个属性:
    offset 对应类型:long
    MessageSize 对应类型:int32
    data 是message的具体内容

4)Producer:消息和数据生产者

  • Producer将消息发布到指定的Topic中,同时也决定将此消息归属到哪个Partition(基于Hash算法等)
  • Producer支持批量发送,先将消息缓存在内存中,然后一次请求批量将消息发送出去

5)Consumer:消息和数据消费者

  • 每个Consumer属于一个Consumer Group。反过来说,每个Consumer Group中可以有多个Consumer。发送到Topic的消息,只会被订阅此Topic的每个Consumer Group中的一个Consumer消费
  • 在Kafka中,可以认为一个Consumer Group是一个订阅者,对于一个Topic中的每个Partition,只能被Consumer Group中的一个Consumer所消费,不过一个Consumer可以消费多个Partition中的消息。Kafka的设计原理决定,对于一个Topic,同一个Consumer Group中不能有多于Partition个数的Consumer同时消费,否则将意味着某些Consumer将无法得到消息
  • Kafka只能保证一个Partition中的消息被某个Consumer消费时,消息是顺序的。事实上,从Topic角度来说,消息仍不是有序的
  • 多个Consumer Group对一个Topic进行消费时,不同的Consumer Group之间独立订阅
  • 为了对减小一个Consumer Group中不同Consumer之间的分布式协调开销,指定Partition为最小的并行消费单位,即一个Consumer Group内的Consumer只能消费不同的Partition

6)Broker:缓存代理,Kafka集群中的一台或多台服务器统称为Broker

  • 为了减少磁盘写入的次数,Broker会将消息暂时缓存起来,当消息的个数(或尺寸)达到一定阈值时,再刷新到磁盘中,这样减少了磁盘IO调用的次数
  • Broker没有副本机制,一旦Broker宕机,该Broker的消息将都不可用。Broker不保存订阅者的状态,由订阅者自己保存
  • 无状态导致消息的删除成为难题(可能删除的消息正在被订阅),Kafka采用基于时间的SLA(服务水平保证),消息保存一定时间(通常为7天)后会被删除
  • 消息订阅者可以倒退到任意位置重新进行消费,当订阅者故障时,可以选择最小的id(offset)进行重新读取消费消息

三、Kafka消息队列分类

1)点对点
消息生产者生产消息发送到Queue中,然后消息消费者从Queue中取出并且消费消息。消息被消费以后,Queue中不再有存储,所以消息消费者不可能消费到已经被消费的消息。Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费

2)发布/订阅
消息生产者(发布)将消息发布到Topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到Topic的消息会被所有订阅者消费

四、Kafka中offset的作用

1)什么是offset
每条消息在文件中的位置称为offset(偏移量)。offset为一个long型数字,它唯一标记一条消息

2)offset的作用
Partition中的每条Message由offset来表示它在这个Partition中的偏移量,这个offset不是该Message在Partition数据文件中的实际存储位置,而是逻辑上一个值,它唯一确定了Partition中的一条Message。因此,可以认为offset是Partition中Message的id。故消息定位=【Topic,Partition,offset】

五、数据传输的事务定义

1)at most once:消息最多发送一次,这个和JMS中“非持久化”消息类似。发送一次,无论成败,将不会重发

  • 消费者fetch消息,然后保存offset,然后处理消息;当Client保存offset之后,但是在消息处理过程中出现了异常,导致部分消息未能继续处理。那么此后未处理的消息将不能被fetch到,这就是at most once

2)at least once:消息至少发送一次,如果消息未能接受成功,可能会重发,直到接收成功

  • 消费者fetch消息,然后处理消息,然后保存offset。如果消息处理成功之后,但是在保存offset阶段ZooKeeper异常导致保存操作未能执行成功,这就导致接下来再次fetch时可能获得上次已经处理过的消息,这就是at least once,原因offset没有及时的提交给ZooKeeper,ZooKeeper恢复正常还是之前offset状态

3)exactly once:消息只会发送一次,保证消息处理和提交反馈在同一个事务中,即有原子性

  • Kafka在0.11.0版本以上实现了此功能,即幂等的Producer还有对事务的支持。kafka 0.11.0.0版本引入了Idempotent Producer机制,设置Producer端的参数enable.idempotent为true即可开启。在这个机制中同一消息可能被Producer发送多次,但是在Broker端只会写入一次,它为每一条消息编号去重,而且对Kafka开销影响不大。而对于多分区的情况,我们需要保证原子性的写入多个分区,即写入到多个分区的消息要么全部成功,要么全部回滚。这时候就需要使用事务,在Producer端设置transcational.id为一个指定字符串,这样幂等Producer可以保证单分区上无重复消息;事务可以保证多分区写入消息的完整性。这样Producer端实现了exactly once,那么Consumer端呢?Consumer端由于可能无法消费事务中所有消息,并且消息可能被删除,所以事务并不能解决Consumer端exactly once的问题,我们可能还是需要自己处理这方面的逻辑。比如自己管理offset的提交,不要自动提交,也是可以实现exactly once的

注:通常情况下at least once是我们首选(相比at most once而言,重复接收数据总比丢失数据要好),但对数据要求比较严格的场景来说,需要实现exactly once

六、Kafka的存储策略

在这里插入图片描述
1)Kafka以Topic来进行消息管理,每个Topic包含多个Partition,每个Partition对应一个逻辑log,有多个segment组成
2)每个segment中存储多条消息(见上图),消息id由其逻辑位置决定,即从消息id可直接定位到消息的存储位置,避免id到位置的额外映射
3)Broker收到发布消息往对应Partition的最后一个segment上添加该消息
4)每个Partition在内存中对应一个index,记录每个segment中的第一条消息偏移
5)发布者发到某个Partition的消息会被均匀的分布到多个Partition上(随机或根据用户指定的回调函数进行分布),Broker收到发布消息往对应Partition的最后一个segment上添加该消息,当某个segment上的消息条数达到配置值或消息发布时间超过阈值时,segment上的消息会被flush到磁盘,只有flush到磁盘上的消息订阅者才能订阅到,segment达到一定的大小后将不会再往该segment写数据,Broker会创建新的segment

七、Kafka消息发送处理流程

由于Broker会持久化数据且没有内存压力,因此,Consumer非常适合采取pull的方式消费数据
1)Producer向Kafka推(push)数据
2)Consumer从Kafka拉(pull)数据

优势:
1)简化Kafka设计
2)Consumer根据消费能力自主控制消息拉取速度
3)Consumer根据自身情况自主选择消费模式,例如批量,重复消费,从尾端开始消费等
4)Kafka集群接收到Producer发过来的消息后,将其持久化到硬盘,并保留消息指定时长(可配置),而不关注消息是否被消费

八、Kafka数据持久化

很多时候发现线性的访问磁盘,比随机的内存访问快得多。传统的方式使用内存做为磁盘的缓存,而Kafka直接将数据写入到日志文件中

写操作:
通过将数据追加到文件中实现
读操作:
直接从文件中读取

JVM特性:
Java对象占用空间是非常大的,差不多是要存储的数据的两倍甚至更高,随着堆中数据量的增加,垃圾回收回变的越来越困难
Kafka对其来说的优势:
1)Kafka读操作不会阻塞写操作和其他操作,数据大小不对性能产生影响
2)没有容量限制(相对于内存来说)的硬盘空间建立消息系统
3)线性访问磁盘,速度快,可以保存任意一段时间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值