Redis (Object cache)

Redis is a high-performance in-memory object store, well-suited for application level caching.

See the Redis documentation for more information.

Platform.sh supports two different Redis configurations:

  • Persistent: useful for key-value application data
  • Ephemeral: in-memory only, useful for application caching

Otherwise, they’re identical.

Use a framework 

If you use one of the following frameworks, follow its guide:

For more implementation ideas, consult a template.

Supported versions 

Grid Dedicated Gen 3 Dedicated Gen 2
  • 7.0
  • 6.2
  • 7.0
  • 6.2
  • 7.0
  • 6.2

The following versions aren’t available in the EU-1 and US-1 regions:

  • 7.0

  • 6.2

Consider region migration if your project is in those regions.

Deprecated versions 

The following versions are deprecated. They’re available, but they aren’t receiving security updates from upstream and aren’t guaranteed to work. They’ll be removed at some point in the future, so you should migrate to one of the supported versions.

Grid Dedicated Gen 3 Dedicated Gen 2
  • 6.0
  • 5.0
  • 4.0
  • 3.2
  • 3.0
  • 2.8
  • 6.0
  • 5.0
  • 4.0
  • 3.2
  • 3.0
  • 2.8
  • 6.0
  • 5.0
  • 3.2

Service types 

There are two types of the Redis service depending on what you want to do with it.

Ephemeral Redis 

The ephemeral Redis service is configured to serve as a cache; its storage isn’t persistent.

Data in an ephemeral Redis instance is stored only in memory and thus requires no disk space. When the service hits its memory limit, it automatically evicts cache items according to the configured eviction rule to make room for new ones.

Your app must not treat ephemeral Redis as permanent. Instead, the cache needs to be regenerated as necessary. For example, if a container is moved for a reason such as region maintenance, the deploy and post_deploy hooks don’t run and an app that treats the cache as permanent shows errors. The cache should be cleared each time the app is restarted, in the start key in your web configuration.

If your app needs to treat the cache as permanent, use persistent Redis, which saves data to its volume even when the container is shut down.

Persistent Redis 

The redis-persistent service type is configured for persistent storage. That makes it a good choice for fast application-level key-value storage.

Relationship 

The format exposed in the $PLATFORM_RELATIONSHIPS environment variable:

{
    "username": null,
    "scheme": "redis",
    "service": "redis6",
    "fragment": null,
    "ip": "169.254.22.75",
    "hostname": "7mnenhdiz7ecraovljrba6pmiy.redis6.service._.eu-3.platformsh.site",
    "port": 6379,
    "cluster": "rjify4yjcwxaa-master-7rqtwti",
    "host": "redis.internal",
    "rel": "redis",
    "path": null,
    "query": [],
    "password": null,
    "type": "redis:6.0",
    "public": false,
    "host_mapped": false
}

The format is identical regardless of whether it’s a persistent or ephemeral service.

Usage example 

1. Configure the service 

Use the redis type for ephemeral Redis to define the service:

.platform/services.yaml
<SERVICE_NAME>:
    type: redis:<VERSION>

Or the redis-persistent type for persistent Redis:

.platform/services.yaml
<SERVICE_NAME>:
    type: redis-persistent:<VERSION>
    disk: 256

Persistent Redis requires a disk to store data.

Note that if you later change the name, it’s treated as an entirely new service. This removes all data from your service. Always backup your data before changing the service.

2. Add the relationship 

Use the redis endpoint to define the relationship:

.platform.app.yaml
relationships:
    <RELATIONSHIP_NAME>: "<SERVICE_NAME>:redis"

You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, but it’s best if they’re distinct.

For PHP, enable the extension for the service:

.platform.app.yaml
runtime:
    extensions:
        - redis

Ephemeral Redis example configuration

Service definition

.platform/services.yaml
cacheredis:
    type: redis:7.0

App configuration

.platform.app.yaml
relationships:
    rediscache: "cacheredis:redis"

# If using PHP
runtime:
    extensions:
        - redis

Persistent Redis example configuration

Service definition

.platform/services.yaml
data:
  type: redis-persistent:7.0
  disk: 256

App configuration

.platform.app.yaml
relationships:
  redisdata: "data:redis"

# If using PHP
runtime:
  extensions:
      - redis

Use in app 

Then use the service in your app with a configuration file like the following:

package sh.platform.languages.sample;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import sh.platform.config.Config;
import sh.platform.config.Redis;

import java.util.Set;
import java.util.function.Supplier;

public class RedisSample implements Supplier<String> {

    @Override
    public String get() {
        StringBuilder logger = new StringBuilder();

        // Create a new config object to ease reading the Platform.sh environment variables.
        // You can alternatively use getenv() yourself.
        Config config = new Config();

        // The 'database' relationship is generally the name of primary database of an application.
        // It could be anything, though, as in the case here here where it's called "redis".
        Redis database = config.getCredential("redis", Redis::new);
        JedisPool dataSource = database.get();

        // Get a Redis Client
        final Jedis jedis = dataSource.getResource();

        // Set a values
        jedis.sadd("cities", "Salvador");
        jedis.sadd("cities", "London");
        jedis.sadd("cities", "Sรฃo Paulo");

        // Read it back.
        Set<String> cities = jedis.smembers("cities");
        logger.append("<p>");
        logger.append("cities: " + cities);
        logger.append("</p>");
        jedis.del("cities");
        return logger.toString();
    }
}
const redis = require('redis');
const config = require("platformsh-config").config();
const { promisify } = require('util');

