fbpx

Magento / Web Apps

Magento 2 Redis Configuration

by , , revisited on


We have by far the largest RPM repository with NGINX module packages and VMODs for Varnish. If you want to install NGINX, Varnish, and lots of useful performance/security software with smooth yum upgrades for production use, this is the repository for you.
Active subscription is required.

Magento 2 is quite fast if you know how to configure it. One of the complementary programs to help with Magento speedup is Redis.

Redis is server software that allows applications to store their data in memory, which is the fastest storage. Magento can leverage Redis to store its cache for faster performance.

Magento 2 allows both full page cache and general cache to be stored in Redis. Additionally, you can have user sessions stored in Redis.

Before we can properly configure Redis in Magento 2, we must set up and configure Redis itself.

Configure Redis for Magento 2

1. Installing latest Redis on CentOS/RHEL 7

yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
yum install https://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum --enablerepo=remi install redis

Enable it at runtime and at boot time with:

systemctl enable --now redis

2. Configure memory limit in Redis

We are going to use Redis for caches and sessions. We have to configure the memory limit so that it does not exhaust our RAM over time. Edit /etc/redis.conf as appropriate for your cache maximum storage. For example, for a cache up to 4GB in RAM, use:

maxmemory 4096mb
maxmemory-policy allkeys-lfu

The allkeys-lfu is an eviction policy that removes any key using approximated LFU.
This will ensure that frequently used data stays in the cache, while the least used data can be removed in order to keep our cache size to a sane limit.

3. Configure Redis UNIX socket

For a typical all-in-one server setup, it is recommended to use UNIX sockets for inter-process communication.
Thus, in the same configuration file, enable Redis to listen on a UNIX socket with these lines:

unixsocket /var/run/redis/redis.sock
unixsocketperm 0660

4. Grant your website user access to the Redis socket

usermod -a -G redis example

5. Ensure multiple Redis instances for different data

You’re much recommended to allocate separate Redis instances (services), even on the same server, for each stored data type.

The reason being is that Magento 2 being a buggy software with buggy plugins, can easily wipe out your sessions when you clean caches.
This may happen whether you use different database IDs or not.

It is easy to create a separate instance of Redis, by copying its SystemD unit file and customizing it with different port/socket location.

For example, the original SystemD unit file can be used for general cache storage.

It is located under /usr/lib/systemd/system/redis.service. You can copy it for creating another instance, e.g. for sessions:

cp -p /usr/lib/systemd/system/redis.service /etc/systemd/system/redis-sessions.service

Now edit it so it looks like the following:

[Unit]
Description=Redis persistent key-value database (sessions)
After=network.target

[Service]
ExecStart=/usr/bin/redis-server /etc/redis-sessions.conf --supervised systemd
ExecStop=/usr/libexec/redis-shutdown redis-sessions

# Write PID file: https://github.com/antirez/redis/issues/3716
ExecStartPost=/bin/sh -c "echo $MAINPID > /var/run/redis-sessions/redis-sessions.pid"

Type=notify
User=redis
Group=redis
RuntimeDirectory=redis-sessions
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target

The parts that will be different from the original unit are ExecStart specifying a different configuration file, and ExecStop providing the base name of that configuration file.
This is required so that the separate instance is launched and stopped using a different port and socket path.
We have to create the aforementioned instance-specific configuration files by copying the original and editing it, specifying different port and socket path:

cp -p /etc/redis.conf /etc/redis-sessions.conf # then edit

Another change to the original unit file is that we put a different RuntimeDirectory.
This is essential so that our instances “don’t step onto each other’s” runtime files during startup or shutdown.

How to configure Magento caches and PHP sessions to be stored in Redis

Magento 2.2.x and above

The easiest way to manage your Magento 2 Redis caches is via command-line.

Once you have configured the Redis instances, you can finally resort to the Magento CLI interface to configure everything to cache onto Redis, with the following commands:

bin/magento setup:config:set --cache-backend=redis --cache-backend-redis-server=/var/run/redis/redis.sock --cache-backend-redis-db=0

bin/magento setup:config:set --page-cache=redis --page-cache-redis-server=/var/run/redis-fpc/redis-fpc.sock --page-cache-redis-db=1

yes | bin/magento setup:config:set --session-save=redis --session-save-redis-host=/var/run/redis-sessions/redis-sessions.sock --session-save-redis-log-level=3 --session-save-redis-db=2 --session-save-redis-max-concurrency=20

Note how we are specifying different socket paths, essentially making use of our extra Redis instances.
We could have omitted the database number specifiers, but we keep it around for edge cases where one instance is to be used.

  • The first command configures Magento 2 to store the general cache to Redis.
  • The second command configures Magento 2 to store the full page cache to Redis.
  • Finally, the third command configures Magento 2 to store user sessions to Redis.

We prepend it with yes | in order to accept possible prompt: To deal with "Overwrite the existing configuration for session-save?[Y/n]" prompt..

All three commands specify the paths to Redis sockets, which makes sense only if Redis runs on the same machine where Magento files are located.

Important note about the sessions max concurrency

The --session-save-redis-max-concurrency=20 switch as specified above, is required for a sane website function because the default value of 6 is too low for any situation.
See related issue for details.

If you see an error in your var/log/exception.log like the following:

