pulsar底层原理浅析-新一代消息队列

pulsar原理浅析

[TOC]

前言

随着时代发展,技术更迭,不断有新的消息中间件出现并使用,本文就pulsar特性进行探讨和分析,阅读本文前,建议对业界通用消息队列有一定的学习和使用 (文中内容引用了部分互联网文档)

背景

  • pulasr是什么:一个Pub/Sub模型的消息中间件

image.png

2021年pulsar在Yahoo内部开发

2016年开源并捐献给Apache

2018年成为Apache顶级项目

image.png

特点

  • Pulsar的单个实例原生支持多个集群,可跨机房在集群间无缝的完成消息复制
  • 极低的发布延迟和端到端延迟
  • 可无缝扩展到超过一百万个Topic
  • 简单的客户端API、支持Java、Go、Python和C++
  • Topic支持多种订阅模式(独占订阅、共享订阅、故障转移订阅)
  • 通过Apache BookKeeper 提供的持久化消息存储机制保证消息传递

...

基础概念

pulsar的结构,由几个核心内容所组成

image.png

我们以上文结构进行分析

  • Producer : 消息的生产者,负责发布消息到Topic
  • Consumer : 消息的消费者,负责从Topic订阅消息
  • Broker : 无状态服务层,负责接收和传递消息,集群负载均衡等工作,Broker 不会持久化保存元数据,因此可以快速的上、下线
  • Apache BookKeeper : 有状态持久层,由一组 Bookie 存储节点组成,可以持久化地存储消息

Topic(主题)是某一种分类的名字,消息在 Topic 中可以被存储和发布。生产者往 Topic 中写消息,消费者从 Topic 中读消息

实现原理

image.png

  • 通过上面的介绍,我们对pulasr有了一个整体的认识,但是消息是如何生产的?又是如何存储的?下游又是如何消费的呢?

broker和bookie

这里就不得聊一聊pulsar中比较有意思的broker和bookie了,我们在使用kafka的时候,也经常会提到broker的概念,在kafka中broker扮演的角色作用主要是集群中的一个实例节点,但在pulsar中大不相同

broker是一个无状态组件,负责处理和负载均衡 producer 发出的消息,并将这些消息分派给 consumer

可以看到broker只是一个组件,并不负责存储消息,且是无状态的,便于快速上下线,更适合于云原生场景

bookie是BookKeeper集群中的存储节点,负责存储消息和游标

这里的设计,将 Broker 和 bookie 相互独立,方便实现独立的扩展以及独立的容错性 对于broker,在高负载场景下可以更方便的添加新节点 对于bookie,在存储不足时可以快速新增节点来平摊存储负载 在这种结构下消息存储分布均匀,单个分区数据量突出不会使整个集群出现木桶效应

生产到消费

有了以上的理解,消息的生产链路我们大概也能描绘出来

  1. Producer 生产消息
  2. 消息发送指定Topic
  3. 根据策略选择对应broker节点和Partition
  4. broker接收消息后,追加写入bookie分区下的segment分片
  5. 下游消费者拉取消息,按照指定模式消费

其中,生产模式分为 同步异步

消费模式分为

  • 独占(Exclusive) : 只能有一个消费者
  • 灾备(Failover) : 支持多个消费者但同时只能一个消费,当上一消费者异常后按顺序依次执行消费
  • 共享(Shared) : 多消费者共享消费,同一消息只会被一个消费者唯一消费
  • KEY 共享模式(Key_Shared) : 消息根据key进行分发,同一key保证由同一消费者消费(这样保证了同一KEY下的有序性

延时队列

pulsar的延时队列,是另一个非常重要的特性

延时队列 : 生产消息时指定时间,消息在等待特定时间后再被消费,pulsar支持秒级延迟消息投递

这个特性比较有意思,利用这个功能我们可以做一些额外的事,或者取代原先的定时任务 比如错误重试,订单取消,相较于定时任务,使用延时队列

  • 更快
  • 更稳定
  • 效率更高

实现

那,延时队列是如何实现的?

image.png

结合上图可以简单看一下,pulsar与内存之中维护了一个delayed message tracker,它的作用即是存储所有的延时消息,底层存储结构为小顶堆,当然,其中的index指向了具体的消息内容,包括Timestamp、LedgerID、EntryID等

每次消费者拉取数据时,都会优先检查延时队列中的内容,如果发现堆顶的消息已经达到过期时间,那么即可消费该消息

挑战

那么,通过对延时队列的了解,可能会遇到什么问题呢?

  • delayed index 队列受内存限制 : 显然,你不能不限时间、不限数量的存储所有的延时消息
  • delayed index 队列重建时间开销 : 假如pulsar服务发生了重启或其他异常情况,必然要面临延时队列重建的问题

还会不会有其他问题呢?问题又是否可以优化?等待思考

业界组件对比与应用前景

说了那么多,我到底要不要用pulsar?在什么情况下应该用它?

对比

我们先来看看业界通用组件的对比

分类 功能 Kafka Pulsar RocketMQ RabbitMQ
功能 消费推拉模式 pull pull+push pull push
延迟队列 不支持 支持 支持 支持
死信队列 不支持 支持 支持 支持
消息回溯 支持 支持 支持 不支持
消息持久化 支持 支持 支持 支持
消息确认机制 Offset Offset+单条 Offset 单条
消费模式 流模式 流模式+队列模式 广播模式+集群模式 队列模式
性能 单机吞吐量 605MB/s 605MB/s 605MB/s 38MB/s
消息延迟 5ms 5ms ms级 微秒级
运维 高可用 分布式架构 分布式架构 主从架构 主从架构

应用

  • 常规消息中间件使用场景
  • 服务请求异常,需要将异常请求放到单独的队列,隔 5 分钟后进行重试;
  • 用户购买商品,但一直处于未支付状态,需要定期提醒用户支付,超时则关闭订单;
  • 面试或者会议预约,在面试或者会议开始前半小时,发送通知再次提醒;

总结

pulsar作为新一代消息队列,有许多新生功能,可以用于解决特定场景下的业务痛点, 目前我们团队主要使用的消息中间件仍是kafka,但同时使用pulsar可以用于失败重试、定时取消等场景

相较于kafka,目前pulsar社区经验还没有那么丰富,虽然带来了新功能但同时也存在潜在的隐患和不稳定性,如果不需要使用到新特性的话,选择kafka或许是个更好的选择



相关文档资料:

github地址 : github.com/apache/puls…

pulsar官网 : pulsar.apache.org/

腾讯云文档: cloud.tencent.com/document/pr…

猜你喜欢

转载自juejin.im/post/7086741087800754189