2

Does Magento Enterprise have any means of using read replicas when using Redis as a back-end cache? If not, any tips on how this could be added?

Magento uses Credis_Client by Colin Mollenhour, who also offers a Client_Cluster class: https://github.com/colinmollenhour/credis/tree/74b2b703da5c58dc07fb97e8954bc63280b469bf However, I don't see this included in Magento by default.

1

I think there is no configuration in Magento needed as the replication is set up on (redis) application level.

From what I've seen in the documentation here, it's enough to set this up in the redis configruation.

2
  • 1
    I am using ElastiCache with read replication setup, and even though Magento is pointing at the replication group's endpoint, Magento only ever reads from the primary (aka "master") node. I want to set it up to read from multiple nodes, and write to one. – Tyler V. Jun 17 '16 at 23:28
  • I see. Hope to find someone experienced with that to answer here. – Anna Völkl Jun 18 '16 at 8:06
1

This is the solution that I eventually came up with.

1) I updated /lib/Credis/Client.php and added /lib/Credis/Cluster.php using the latest versions from Colin Mollenhour.

2) I replaced the single Redis cluster connection line in /lib/Cm/Cache/Backend/Redis.php with a Cluster connection.

Original:

$this->_redis = new Credis_Client($options['server'], $options['port'], $timeout, $persistent);

New:

$cluster = false;
if (class_exists('Credis_Cluster') && array_key_exists('cluster', $options) && !empty($options['cluster'])) {
    $clusterNodes = array();

    if (array_key_exists('master', $options['cluster']) && !empty($options['cluster']['master'])) {
        foreach ($options['cluster']['master'] as $masterNode) {
            if (empty($masterNode['server']) || empty($masterNode['port'])) {
                continue;
            }

            $clusterNodes[] = array(
                'host'       => $masterNode['server'],
                'port'       => $masterNode['port'],
                'alias'      => 'master',
                'master'     => true,
                'write_only' => true,
                'timeout'    => $timeout,
                'persistent' => $persistent,
                'db'         => (int)$options['database'],
                'password'   => $options['password'],
            );
            break; // limit to 1
        }
    }

    if (!empty($clusterNodes) && array_key_exists('slave', $options['cluster']) && !empty($options['cluster']['slave'])) {
        foreach ($options['cluster']['slave'] as $slaveNodes) {
            if (empty($masterNode['server']) || empty($masterNode['port'])) {
                continue;
            }

            $clusterNodes[] = array(
                'host'       => $slaveNodes['server'],
                'port'       => $slaveNodes['port'],
                'alias'      => 'slave' . count($clusterNodes),
                'timeout'    => $timeout,
                'persistent' => $persistent,
                'db'         => (int)$options['database'],
                'password'   => $options['password'],
            );
        }
    }

    if (!empty($clusterNodes)) {
        $cluster = true;
        $this->_redis = new Credis_Cluster($clusterNodes);
    }
}

if (!$cluster || !$this->_redis) {
    $this->_redis = new Credis_Client($options['server'], $options['port'], $timeout, $persistent);
}

3) I updated /app/etc/local.xml to include a new <cluster> tag inside <global><cache><backend_options> and <global><full_page_cache><backend_options> like the following:

<cluster>
    <master>
        <node-001>
            <server>elasticache-replicationgroup-endpoint-here</server>
            <port>6379</port>
        </node-001>
    </master>
    <slave>
        <node-001>
            <server>elasticache-cluster-001-endpoint-here</server>
            <port>6379</port>
        </node-001>
        <node-002>
            <server>elasticache-cluster-002-endpoint-here</server>
            <port>6379</port>
        </node-002>
    </slave>
</cluster>

4) To test, I temporarily modified the connect() method in /lib/Credis/Client.php to add the following right before the return statement:

Mage::log('Connected to '.$this->getHost(), null, 'redis.log', true);

With these changes, I can see that the ElastiCache Replication Group endpoint is being connected to for writes, and the other ElastiCache Cluster endpoints are being connected to at random for reads. This has introduced true read replica support to Redis in Magento, and has significantly improved performance and stability during high load.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.