Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Redis cluster support #17982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 32 commits into
base: 5.next
Choose a base branch
from
Open

Redis cluster support #17982

wants to merge 32 commits into from

Conversation

zunnu
Copy link

@zunnu zunnu commented Oct 17, 2024

Support for Redis cluster.

I have included a test file but im not sure how to implement it to the Github actions.
To test this I have used a docker-compose file and I will put it as a comment to this PR.

@zunnu
Copy link
Author

zunnu commented Oct 17, 2024

docker-compose.yml

services:
  php:
    build:
      context: .
      args:
        PHP_MODE: production
    restart: unless-stopped
    volumes:
      - ./:/var/www/html
    depends_on:
      - redis-node-0
      - redis-node-1
      - redis-node-2
      - redis-node-3
      - redis-node-4
      - redis-node-5

  redis-node-0:
    image: bitnami/redis-cluster:latest
    restart: unless-stopped
    environment:
      ALLOW_EMPTY_PASSWORD: yes
      REDIS_CLUSTER_CREATOR: yes
      REDIS_CLUSTER_REPLICAS: 1
      REDIS_NODES: redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5
    depends_on:
      - redis-node-1
      - redis-node-2
      - redis-node-3
      - redis-node-4
      - redis-node-5

  redis-node-1:
    image: bitnami/redis-cluster:latest
    restart: unless-stopped
    environment:
      ALLOW_EMPTY_PASSWORD: yes
      REDIS_NODES: redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5

  redis-node-2:
    image: bitnami/redis-cluster:latest
    restart: unless-stopped
    environment:
      ALLOW_EMPTY_PASSWORD: yes
      REDIS_NODES: redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5

  redis-node-3:
    image: bitnami/redis-cluster:latest
    restart: unless-stopped
    environment:
      ALLOW_EMPTY_PASSWORD: yes
      REDIS_NODES: redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5

  redis-node-4:
    image: bitnami/redis-cluster:latest
    restart: unless-stopped
    environment:
      ALLOW_EMPTY_PASSWORD: yes
      REDIS_NODES: redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5

  redis-node-5:
    image: bitnami/redis-cluster:latest
    restart: unless-stopped
    environment:
      ALLOW_EMPTY_PASSWORD: yes
      REDIS_NODES: redis-node-0 redis-node-1 redis-node-2 redis-node-3 redis-node-4 redis-node-5

Edit:
The tests are locked to use specific ip's so the yml maybe should have ip's defined like this.

    networks:
      redis-cluster-net:
        ipv4_address: 172.18.0.7

@dereuromark dereuromark added this to the 5.2.0 milestone Oct 17, 2024
@LordSimal
Copy link
Contributor

LordSimal commented Oct 17, 2024

You can run composer cs-fix to automatically fix the codestyle errors which are present.
To check if codestyle is green, you can do composer cs-check

For stan you need to do a composer stan-setup (you need to have phive installed) and then a composer stan to locally debug and fix the PHPStan/Psalm issues.

Certain stan issues can't be fixed easily, so it may be, that you need to regenerate the baselines for phpstan and psalm composer phpstan-baseline and psalm-baseline

zunnu and others added 2 commits October 17, 2024 17:53
@ADmad
Copy link
Member

ADmad commented Oct 24, 2024

I think the changes to RedisEngine seem good, need to add/update the tests now.

@zunnu
Copy link
Author

zunnu commented Oct 24, 2024

Tests have been updated. There is a separated test for RedisCluster. The main problem with the current version of that test is that it uses static ips. Im not sure how to implement RedisCluster testing to Github actions

Copy link
Member

@markstory markstory left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good. I left a few comments on test coverage.

}

if ($this->_Redis instanceof RedisCluster) {
foreach ($this->_Redis->_masters() as $masterNode) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have tests for clear + RedisCluster.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, I wonder why codecov had those lines flagged as uncovered.

$this->_Redis->setOption(Redis::OPT_SCAN, (string)Redis::SCAN_RETRY);
}

if ($this->_Redis instanceof RedisCluster) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another place where we should have some test coverage.

Comment on lines 30 to 35
['host' => '172.18.0.7', 'port' => 6379],
['host' => '172.18.0.2', 'port' => 6379],
['host' => '172.18.0.3', 'port' => 6379],
['host' => '172.18.0.5', 'port' => 6379],
['host' => '172.18.0.4', 'port' => 6379],
['host' => '172.18.0.6', 'port' => 6379],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a 6 node cluster? Couldn't we make due with a 3 node cluster? No need to waste additional resources.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need 6 nodes 3 is fine this was what I used for testing

@markstory markstory modified the milestones: 5.2.0, 5.3.0 Mar 29, 2025
@dereuromark
Copy link
Member

ping @zunnu Anything left to be done? There seems to be a few conflicts.

