[13.x] Add cluster_aware Redis mode for managed single-endpoint providers#59797
Closed
timmylindh wants to merge 0 commit into
Closed
[13.x] Add cluster_aware Redis mode for managed single-endpoint providers#59797timmylindh wants to merge 0 commit into
timmylindh wants to merge 0 commit into
Conversation
|
Thanks for submitting a PR! Note that draft PRs are not reviewed. If you would like a review, please mark your pull request as ready for review in the GitHub user interface. Pull requests that are abandoned in draft may be closed due to inactivity. |
bd01dca to
79d24c8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Several managed Redis providers - AWS ElastiCache Serverless (Valkey), Upstash Redis, Redis Cloud with the DMC proxy - present a Redis Cluster behind a single endpoint while blocking the
CLUSTERtopology commands, so the client can't configure itself as a real cluster client. The endpoint still enforces slot semantics: multi-key commands returnCROSSSLOTunless every key hashes to the same slot.Laravel breaks out of the box on these providers.
Cache::many(),Cache::putMany(), tagged cacheflush(), and every queuepush/pop/later/migratescript issue multi-key commands with no slot guarantee.The existing hash-tag handling from #59533 only fires for real cluster clients - but here the client is standalone and only the server is clustered. There's no runtime signal to detect this, so the signal has to come from config.
This PR introduces a
cluster_awareflag, opt-in per connection:When set, queue and limiter keys get hash-tagged, and multi-key cache operations fall back to per-key paths.
Changes
Connection infrastructure
isClusterAware()- true for real cluster clients or standalone connections withcluster_aware: true.supportsMultiSlotMultiKeyCommands()- false when the client can't route a multi-key command across slots. Overridden to true onPhpRedisClusterConnection, which routesMGET/DEL/etc. per slot natively.$configmoved to the baseConnectionsoPredisConnectioncan read it; Predis constructor and connector updated accordingly (BC-safe default).RedisQueue & ConcurrencyLimiter
isClusterAware()is true, not just for real cluster clients.RedisStore
many()falls back to per-keygetwhen! supportsMultiSlotMultiKeyCommands(); phpredis cluster keeps the nativeMGETpath.putMany()falls back to per-keysetexwhenisClusterAware()-MULTI/EXECcan't span slots on any cluster-like endpoint.RedisTaggedCache
flush()uses the per-slot fallback whenisClusterAware().flushValues()uses pipelined per-keyDELwhen! supportsMultiSlotMultiKeyCommands(); phpredis cluster keeps the variadicDELfast path.Backward Compatibility
cluster_awaredefaults tofalse. Zero behaviour change for any existing config.isCluster()semantics are unchanged - still true only for real cluster clients.isClusterAware()via theisCluster()branch, so every rewired call site takes the same path it did before for them.PredisConnection::__construct($client)still works; the new$configparameter is optional.