Use and configure Redis or Valkey as a key-value store
Edit on GitHubThis document describes how key-value storage (Redis or Valkey) is used within Spryker. The current functionality can be extended according to your needs.
Spryker supports both Redis and Valkey as key-value storage solutions. For detailed information about the differences, compatibility, and migration considerations, see Key-value store architecture (Redis and Valkey).
About key-value storage
Redis is an open-source, in-memory key-value data store that supports a large collection of data structures, including strings, hashes, lists, sets, and more. It provides high performance and flexibility for caching and data storage.
Valkey is an open-source, high-performance key-value datastore that supports the Redis protocol and APIs. It’s developed under the Linux Foundation and offers:
- Full Redis compatibility
- High performance and scalability
- Active community development
- Enterprise-grade reliability
Both solutions provide the same functionality within Spryker and can be used interchangeably.
The following table shows how translations are stored:
LOCALE | KEY | VALUE |
---|---|---|
de_DE | kv:de.de_de.glossary.translation.global.cart |
Warenkorb |
en_US | kv:de.en_us.glossary.translation.global.cart |
Cart |
The values for the translations are stored as strings, but more complex types, such as product information, are stored in JSON format.
The key name follows this format: kv:{store}{locale}{resource-type}{key}
.
Redis data storage
The data stored in the key-value store (Redis or Valkey) includes the following:
- URL mappings
- Product details
- Product category details
- Stock information
- Translations
- CMS pages and blocks
How data is loaded into Redis
Data is loaded in the key-value store (Redis or Valkey) through a dedicated console command. This console command is executed when the application is initially installed, but you can execute it also from the command line:
console sync:data
For more information about how the Publish and Synchronization process works and how to extend them, see Publish and Synchronization.
How data is kept in sync
Of course, the data stored in the SQL database is the subject of change; data can be updated or deleted, or new entries can be added. The data currently stored in the key-value store (Redis or Valkey) is a snapshot of the data in the SQL database from when the last update was run. The key-value data storage must be kept in sync with the data persisted in the SQL database. To achieve this, you must set up a cron job that runs on a specified time interval and updates the key-value data storage.
For more information, see Cronjob scheduling.
Also, you need to find out which data has changed because you don’t want to completely reload the content stored in the key-value store (Redis or Valkey). The Touch
module takes care of marking the items that were updated in the meantime.
Every time you make an update delete insert request for data that is also stored in the key-value store (Redis or Valkey), you must touch that data so that it’s marked for export when the next storage update task runs.
Browse the data from the key-value store (Redis or Valkey)
To browse the data that’s stored in the key-value store (Redis or Valkey), you can use Redis-compatible desktop managers such as Redis Desktop Manager (RDS) or RedisInsight. Since Valkey maintains full Redis protocol compatibility, any Redis client will work with both Redis and Valkey.
For Redis Desktop Manager, install RDS and then configure it as shown on the following screenshot.
Find the current key-value store port in config/Shared/config_default-development.php
.
Make sure that your virtual machine is up and running.
Use the data stored in the key-value store (Redis or Valkey)
This section describes how you can use data stored in the key-value store (Redis or Valkey).
Translations
To show content translated according to the selected locale, you can use the translation extension from the twig
file; you need to specify the key name and pipe it to the trans
extension. When rendered, the value corresponding to the selected locale for that key is be shown—for example:
<button>{{ "page.detail.add-to-cart"|trans }}</button>
The caption for the button depends on the selected locale:
LOCALE | KEY | VALUE |
---|---|---|
de_DE | kv:de.de_de.glossary.translation.page.detail.add-to-cart |
In den Warenkorb. |
en_US | kv:de.en_us.glossary.translation.page.detail.add-to-cart |
Add to Cart . |
Access the key-value store (Redis or Valkey) data storage
Key-value data storage (Redis or Valkey) is accessed using StorageClient
. The StorageClient
provides a unified interface that works seamlessly with both Redis and Valkey backends.
The StorageClient
can be obtained as an external dependency in the client layer for Yves. In the dependency provider of the client layer from your module, add the StorageClient
dependency as in the following example:
<?php
const CLIENT_STORAGE = 'CLIENT_STORAGE';
/**
* @param \Spryker\Client\Kernel\Container $container
*
* @return \Spryker\Client\Kernel\Container
*/
public function provideServiceLayerDependencies(Container $container)
{
$container[static::CLIENT_STORAGE] = function (Container $container) {
return $container->getLocator()->storage()->client();
};
return $container;
}
Add a method that retrieves an instance of the key-value storage in the factory of the Client
layer of your module:
<?php
/**
* @return \Spryker\Client\Storage\StorageClientInterface
*/
public function getStorageClient()
{
return $this->getProvidedDependency(MyBundleDependencyProvider::CLIENT_STORAGE);
}
To retrieve the value for a given key, you can use the get($key)
operation from StorageClient
.
<?php
$storedValue = $this->storageClient->get($myKey);
Use a password for accessing key-value storage
You can define a password to restrict access to the key-value store (Redis or Valkey). Spryker provides the \Spryker\Shared\Storage\StorageConstants::STORAGE_REDIS_PASSWORD
configuration option that can be used to configure the key-value store client to authenticate Spryker.
To activate it, specify the redis
protocol for \Spryker\Shared\Storage\StorageConstants::STORAGE_REDIS_SCHEME
(the Spryker Demo Shop uses tcp
by default).
All Redis configuration parameters (prefixed with REDIS_*
) work seamlessly with both Redis and Valkey since Valkey maintains full Redis protocol compatibility.
Use and configure key-value storage cache
To boost the performance in Spryker even more, we have built a caching mechanism to cache all used key-value store keys on any page in the shop.
A page in the shop often contains many different key-value store entries for various content and information it has. For example, a product title, a description, and attributes on a product details page. All of this data is stored in many key-value store key-value pairs. To retrieve the data for a page, multiple GET requests are needed, so if a page uses 100 key-value store key-value pairs, then 100 GET requests are needed to retrieve the data.
To optimize the data retrieval from the key-value store (Redis or Valkey), we designed an algorithm to store all the needed keys in a given page in the shop in only one key-value store key and then use one Redis MGET (multi-get) request to retrieve all the data. Using the implemented algorithm, only two requests to the key-value store (Redis or Valkey) are needed for most of the pages: one GET request to get the cache entry and one MGET requests to get all the data.
the key-value store (Redis or Valkey) cache for a page is basically a key-value pair. The key of the cache is the prefix StorageClient_
followed by the URL of the page, while the value of the cache is simply a list of all key-value store keys used on the cached page.
When accessing a new page, the algorithm checks if a cache for it’s already built. If yes, the page uses or refreshes the cache if needed; otherwise, the algorithm builds a new cache.
Spryker provides three caching strategies to build the list of the keys in the cache entry:
- Replacement strategy. This strategy overwrites the list of the keys in a cache with a new one every time a cached page is accessed. This strategy is useful with static pages where the list of keys for these does not change often. This is a default strategy when a strategy is not specified.
- Incremental strategy. This strategy increments the list of keys inside the cache until the limit’s exceeded. The default limit’s 1000 keys. The incremental strategy is useful with a page that uses configurators—for example, variants where the cache stores all the different combinations.
- Inactive strategy. This strategy deactivates the cache for a specified page.
All the cache entries have a default TTL of one day. The cache is removed after one day, and a new one is generated for different pages when accessing them.
How to add and configure the cache
The cache works on the controller level. This means that you can define what strategy a controller uses for all of its actions. By default, the cache is active and uses the Replace strategy.
To specify what cache strategy a controller uses, only two steps are required:
- Use the Yves
AbstractController
.
use Pyz\Yves\Application\Controller\AbstractController;
- Define the cache strategy by assigning the value to the
STORAGE_CACHE_STRATEGY
constant—for example, an incremental strategy is defined in the following code.
const STORAGE_CACHE_STRATEGY = StorageConstants::STORAGE_CACHE_STRATEGY_INCREMENTAL;
That is it!
To change the default configuration values for the TTL and the key-size limit for the incremental strategy, you can extend StorageConfig
and override the following methods:
- To change the limit size for the incremental strategy, override
getStorageCacheIncrementalStrategyKeySizeLimit
. - To change the TTL for the cache, override
getStorageCacheTtl
.
Thank you!
For submitting the form