@ADmad ADmad added the needs squashing The pull request should be squashed before merging label Jun 5, 2025
@zunnu
Copy link
Author

zunnu commented Jun 5, 2025

@ADmad Is there something to be done here or can this be merged?

@ADmad ADmad requested a review from markstory June 5, 2025 07:52
@ADmad ADmad requested a review from Copilot June 5, 2025 11:59
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds Redis Cluster support to the existing RedisEngine by introducing new configuration keys, branching connection logic, and cluster-aware key-scanning in clear operations.

  • Extend RedisEngine to detect and connect to a Redis Cluster via connectRedisCluster()
  • Introduce new config options: clusterName, nodes, and readTimeout
  • Update clear() and clearBlocking() to scan and delete keys across cluster masters
  • Add CI service for Redis Cluster and update tests for default config values

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

File Description
tests/TestCase/Cache/Engine/RedisEngineTest.php Added 'readTimeout', 'clusterName', and 'nodes' to expected configs
src/Cache/Engine/RedisEngine.php Imported RedisCluster, updated default config, added cluster connect and scan/delete logic
phpstan-baseline.neon Suppressed RedisCluster-related type errors in baseline
.github/workflows/ci.yml Added redis-cluster service and REDIS_CLUSTER_NODES environment variable
Comments suppressed due to low confidence (4)

src/Cache/Engine/RedisEngine.php:409

  • Calling the internal _masters() method on RedisCluster relies on a non-public API. Use the officially documented method for retrieving cluster nodes to avoid future compatibility issues.
foreach ($this->_Redis->_masters() as $masterNode) {

tests/TestCase/Cache/Engine/RedisEngineTest.php:106

  • [nitpick] There are no tests covering the new cluster connection or cluster-specific clear behavior. Add tests to validate connectRedisCluster() and ensure key deletion works across all masters.
'readTimeout' => 0,

src/Cache/Engine/RedisEngine.php:156

  • The log message references RedisClusterEngine but the class is named RedisEngine. Update the message for consistency.
Log::error('RedisClusterEngine could not connect. Got error: ' . $e->getMessage());

src/Cache/Engine/RedisEngine.php:146

  • The 'persistent' key is not defined in the default config, leading to an undefined index when constructing RedisCluster. Add a default 'persistent' entry or guard against missing values.
$this->_config['persistent'],

@dereuromark
Copy link
Member

I merged #18721 changes into 5.next
So if you rebase should be on latest changes then.

@zunnu
Copy link
Author

zunnu commented Jun 5, 2025

I merged #18721 changes into 5.next So if you rebase should be on latest changes then.

Should be good now.

@dereuromark
Copy link
Member

Error: Ignored error pattern #^Comparison operation ">" between (int<0, max>|Redis|false) and 0 results in an error.$# in path /home/runner/work/cakephp/cakephp/src/Cache/Engine/RedisEngine.php was not matched in reported errors.
Error: Ignored error pattern #^Comparison operation ">" between (int|Redis|false) and 0 results in an error.$# in path /home/runner/work/cakephp/cakephp/src/Cache/Engine/RedisEngine.php was not matched in reported errors.
Error: Process completed with exit code 1.

@zunnu
Copy link
Author

zunnu commented Jun 6, 2025

Error: Ignored error pattern #^Comparison operation ">" between (int<0, max>|Redis|false) and 0 results in an error.$# in path /home/runner/work/cakephp/cakephp/src/Cache/Engine/RedisEngine.php was not matched in reported errors. Error: Ignored error pattern #^Comparison operation ">" between (int|Redis|false) and 0 results in an error.$# in path /home/runner/work/cakephp/cakephp/src/Cache/Engine/RedisEngine.php was not matched in reported errors. Error: Process completed with exit code 1.

@dereuromark Done

@zunnu
Copy link
Author

zunnu commented Jun 17, 2025

@dereuromark Anything else to be done or can this be merged?

@dereuromark
Copy link
Member

I wonder what those test fails are

@markstory can maybe sign off.

@LordSimal
Copy link
Contributor

LordSimal commented Jun 17, 2025

@dereuromark seems its related to a PHPUnit change since the 2 collection objects are not "equal" anymore.
I'll get that fixed in a separate PR.

The split package stan issues can be ignored.

path: src/Cache/Engine/RedisEngine.php

-
message: "#^Parameter \\#3 \\$pattern of method RedisCluster\\:\\:scan\\(\\) expects int, string given\\.$#"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this should be a cast instead.

}

foreach ($keys as $key) {
$isDeleted = ($this->_Redis->del($key) > 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also use unlink. I think that scan should be moved to a dedicated method to avoid code duplication.

I have an implementation with yield in my branch you can borrow.

See:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement needs squashing The pull request should be squashed before merging
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants