Kafka总结

                                           Kafka总结

 

一.消息队列Message Queue

两种模式

  1. 点对点模式
    点对点模式是一个基于拉取或轮询的消息传送模型,由消费者主动拉取数据,客户端需要实时开启一个线程监控队列中是否有数据。
  2. 发布/订阅模式
    发布/订阅模式是一个基于推送的消息传送模型,由MQ主动推送消息给所有订阅者,即使当前订阅者不可用。

优点

  • 解耦
    允许你独立的扩展或修改两边的处理过程,只要确保它们遵循同样的接口约束。
  • 冗余
    MQ把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。
  • 扩展
    因为MQ解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可,提高了灵活性和峰值处理能力。
  • 可恢复性
    消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
  • 顺序保证
    队列本身就遵循FIFO的原则,保证了数据的处理顺序。
  • 缓冲
    有助于控制和优化数据流经过系统的速度,解决生产者和消费者处理速度不一致的问题。
  • 异步通信
    MQ提供了异步处理机制,允许用户把消息放入队列但不立即处理它,直到需要时再去处理。

 

二.Kafka简介

  • Apache Kafka是一个开源消息系统,是由Apache软件基金会开发的一个开源消息系统项目。
  • Kafka最初是由LinkedIn公司开发,并于2011年初开源。2012年10月从Apache Incubator毕业。该项目的目标是为处理实时数据提供一个统一、高通量、低等待的平台。
  • Kafka是一个Distributed Message Queue。Kafka对消息保存时根据Topic进行归类,发送消息者称为Producer,消息接收者称为Consumer,此外Kafka集群有多个Kafka实例组成,每个实例称为Broker。
  • Kafka需要依赖于Zookeeper保存一些Meta信息,来保证系统可用性。
  • 在流式计算中,Kafka一般用来缓存数据,Storm通过消费Kafka的数据进行计算。

 

三.Kafka架构

No.组件说明
1Producer消息生产者,向Kafka中发消息的客户端。
2Consumer消息消费者,从Kafka中取消息的客户端。
3Broker一台Kafka服务器就是一个Broker,一个集群由多个Broker组成,一个Broker可以容纳多个Topic。
4Topic属于特定类别的消息流称为Topic, 数据存储在Topic中,可以理解为一个队列。
5Partition为了实现负载均衡和高并发,一个非常大的Topic可以通过分为多个Partition分布到多个Broker上,每个Partition都是一个有序的队列。
6Consumer Group(CG)这是Kafka用来实现一个消息的广播(发给所有Consumer)和单播(发给任意一个Consumer)的手段。一个Topic可以有多个CG,Topic中的消息会复制(不是真的复制,是概念上的)到所有的CG,但每个Partition只会把消息发给该CG中的一个Consumer。如果需要实现广播,只要每个Consumer都有一个独立的CG即可,需要实现单播,只要所有Consumer都在同一个CG即可。用CG还可以将Consumer进行自由分组而不需要重复发送消息到不同的Topic。
7OffsetPartition中的每条消息都会被分配一个有序的id(Offset)。Kafka只保证每个Partition中的顺序,不保证多个Partition的顺序。
8Leader负责给定Partition的所有读取和写入的节点。
9Follower跟随Leader指令的节点被称为Follower。 如果Leader节点宕机,其中一个Follower将通过选举自动成为新的Leader。

 

四.Kafka工作流程

Producer生产过程

  1. 写入方式
    Producer采用Push模式将消息发布到Broker,每条消息都被追加(append)到Partition中,属于顺序写磁盘(顺序写磁盘效率比随机写内存要高,保障Kafka吞吐率)。
  2. 分区(Partition)
    消息发送时都被发送到一个topic,其本质就是一个目录,而topic是由一些Partition Logs(分区日志)组成,其组织结构如下图所示:

     

     

     

     

     

    我们可以看到,每个Partition中的消息都是有序的,生产的消息被不断追加到Partition log上,其中的每一个消息都被赋予了一个唯一的offset值。

    1. 分区的原因
      1. 负载均衡,方便在集群中扩展,每个Partition可以通过调整以适应它所在的机器,而一个Topic又可以有多个Partition组成,因此整个集群就可以适应任意大小的数据了。
      2. 可以提高并发,因为可以以Partition为单位读写了。
    2. 分区的原则
      1. 已指定Partition,则直接使用该Partition。
      2. 未指定Partition但指定了Key,则通过对Key进行哈希计算得出一个Partition。
      3. Partition和Key都未指定,则轮询选出一个Partition。
  3. 副本(Replication)
    同一个Partition可能会有多个Replication(对应server.properties配置中的default.replication.factor=N)。没有Replication的情况下,一旦Broker宕机,其上所有Partition的数据都不可被Consumer消费,同时Producer也不能再将数据存于其上的Partition。引入Replication之后,同一个Partition可能会有多个Replication,而这时需要在这些Replication之间选出一个Leader,Producer和Consumer只与这个Leader交互,其它Replication作为Follower从Leader中复制数据。
  4. 写入流程

     

     