main.CRITICAL: Warning: session_start(): Failed to read session data …

It means that you need to increase max concurrency further by running, e.g. n98-magerun2 config:env:set session.redis.max_concurrency 30.
It is also recommended to use bot session fix module which prevents session creation for bots.

Older Magento 2 versions

If your Magento 2 is older than 2.2 you’ll have to get your hands a bit dirty by editing PHP configuration files.

How to configure Magento 2 (versions below 2.2) cache to be stored in Redis

Add the following to app/etc/env.php:

'cache' => array (
    'frontend' => array (
        'default' => array (
            'backend' => 'Cm_Cache_Backend_Redis',
            'backend_options' => array (
                'server' => '/var/run/redis/redis.sock',
                'port' => '6379',
                'database' => '0'
            ),
        ),
        'page_cache' => array (
            'backend' => 'Cm_Cache_Backend_Redis',
            'backend_options' => array (
                'server' => '/var/run/redis-fpc/redis-fpc.sock',
                'port' => '6380',
                'database' => '1',
                'compress_data' => '0' 
            )
        )
    )
),

The cache settings specified above are for: default cache (which bears basic Magento data) and page_cache (which is the full page cache).

If you already make use of Varnish for full page cache (specified it in Magento admin), you can omit the page_cache settings array and simply put:

'cache' => array (
    'frontend' => array (
        'default' => array (
            'backend' => 'Cm_Cache_Backend_Redis',
            'backend_options' => array (
                'server' => '/var/run/redis/redis.sock',
                'port' => '6379',
                'database' => '0'
            ),
        ),
    )
),

Otherwise, both Varnish and Redis will simultaneously store full page cache. Having Varnish and Redis store cache works fine, but you want to keep only one cache of this type in order to save on RAM/CPU.

How to configure Magento 2 (versions below 2.2) sessions to be stored in Redis

Add the following to app/etc/env.php:

'session' => array (
    'save' => 'redis',
    'redis' => array (
        'host' => '/var/run/redis-sessions/redis-sessions.sock',
        'port' => '6381',
        'password' => '',
        'timeout' => '2.5',
        'persistent_identifier' => '',
        'database' => '2',
        'compression_threshold' => '2048',
        'compression_library' => 'gzip',
        'log_level' => '1',
        'max_concurrency' => '20',
        'break_after_frontend' => '5',
        'break_after_adminhtml' => '30',
        'first_lifetime' => '600',
        'bot_first_lifetime' => '60',
        'bot_lifetime' => '7200',
        'disable_locking' => '0',
        'min_lifetime' => '60',
        'max_lifetime' => '2592000'
    )
),

As a final note, make sure that the database setting is different for all types of data that is stored in Redis if you don’t use separate instance.
In our example configs, sessions are stored into Redis database 2, whereas general cache and full page cache are stored in Redis databases 0 and 1 respectively.

But because they are using different instances, database numbers are not essential.

Caveats and gotchas

For Magento 2.4.0

The new module introduced with this version creates numerous hash entries and stores them into the Redis cache.
This quickly results in out-of-memory conditions, if your Redis is not configured with maxmemory settings.
As a workaround, disable the module with clearmage2:

clearmage2 --disable Magento_Csp

Or, using magento CLI:

php bin/magento module:disable Magento_Csp

Still find Magento 2 extremely slow even after configuring Redis? Let me help you with that! 🙂

  1. Norman

    how about configure Magento 2 with Redis cluster? I didn’t find any information for this configuration.

    Reply
  2. Hub

    Hello Danila,
    i have a question to you sentence “If you already make use of Varnish for full page cache , you can omit the page_cache settings array. “.

    For some reason i dont know it does not work to omit the second array . There is a mistake with too much “,” or ” ” when i do this. After that the site gets “weird”.

    Can you please post the solution without the page_cache settings array?

    Is it necessary to generate different databases (1,2,3) beforehand, or does redis it on its own?

    Reply
    • Danila Vershinin

      Trailing , after PHP array declaration is fine. See update. You don’t need to do anything beforehand in regards with Redis database. Just make sure to configure different database numbers for different caches.

      Reply
      • Hub

        Hello,
        thanks for your support. It were just the lines i used.

        If I only append them to the env.php (your setting ‘backend’ => ‘Cm_Cache_Backend_Redis’ (your last block)) the admin backend is no more accessible and also the frontend does not work anymore. If i put into CLI /bin/magento cache:flush no response from the CLI.

        WITHOUT the ‘backend’ => ‘Cm_Cache_Backend_Redis’ everything works and also the cache:flush command gives successful response.

        Please note. the session storage works and i get successful data from the redis-cli monitor.

        It’s only the Cm_Cache_Backend_Redis which does not work.

        I have installed Varnish for the frontend, which works.

        Reply
        • Danila Vershinin

          Obviously, you should not append those lines. The lines should go in between return array ( and trailing ); lines.
          To make sure that your edits produce valid PHP file, you can check it for syntax errors with php -l app/etc/env.php.

          Try to locate the following lines:

            'crypt' =>
            array (
              'key' => 'xxxxxx',
            ),
          

          And put the suggested configuration lines right above or below them.

          Reply
          • Hub

            Hello Danila,

            thank you, that was it!!
            i but it after the last “);“ of the PHP command and not before.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.