apache / apache/pulsar

[Enhancement] Support negative acknowledgement (nack) with Key_Shared subscriptions while preserving ordering

Open
#23,480 1 comment 3 reactions 1 assignee Claimed by @lhotari View on GitHub
type/enhancement
Dominant language
Java
Stars
15.3k
Forks
3.8k
Avg merge
1d 14h
Merged PRs (30d)
160

Description

### Search before asking

- [X] I searched in the [issues](https://github.com/apache/pulsar/issues) and found nothing similar.

### Motivation

Key_Shared subscriptions don't currently support negative acknowledgements (nack).
Consumers can get stuck with Key_Shared subscriptions in all previous versions of Pulsar before 4.0.0.
With Pulsar 4.0.0, the consumers will no longer get stuck due to using nacks. This has been addressed with [PIP-379: Key_Shared Draining Hashes for Improved Message Ordering](https://github.com/apache/pulsar/blob/master/pip/pip-379.md) improvements. However, in Pulsar 4.0.0, the nacked messages will get relivered after a delay without considering the ordering.
There's a need to also preserve ordering when using nacks in Key_Shared subscriptions.

### Solution

A complete solution would require changes to the Pulsar binary protocol in addition to changes in both the broker and the client, since both sides would need to cooperate to hold back messages for a key. This increases the implementation and rollout effort considerably, as protocol changes also raise compatibility concerns across broker and client versions.

Alternatively, a purely client-side implementation is possible. The high-level idea:

1. When a message is nacked, the client retains the nacked message and buffers any subsequently received messages with the same key.
2. Delivery of buffered messages for that key is paused until the nacked message has been redelivered (handled entirely on the client side) and successfully acknowledged.
3. Once the nacked message is acknowledged, the buffered messages for the key are delivered in order.

The main limitation of a client-side-only approach is flow control: since the broker isn't aware of the nack semantics, it keeps dispatching messages for the affected key, and the consumer could eventually run out of permits if there's a large volume of messages for that key. In that sense, the primary benefit of adding broker-side (and protocol-level) support would be avoiding permit exhaustion, since the broker could hold back messages for the key instead of pushing them to the client.

Until this feature is implemented, applications can achieve similar behavior themselves: retry the failed message in application code and defer processing of any further messages for the same key until the original message has been processed successfully. This has the same drawback as the client-side approach — messages for the key aren't held back on the broker side, so a consumer's permits could still run out.

### Alternatives

_No response_

### Anything else?

_No response_

### Are you willing to submit a PR?

- [ ] I'm willing to submit a PR!

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.