Redis (Object cache)
Back to home
On this page
Redis is a multi-model database that allows you to store data in memory for high-performance data retrieval and key-value storage. Platform.sh supports two different Redis configurations:
- Persistent: to set up fast persistent storage for your application
- Ephemeral: to set up a non-persistent cache for your application
Use a framework
If you use one of the following frameworks, follow its guide:
Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches.
Grid | Dedicated Gen 3 | Dedicated Gen 2 |
---|---|---|
|
|
|
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 in the future, so migrate to one of the supported versions.
Grid | Dedicated Gen 3 | Dedicated Gen 2 |
---|---|---|
|
|
|
Note that versions 3.0 and higher support up to 64 different databases per instance of the service, while Redis 2.8 only supports a single database.
Service types
Depending on your needs, you can set up Redis as persistent or ephemeral.
Relationship reference
Example information available through the PLATFORM_RELATIONSHIPS
environment variable
or by running platform relationships
.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed.
So your apps should only rely on the PLATFORM_RELATIONSHIPS
environment variable directly rather than hard coding any values.
{
"username": null,
"scheme": "redis",
"service": "redis",
"fragment": null,
"ip": "123.456.78.90",
"hostname": "azertyuiopqsdfghjklm.redis.service._.eu-1.platformsh.site",
"port": 6379,
"cluster": "azertyuiopqsdf-main-7rqtwti",
"host": "redis.internal",
"rel": "redis",
"path": null,
"query": [],
"password": null,
"type": "redis:7.2",
"public": false,
"host_mapped": false
}
The format of the relationship is identical whether your Redis service is ephemeral or persistent.
Persistent Redis
By default, Redis is an ephemeral service that stores data in memory. This allows for fast data retrieval, but also means data can be lost when a container is moved or shut down.
To solve this issue, configure your Redis service as persistent. Persistent Redis stores data on a disk, restoring it if the container restarts.
To switch from persistent to ephemeral Redis, set up a new service with a different name.
Warning
Platform.sh sets the maximum amount of memory (maxmemory
) Redis can use for the data set,
and it cannot be amended.
It is defined by comparing the following values and keeping the lower of the two:
- Disk size/6 (based on a recommendation from Redis)
- The amount of memory allocated to the service container
For instance, if your Redis container has 3072 MB of disk space and 1024 MB of memory, only 512 MB of RAM are actually available to the service (3072/6 = 512).
But if your Redis container has 3072 MB of disk space and 256 MB of memory, only 256 MB of RAM are actually available to the service (as per the container limit).
Usage example
1. Configure the service
To define the service, use the redis-persistent
endpoint:
# The name of the service container. Must be unique within a project.
<SERVICE_NAME>:
type: redis-persistent:<VERSION>
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
2. Define the relationship
To define the relationship, use the redis
endpoint :
# Relationships enable access from this app to a given service.
# The example below shows simplified configuration leveraging a default service
# (identified from the relationship name) and a default endpoint.
# See the Application reference for all options for defining relationships and endpoints.
relationships:
<SERVICE_NAME>:
You can define <SERVICE_NAME>
as you like, so long as it’s unique between all defined services and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships. That is, it uses default endpoints behind-the-scenes, providing a relationship (the network address a service is accessible from) that is identical to the name of that service.
Depending on your needs, instead of default endpoint configuration, you can use explicit endpoint configuration.
With the above definition, the application container now has access to the service via the relationship <SERVICE_NAME>
and its corresponding PLATFORM_RELATIONSHIPS
environment variable.
# Relationships enable access from this app to a given service.
# The example below shows configuration with an explicitly set service name and endpoint.
# See the Application reference for all options for defining relationships and endpoints.
# Note that legacy definition of the relationship is still supported.
# More information: https://docs.platform.sh/create-apps/app-reference/single-runtime-image.html#relationships
relationships:
<RELATIONSHIP_NAME>:
service: <SERVICE_NAME>
endpoint: redis
You can define <SERVICE_NAME>
and <RELATIONSHIP_NAME>
as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
Depending on your needs, instead of explicit endpoint configuration, you can use default endpoint configuration.
With the above definition, the application container now has access to the service via the relationship <RELATIONSHIP_NAME>
and its corresponding PLATFORM_RELATIONSHIPS
environment variable.
For PHP, enable the extension for the service:
# PHP extensions.
runtime:
extensions:
- redis
Configuration example
Service definition
# The name of the service container. Must be unique within a project.
redis:
type: redis-persistent:7.2
disk: 256
App configuration
relationships:
redis:
relationships:
redis:
service: redis
endpoint: redis
Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
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
Ephemeral Redis
By default, Redis is an ephemeral service that serves as a non-persistent cache. Ephemeral Redis stores data only in memory and requires no disk space. When the service reaches its memory limit, it triggers a cache cleanup. To customize those cache cleanups, set up an eviction policy.
Make sure your app doesn’t rely on ephemeral Redis for persistent storage as it can cause issues.
For example, if a container is moved during region maintenance,
the deploy
and post_deploy
hooks don’t run and an app that treats the cache as permanent shows errors.
To prevent data from getting lost when a container is moved or shut down, you can use the persistent Redis configuration. Persistent Redis provides a cache with persistent storage.
Usage example
1. Configure the service
To define the service, use the redis
endpoint:
# The name of the service container. Must be unique within a project.
<SERVICE_NAME>:
type: redis:<VERSION>
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
2. Define the relationship
To define the relationship, use the following configuration:
# Relationships enable access from this app to a given service.
# The example below shows simplified configuration leveraging a default service
# (identified from the relationship name) and a default endpoint.
# See the Application reference for all options for defining relationships and endpoints.
relationships:
<SERVICE_NAME>:
You can define <SERVICE_NAME>
as you like, so long as it’s unique between all defined services and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships. That is, it uses default endpoints behind-the-scenes, providing a relationship (the network address a service is accessible from) that is identical to the name of that service.
Depending on your needs, instead of default endpoint configuration, you can use explicit endpoint configuration.
With the above definition, the application container now has access to the service via the relationship <SERVICE_NAME>
and its corresponding PLATFORM_RELATIONSHIPS
environment variable.
# Relationships enable access from this app to a given service.
# The example below shows configuration with an explicitly set service name and endpoint.
# See the Application reference for all options for defining relationships and endpoints.
# Note that legacy definition of the relationship is still supported.
# More information: https://docs.platform.sh/create-apps/app-reference/single-runtime-image.html#relationships
relationships:
<RELATIONSHIP_NAME>:
service: <SERVICE_NAME>
endpoint: redis
You can define <SERVICE_NAME>
and <RELATIONSHIP_NAME>
as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
Depending on your needs, instead of explicit endpoint configuration, you can use default endpoint configuration.
With the above definition, the application container now has access to the service via the relationship <RELATIONSHIP_NAME>
and its corresponding PLATFORM_RELATIONSHIPS
environment variable.
For PHP, enable the extension for the service:
# PHP extensions.
runtime:
extensions:
- redis
Configuration example
Service definition
# The name of the service container. Must be unique within a project.
redis:
type: redis:7.2
disk: 256
App configuration
relationships:
redis:
relationships:
redis:
service: redis
endpoint: redis
Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
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 support up to 64 databases. But you can’t set up different access rights to each database. When you set up a relationship connection, access to all of the databases is automatically granted.
The way to access a particular database depends on the client library you’re using:
Use the Redis select
command:
<?php
$redis = new Redis();
$redis->connect(getenv('REDIS_HOST'), getenv('REDIS_PORT'));
$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:
import os
from redis import Redis
database0 = Redis(host=os.getenv('REDIS_HOST'), port=os.getenv('REDIS_PORT'), db=0)
database1 = Redis(host=os.getenv('REDIS_HOST'), port=os.getenv('REDIS_PORT'), db=1)
Use the Redis select
command:
const redis = require('redis');
const client = redis.createClient(process.env.CACHE_PORT, process.env.CACHE_HOST);
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
Restrict access to database replicas only
Feature availability
This feature is available on Grid HA (High Availability) and Dedicated Gen 3 projects. For more information, contact Sales.
For security reasons, you can grant your app access to replicas instead of your actual database. To do so, when defining the relationship between your app and database, make sure you do the following:
- Use the explicit endpoint syntax.
- Add the
-replica
suffix to the name of the endpoint you want to use.
This results in the following configuration:
relationships:
RELATIONSHIP_NAME:
service: SERVICE_NAME
endpoint: ENDPOINT_NAME-replica
For example, if you define a redis-persistent
database as follows:
postgresql:
type: "redis-persistent:16"
disk: 2048
configuration:
databases:
- main
- legacy
endpoints:
admin:
privileges:
main: admin
legacy: admin
reporter:
default_database: main
privileges:
main: ro
To create a replica of the redis-persistent
database and allow your app to connect to it
through the admin
endpoint with admin permissions,
use the following configuration:
relationships:
redis-persistent:
service: redis-persistent
endpoint: admin-replica
To create a replica of the redis-persistent
database and allow your app to connect to it
through the reporter
endpoint with read-only permissions instead,
use the following configuration:
relationships:
redis-persistent:
service: redis-persistent
endpoint: reporter-replica
Relationship reference
Example information available through the PLATFORM_RELATIONSHIPS
environment variable
or by running platform relationships
.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed.
So your apps should only rely on the PLATFORM_RELATIONSHIPS
environment variable directly rather than hard coding any values.
{
"username": null,
"scheme": "redis",
"service": "redis",
"fragment": null,
"ip": "123.456.78.90",
"hostname": "azertyuiopqsdfghjklm.redis.service._.eu-1.platformsh.site",
"port": 6379,
"cluster": "azertyuiopqsdf-main-7rqtwti",
"host": "redis.internal",
"rel": "redis",
"path": null,
"query": [],
"password": null,
"type": "redis:7.2",
"public": false,
"host_mapped": false
}
The format of the relationship is identical whether your Redis service is ephemeral or persistent.
Eviction policy
When Redis reaches its memory limit, it triggers a cache cleanup. To customize those cache cleanups, set up an eviction policy such as the following:
# The name of the service container. Must be unique within a project.
redis:
type: "redis:7.2"
configuration:
maxmemory_policy: allkeys-lfu
The following table presents the possible values:
Value | Policy description |
---|---|
allkeys-lru |
Removes the oldest cache items first. This is the default policy when maxmemory_policy isn’t set. |
noeviction |
New items aren’t saved when the memory limit is reached. |
allkeys-lfu |
Removes least frequently used cache items first. |
volatile-lru |
Removes least recently used cache items with the expire field set to true . |
volatile-lfu |
Removes least frequently used cache items with the expire field set to true . |
allkeys-random |
Randomly removes cache items to make room for new data. |
volatile-random |
Randomly removes cache items with the expire field set to true . |
volatile-ttl |
Removes cache items with the expire field set to true and the shortest remaining time-to -live value. |
For more information on the different policies, see the official Redis documentation.
Access your Redis service
After you’ve configured your Redis service, you can access it using either the Platform.sh CLI or through the Redis CLI.
Platform.sh CLI
Unlike the Redis CLI, connecting via the Platform.sh CLI does not require additional authentication steps if you are already authenticated in your terminal.
Access your Redis service by running the command:
platform redis
Redis CLI
Retrieve the hostname and port you can connect to
through the PLATFORM_RELATIONSHIPS
environment variable.
To do so, run the platform relationships
command.
After you’ve retrieved the hostname and port, open an SSH session. To access your Redis service, run the following command:
redis-cli -h HOSTNAME -p PORT
If you have a Grid project, note that the CONFIG GET
and CONFIG SET
admin commands are restricted.
To get the current configuration, run the following command:
redis-cli -h HOSTNAME -p PORT info
Use Redis as a handler for PHP sessions
A PHP session allows you to store different data for each user through a unique session ID. By default, PHP handles sessions using files. But you can use Redis as a session handler, which means Redis stores and retrieves the data saved into sessions.
To set up Redis as your session handler, add a configuration similar to the following:
# The name of the service container. Must be unique within a project.
redissessions:
type: "redis-persistent:7.2"
disk: 256
name: myapp
type: "php:8.4"
relationships:
redissessions:
variables:
php:
session.save_handler: redis
session.save_path: "tcp://HOSTNAME:PORT"
web:
locations:
'/':
root: 'web'
passthru: '/index.php'
name: myapp
type: "php:8.4"
relationships:
redissessions:
service: "redissessions"
endpoint: "redis"
variables:
php:
session.save_handler: redis
session.save_path: "tcp://HOSTNAME:PORT"
web:
locations:
'/':
root: 'web'
passthru: '/index.php'