Apache Pulsar 设计用于大规模实时数据处理,支持多种消息传递模型(发布/订阅、队列等),并提供了强大的功能来确保消息的可靠性和性能。
优势
1. 强大的消息模型
发布/订阅 (Pub/Sub): 支持多个消费者同时从同一个主题接收消息,适合实时数据分析和通知系统。
独占订阅 (Exclusive Subscription): 确保只有一个消费者能够消费某个分区的消息,从而保证消息的严格顺序。
共享订阅 (Shared Subscription): 多个消费者可以负载均衡地消费消息,提高吞吐量。
故障域感知路由: 根据地理位置和网络拓扑优化消息路由,确保高效的数据传输。
2. 持久化与存储
持久化消息: 所有消息都被持久化到磁盘,确保消息不会丢失。
分层存储: 使用分层存储策略,结合内存和磁盘存储,提高读写效率。
自动清理: 定期清理过期或不再需要的消息,节省存储空间。
3. 事务支持
事务消息: 支持事务性的消息发送和确认机制,确保数据一致性。
两阶段提交: 实现ACID特性,保证消息的一致性和可靠性。
4. 死信队列
死信队列 (Dead Letter Queue, DLQ): 对于无法成功处理的消息,将其放入死信队列以便后续排查和处理。
重试机制: 在消息处理失败时,进行一定次数的重试(默认最多3次),如果仍然失败,则将消息放入死信队列。
应用场景
用户发起一笔交易请求,系统需要将该请求发送到交易处理系统,并确保请求按顺序被处理。而使用Pulsar的独占订阅模式确保交易请求按顺序被单一消费者处理,避免乱序导致的账务错误。
启动Pulsar:
bin/pulsar standalone
代码实操
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Apache Pulsar Client -->
<dependency>
<groupId>org.apache.pulsar</groupId>
<artifactId>pulsar-client</artifactId>
<version>2.10.1</version>
</dependency>
<!-- Lombok for cleaner Java code -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- JUnit for testing -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
配置文件
在application.properties
文件中配置Pulsar的相关属性:
# Pulsar broker URL
pulsar.service.url=pulsar://localhost:6650
# Topic name
pulsar.topic.name=finance-transaction-topic
# Dead letter topic name
pulsar.dead-letter.topic.name=dead-letter-topic
# Max redelivery count before sending to dead letter queue
pulsar.max.redeliver.count=3
服务类
创建一个服务类来处理生产和消费消息,包括事务消息和死信队列的处理逻辑。
import lombok.extern.slf4j.Slf4j;
import org.apache.pulsar.client.api.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.CompletableFuture;
@Service
@Slf4j
public class FinanceTransactionService {
@Value("${pulsar.service.url}")
private String serviceUrl;
@Value("${pulsar.topic.name}")
private String topicName;
@Value("${pulsar.dead-letter.topic.name}")
private String deadLetterTopicName;
@Value("${pulsar.max.redeliver.count}")
private int maxRedeliverCount;
&