Skip to content

Conversation

@RenewedLove
Copy link

Add Redis Cluster Support for v0.9.1

This PR adds Redis Cluster support to the legacy v0.9.1 version.
While integrating this library into an older PHP project, I discovered that the original Redis adapter does not work correctly in cluster mode. After analyzing the source code, I identified three key issues and implemented a backward-compatible solution.

🐞 Problem Analysis & Solutions

  1. CROSSSLOT Key Distribution Issue

Problem:
When multiple keys fall into different hash slots, Redis Cluster returns:

CROSSSLOT Keys in request don't hash to the same slot

Solution:
Introduce a setHashTag method to ensure all related keys are placed under the same hash slot:

RedisCluster::setHashTag('TEST_PROMETHEUS');

  1. Multi-Instance Write Contention

Problem:
The original adapter relies on EVAL to guarantee atomicity.
However, Redis Cluster does not support cross-slot Lua scripts, resulting in potential write conflicts between multiple application instances.

Solution:
Following Prometheus best practices, assign a unique prefix for each instance to isolate keys:

$instanceID = !empty($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '127.0.0.1';
RedisCluster::setPrefix('TEST_PROMETHEUS:' . $instanceID);

This ensures each instance only writes to its own metrics keys.

  1. Multi-Process Atomicity Issue

Problem:
Atomic operations can no longer rely on EVAL since Lua scripts may not run on the same node in cluster mode.

Solution:
Use idempotent Redis operations to simulate atomic behavior and reduce inconsistency risks:

// Idempotent operations replacing the original Lua script logic
$pipe->hsetnx($metricKey, '__meta', json_encode($metaData)); // Set only if missing
$pipe->sadd($metricKeysKey, $metricKey); // Idempotent insert

⚖️ Trade-offs

If a Redis connection drops during pipeline execution, some operations may succeed while others fail — strict atomicity cannot be guaranteed.

However, this trade-off is acceptable for Prometheus metric data, where a small amount of inconsistency is tolerable.

💡 Contribution Suggestions

If the maintainers find this approach valuable, I am happy to continue contributing with:

Full Redis Cluster support for the latest version, or

Keeping this PR as a backward-compatible solution, where users only need to copy:

src/Prometheus/Storage/RedisCluster.php

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant