具象化模型

下图以订单、运输、通知等信息,描述与kafka交互的过程,业务中的事件(如下单,支付,配送,评价,售后)会产生各类信息,最终以topic归类汇集到kafka中

分区

同一类的消息都会汇集到一个Topic中,一个Topic可以分为多个Partition,Partition是最小的储存单元,每一个Partition储存着一部分的消息,每个Partition都是一个单独的log文件,每条记录都以追加的形式写入

偏移量 & 消息顺序

Partition中每条记录都会被分配唯一的序号,称为Offset,即偏移量
Offset是一个递增的,不可变的数字,由kafka自动维护
当一条记录写入Partition的时候,它就被追加到log文件的末尾,并被分配一个序号,作为 Offset

  • 所以从Partition来看,单个Partition内部是有序的,但从Topic来看,消息在Partition之间是无序的;如果希望消息保证完全的顺序,就只能存在一个Partition,又或者发送端指定发送到某个Partition,消费端指定从某个Partition消费

Partition 扩展 & 冗余

kafka集群由多个Broker构成,每个Broker中含有集群的部分数据,同一个Topic的多个 Partition将分布在多个Broker中;Partition会生成多个副本,它们会分散在不同的Broker中,
如果某个Broker故障了,Consumer可以在其他Broker上找到Partition的副本,继续获取消息

Message 写入

  • 指定Partition

      Producer发送消息时,可指定一个Partition Key
      这样就可以写入特定的Partition
      Partition Key会根据一个Hash函数计算出写入哪个Partition
      Partition Key相同的消息,会被放到相同的Partition
      这种方式需要注意数据倾斜问题

  • 随机Partition

      如果没有使用Partition Key,kafka则会使用轮询的方式来决定写入哪个Partition
      消息会均衡的写入各个Partition,这样无法确保消息的有序性
    
  • 自定义规则

      kafka支持自定义规则,一个Producer可以使用自己的分区指定规则。
    

Message 读取

kafka的消息读取采用的是pull方式,Consumer需要主动从Topic的Partition拉取消息,Pull模式下,Consumer就可以根据自己的消费能力去决定消费策略
但Pull有个缺点是,如果broker没有可供消费的消息,将导致consumer不断在循环中轮询,直到新消息到达
为了避免这点,kafka有个参数可以让Consumer阻塞直到新消息到达,也可以阻塞直到消息的数量累积到某个特定的值再读取

消息的Offset就是Consumer的游标,根据Offset来记录消息的消费情况
读完一条消息之后,Consumer会推进到Partition中的下一个Offset继续读取消息
Offset由Consumer负责维护

消费组

Consumer Group下有一个或多个Consumer,这些Consumer有相同的groupId,groupId是一个字符串,消费组的唯一标识
Topic中的每个分区只能分配给某个Consumer Group的一个Consumer消费(该分区还可以被分配给其他消费组)

参考资料:
https://medium.com/event-driv...
本文中大部分的图来自上述博客,应该是一位印度工程师所写,原文为英文且查看需要翻墙
https://www.bilibili.com/read...


老污的猫
30 声望5 粉丝

« 上一篇
Java 反射
下一篇 »
线程池的状态