Skip to content

Add redis cluster adapter for v0.9.1 #195

@RenewedLove

Description

@RenewedLove

Add Redis Cluster Support for v0.9.1
#194

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions