本文为原创文章,转载请注明出处
关注 pulsar 项目将近10天左右了,在此前,我和所有刚接触 pulsar 项目的人都有一个共同的疑惑,目前社区内已经有activeMQ、kafka、RocktMQ等优秀的消息队列,而且也经历过社区长时间的洗礼,我们为什么还需要 pulsar 这个MQ?带着这样的疑问,我们开始阅读这篇文章。
记得在之前项目中遇到几个kafka的痛点问题,第一:在数据迁移过程中,我们需要从上游到下游的数据必须是有序的,简单点说就是,我们期望DDL跑到DML的前面,不然当我们DML语句到达之后,我们都不知道数据应该写入到哪个DB(因为此时压根还没有db和table)。熟悉kafka的人都知道,kafka的partition内是有序的状态,但多个partition之间是无序的,最简单的逻辑,我们将所有的数据全部写入一个partition中,让consumer订阅这个partition,但是这其中存在一个较大的问题,kafka这种基于partition的MQ,本身就是通过partition来提高吞吐量,我们的业务是在迁移数据,全量迁移时,瞬时数据会很大,同时塞到一个partition中,势必会使这个partition成为整个系统的热点问题。第二:当时候,我们内部压测过kafka,印象中,当时候的压测是分为8、32、64topic,当时候我们发现,当topic超过64时,kafka的吞吐出现明显的抖动,也就是kafka并不能够单纯的通过增加topic的数量来提升吞吐量。这个64topic性能抖动问题,与RocketMQ和kafka对比压测的现象基本一致。
我们前面也提到过,kafka和rocketMQ这种MQ是基于partition的存储模型。也就是说,他们的存储和partition是绑定的,一个partition只能由一个consumer来订阅消费,这就存在一个问题,partition和consumer究竟怎么设置,原则上,我们需要始终保持这两者是对等的关系,如果partition过多,就可能存在一个consumer订阅多个partition的问题,反过来,如果consumer过多,就会出现consumer空闲的问题。那么合理的分配策略只有是 partition 个数与 consumer 个数成倍数关系。
在kafka中最小的单位是segment,一个segment分为两个文件,一个.index文件用来存储元数据信息,一个.log文件用来存储数据信息,也就意味着一个partition至少需要两个fd,kafka还需要将这些元数据信息注册到zk中,方便整个kafka集群的监控调度。所以在kafka中,partition是一个相对比较重的资源,我们当时候的压测,1000左右的partition 会给kafka系统带来将近40-60ms左右的延迟(大致值)。kafka consumer静态绑定的这种架构设计导致了其扩容缩容也是一个问题。当系统遇到处理能力不足时,单纯的增加consumer并不能解决问题,我们还需要增加其对应的partition 的数量。但是,比较蛋疼的另一个问题是,partition是单向扩容的,意思是我们一旦增加上去partition的数量,我们是不能对其减少的。
这里再回答当时候我们遇到的上述提到的第一个痛点问题,如果我们只用一个partition来保证全局的顺序问题,当数据量较大的时候,这个partition会迅速增长,这个时候,即使你再想通过扩充partition的数量来提升系统的吞吐,也不是很现实来,这种强负载在kafka中简直是一个灾难。我们假设我们增加进来两个partition,但是我之前的partition已经被其中一个consumer订阅,所以那些堆积的消息只能由这个consumer来消费,这种不支持横向扩展的设计一旦遇到真的瓶颈真的有点难受,或者你就选择强制负载均衡。
针对上述的一些问题 ,pulsar是如何解决的呢?
- 对于kafka负载的问题,我们来看一张图:
通过上图,我们可以分析到,kafka等基于partition存储的mq存储起来是"一条一条"的,pulsar会均匀摊开。这点得意于pulsar将存储与计算分离的架构设计,我们可以方便的在存储层和计算层进行扩容。具体参考:Pulsar VS. Kafka(2): 以Segment为中心的架构
- pulsar从设计之初,从写第一行代码开始就考虑到多租户的场景,pulsar自打诞生那天起,就为云这件事情做好了准备。
上图表述了pulsar在多租户场景下的组成架构。
- 租户name:property-1, property-2, property-3
- 业务线:nameSpace-1, nameSpace-2
到了具体的业务线之后,我们就可以和正常使用mq一样对其执行相应的操作。
- pulsar 给consumner提供了不同的订阅形式:
- exclusive: 这种订阅方式可以保证顺序,可以看作是failover的一个子集。
- shared: 共享。这种模式允许每个topic有多个消费者来订阅,大家一人消费点数据,分工合作,可以根据数据的多少任意扩展consumer的多少。
- failover: 灾备模式,这种订阅也可以保证顺序。
exclusive 和 failover 适合对顺序有要求的业务场景,一般我们称作Stream(流)
shared 适合对消息顺序没什么要求的业务场景,一般我们称作Queue(队列)
本文只是针对自己之前在业务中使用kafka的一些问题以及在pulsar中,我们如何规避这些问题,并没有对pulsar的全部特性做详细的介绍,想进一步了解的,请移步下面的文章
下面是搜集的一些优秀的关于pulsar相关的技术文章:
- 深入理解Pulsar工作原理
- Pulsar笔记
- Pulsar vs Kafka 统一消费模型
- Pulsar vs Kafka 分层分片架构
- Apache Pulsar介绍
- Apache Pulsar在智联招聘的实践
如果对Pulsar感兴趣,可通过下列方式参与Pulsar社区:
- Pulsar Slack频道:
https://apache-pulsar.slack.com/
可自行在这里注册:
https://apache-pulsar.herokuapp.com/
- Pulsar邮件列表: http://pulsar.incubator.apache.org/contact
有关Apache Pulsar项目的更多信息,请访问官网:
http://pulsar.incubator.apache.org/
此外也可关注Twitter帐号@apache_pulsar。