Pulsar简介

角色

中间件各角色:

  • Producer:生产者,发布消息至Topic
  • Consumer:消费者,负责从Topic订阅消息
  • Broker:无状态服务层,负责接收传递消息,集群负载均衡等操作
  • Apache BookKeeper:有状态持久层,由一组Bookie节点组成,可以持久化存储消息

计算与存储相隔离的模式,消息发布和订阅相关计算在Broker中,数据存储存储在Bookie节点上

Broker

Broker主要运行两个组件:

  1. 一个HttpServer,暴露REST API给生产者和消费者,用来进行消息的接收和发送,以及Topic查询(在创建消费者、生产者客户端时,将发送http request给任意一个活跃的broker,而broker通过ZooKeeper保存的集群元数据查找哪个broker在负责这个topic,如果一个都没有的话,将创建这个topic,并交给负载最少的broker上。)
  2. 一个TCP服务器,通过自定义的二进制协议进行数据传输

BookKeeper

BookKeeper

Topic与分区

Topic被分为Partitioned Topic和Non-Partitioned Topic,no partitioned topic是分区数为1的topic。

将消息发送至topic的含义为,将消息按照一定的规则发给topic partition

topic partition是逻辑的概念,实际上背后是由Segment组成。且每个Segment的部分都均匀分布存储在BookKeepper中。

一、Pulsar简介 - 图1

消息存储

在Pulsar中,每条消息都有自己的ID,ID由四部分组成ledgerId:entryId:partition-index:batch-index。

partition-index指分区编号,在非分区Topic时指-1

batch-index:在非批量消息时为-1

一个Topic的每个分区会对应一系列的ledger,其中只有一个ledger处于open状态即可写状态,而每个ledger只会存储与之对应的分区下的消息。

Pulsar在存储消息时,会找到当前分区的Ledger,生成当前消息的entry ID,entryID在同一个ledger内是递增的。每个Ledger存在的时间或保存的entry个数超过一定数量后会进行切换。

Ledger是一个数据的逻辑概念,而bookie只会按照entry维度进行写入、查找、获取。

BookKeeper中的数据

  • Journals:存储了BookKeeper的事务日志,在任何对ledger的更新发生前,都会将这个更新的描述信息持久化到这个journal文件中。
  • EntryLogFIle:存储真正数据的文件,来自不同ledger的entry数据会先缓存在内存buffer中,然后批量flush到EntryLogFile中。
    默认情况下,所有Ledger的数据都是先聚合然后顺序写入到同一个EntryLog文件中,避免磁盘随机写
  • Index文件:所有的Ledger的Entry数据都写入相同的 EntryLog文件中,为了加速数据读取,会作LedgerID+entryID到文件的映射,这个映射会缓存至内存中,称为IndexCache。
  • IndexCache容量达到上限时,会被Sync线程flush到磁盘中。

数据写入流程

一、Pulsar简介 - 图2

  1. 数据会同时写入Journal(写入Journal的数据会实时落到磁盘)和Memtable(读写缓存)。在更新到 ledger之前,bookie需要确保描述这个更新的事务被写到持久(非易失)存储上面
  2. 写入Memtable之后,对请求的响应会从缓存中拿数据
  3. Memtable写满之后,会flush到EntryLogger和Index cache,Entry Logger中保存数据,Index Cache中保存数据的索引信息。
  4. 后台线程将同步Entry Logger和Index cache数据到磁盘

数据一致性保证:LastLogMark

  1. 内存中的数据被刷到磁盘中需要一定的时间,如果在这段时间内mq进程崩溃,在重启后则需要根据journal文件来恢复,而LastLogMark就是记录了从什么位置开始恢复。
  2. LastLogMark是不断周期性变化的,当indexCache被刷到磁盘后,LastLogMark也会跟着持久化到磁盘中,用来保证数据恢复时数据的位置。
  3. 如果LastLogMark被持久化到了磁盘,意味着之前的Index和EntryLog也被持久化到了磁盘,那对于Journal来说,在标记位置前的数据都可以清除了。

Pulsar订阅模式

一、Pulsar简介 - 图3

1.独占模式(Exclusive)

是pulsar的默认模式,一个Subscription只能与一个Consumer关联,只有这个Consumer可以接收到Topic的全部消息,如果该Consumer出现了故障就会停止消费。且启动多个消费者将会报错。

2.共享模式(Shared)

消息通过轮询或者自定义的机制分发给不同的消费者,并且每个消息仅会分发给一个消费者。当如果消费者突然下线、断开连接,所有发送给该消费者、且没被确认的消息将被重新安排,分发给其他存活的消费者。

3.灾备模式(Failover)

当存在多个consumer时,会按照字典顺序排序,第一个Consumer将被初始化为接收消息的消费者,当该Consumer下线时,所有未被确认的以及后续进入的消息将会被分发给队列中的下一个Consumer

4.KEY共享模式(Key_Shared)

当存在多个多个Consumer时,将根据消息的Key进行分发,key相同的消息只会被分发到同一个消费者。

一、Pulsar简介 - 图4

定时和延时消息

定时和延时消息的最后效果是一致的,唯一区别的在于:

  1. 定时消息的时间概念为一个时间点
  2. 延时消息的时间概念为一段时间

使用方式都为在生产者处的producer处声明