exports.usageExample = async function() {
    const credentials = config.credentials('redis');
    const client = redis.createClient(credentials.port, credentials.host);

    // The Redis client is not Promise-aware, so make it so.
    const redisGet = promisify(client.get).bind(client);
    const redisSet = promisify(client.set).bind(client);

    const key = 'Deploy day';
    const value = 'Friday';

    // Set a value.
    await redisSet(key, value);

    // Read it back.
    const test = await redisGet(key);

    return `Found value <strong>${test}</strong> for key <strong>${key}</strong>.`;
};
<?php

declare(strict_types=1);

use Platformsh\ConfigReader\Config;

// Create a new config object to ease reading the Platform.sh environment variables.
// You can alternatively use getenv() yourself.
$config = new Config();

// Get the credentials to connect to the Redis service.
$credentials = $config->credentials('redis');

try {
    // Connecting to Redis server.
    $redis = new Redis();
    $redis->connect($credentials['host'], $credentials['port']);

    $key = "Deploy day";
    $value = "Friday";

    // Set a value.
    $redis->set($key, $value);

    // Read it back.
    $test = $redis->get($key);

    printf('Found value <strong>%s</strong> for key <strong>%s</strong>.', $test, $key);

} catch (Exception $e) {
    print $e->getMessage();
}
from redis import Redis
from platformshconfig import Config


def usage_example():

    # Create a new config object to ease reading the Platform.sh environment variables.
    # You can alternatively use os.environ yourself.
    config = Config()

    # Get the credentials to connect to the Redis service.
    credentials = config.credentials('redis')

    try:
        redis = Redis(credentials['host'], credentials['port'])

        key = "Deploy day"
        value = "Friday"

        # Set a value
        redis.set(key, value)

        # Read it back
        test = redis.get(key)

        return 'Found value <strong>{0}</strong> for key <strong>{1}</strong>.'.format(test.decode("utf-8"), key)

    except Exception as e:
        return e

Multiple databases 

Redis 3.0 and above are configured to support up to 64 databases. Redis doesn’t support distinct users for different databases so one relationship connection gives access to all databases.

The way to access a particular database depends on the client library you’re using:

Use the Redis select command:

<?php
$redis->select(0);       // switch to DB 0
$redis->set('x', '42'); // write 42 to x
$redis->move('x', 1);  // move to DB 1
$redis->select(1);    // switch to DB 1
$redis->get('x');    // returns 42

To manage thread safety, the Python library suggests using separate client instances for each database:

from redis import Redis
from platformshconfig import Config

# Get the credentials to connect to the Redis service.
config = Config()
credentials = config.credentials('redis')

database0 = Redis(host='xxxxxx.cache.amazonaws.com', port=6379, db=0)
database1 = Redis(host='xxxxxx.cache.amazonaws.com', port=6379, db=0)

Use the Redis select command:

await client.SELECT(0);                  // switch to DB 0
await client.set('x', '42');            // write 42 to x
await client.MOVE('x', 1);             // move to DB 1
await client.SELECT(1);               // switch to DB 1
const value = await client.get('x'); // returns 42

Eviction policy 

On the Ephemeral redis service it’s also possible to select the key eviction policy. That controls how Redis behaves when it runs out of memory for cached items and needs to clear old items to make room.

cache:
    type: redis:5.0
    configuration:
        maxmemory_policy: allkeys-lru

The default value if not specified is allkeys-lru, which removes the oldest cache item first. The following values are allowed:

  • noeviction
  • allkeys-lru
  • volatile-lru
  • allkeys-lfu (Available as of Redis 4.0)
  • volatile-lfu (Available as of Redis 4.0)
  • allkeys-random
  • volatile-random
  • volatile-ttl

See the Redis documentation for a description of each option.

Using redis-cli to access your Redis service 

Assuming a Redis relationship named applicationcache defined in your app configuration:

.platform.app.yaml
relationships:
    rediscache: "cacheredis:redis"

and your service definition:

.platform/services.yaml
cacheredis:
    type: redis:7.0

The host name and port number obtained from PLATFORM_RELATIONSHIPS would be applicationcache.internal and 6379. Open an SSH session and access the Redis server using the redis-cli tool as follows:

redis-cli -h applicationcache.internal -p 6379

Using Redis as handler for native PHP sessions 

Using the same configuration but with your Redis relationship named sessionstorage:

.platform/services.yaml
data:
    type: redis-persistent:7.0
    disk: 256

.platform.app.yaml

relationships:
    sessionstorage: "data:redis"

variables:
    php:
        session.save_handler: redis
        session.save_path: "tcp://sessionstorage.internal:6379"