Broker保存过程

  1. 存储方式
    物理上把Topic分成一个或多个Partition(对应server.properties配置中的num.partitions=3),每个Partition物理上对应一个文件夹(该文件夹存储该Partition的所有消息和索引文件),如下:

 

  1. 存储策略
    无论消息是否被消费,Kafka都会保留所有消息。有两种策略可以删除旧数据:

    1. 基于时间:log.retention.hours=168
    2. 基于大小:log.retention.bytes=1073741824

    需要注意的是,因为Kafka读取特定消息的时间复杂度为O(1),即与文件大小无关,所以这里删除过期文件与提高Kafka性能无关。

  2. Zookeeper存储结构

     

     

     

    注意:只有Broker和Consumer在Zookeeper中注册,Producer不在Zookeeper中注册。

Consumer消费过程

  1. 消费者组

     

        Consumer是以Consumer Group的方式工作,由一个或者多个Consumer组成一个Group,共同消费一个Topic。每个Partition在同一时间只能由Group中的一个Consumer读取,但是多个Group可以同时消费同一个Partition。在图中,有一个由三个Consumer组成的Group,有一个Consumer读取Topic中的两个Partition,另外两个Consumer分别读取一个Partition。某个Consumer读取某个Partition,也可以叫做某个Consumer是某个Partition的拥有者。
    在这种情况下,Consumer可以通过水平扩展的方式同时读取大量的消息。另外,如果一个Consumer失败了,那么Group中其它的Consumer会自动负载均衡读取之前失败的Consumer读取的Partition。

  2. 消费方式
    Consumer采用Pull模式从Broker中读取数据。
    Push模式很难适应消费速率不同的Consumer,因为消息发送速率是由Broker决定的。它的目标是尽可能以最快速度传递消息,但是这样很容易造成Consumer来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而Pull模式则可以根据Consumer的消费能力以适当的速率消费消息。
    对于Kafka而言,Pull模式更合适,它可简化Broker的设计,Consumer可自主控制消费消息的速率,同时Consumer可以自己控制消费方式——即可以批量消费也可以逐条消费,同时还能选择不同的提交方式从而实现不同的传输语义。
    Pull模式不足之处是,如果Kafka没有数据,消费者可能会陷入循环中,一直等待数据到达。为了避免这种情况,可以Pull请求中设置参数,允许Consumer请求在等待数据到达的“长轮询”中进行阻塞(并且可选地等待到给定的字节数,以确保大的传输大小)。

 

五.Kafka消费语意

三种消费语义

at most once
最多一次,消息可能丢失,但是不会重复投递
at least once
至少一次,消息不会丢失,但是可能重复投递
确保消息发送成功之后才进行消费,如果没有发送成功会继续发送,因此会导致重复消费的情况发生;ack=all
exactly once
正好一次,消息不会丢失,也不会重复(这才是我们真正想要的)
 

幂等性保证Exactly once
在kafka 0.11.0.0之前,是无法保证Exactly once的,但从0.11.0.0开始,producer引入了幂等性的概念,保证消息只会被传递一次。

那么kafka是如何实现的呢,用到了Producer ID(即PID)和Sequence Number。

PID:每个新的Producer在初始化的时候会被分配一个唯一的PID,这个PID对用户是不可见的。
Sequence Numbler:对于每个PID,该Producer发送数据的每个[ Topic, Partition ]都对应一个从0开始单调递增的Sequence Number。

Broker端在缓存中保存了Sequence Numbler,对于接收的每条消息,如果其序号比Broker缓存中的序号大于1则接受它,否则将其丢弃,这样就可以防止了消息重复提交。
但是,以上只能保证单个Producer对于同一个[ Topic, Partition ]的Exactly Once语义。不保证同一个Producer一个topic下不同Partition的幂等。

资料来源:https://www.jianshu.com/p/f7725749e90d

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值