Memory Caching

Introduction

You can significantly improve ownCloud server performance by using memory caching. This is the process of storing frequently requested objects in memory for faster retrieval later. There are two types of memory caching available:

A PHP opcode Cache (OPcache)

An opcode cache stores compiled PHP scripts (opcodes) so they don’t need to be parsed and compiled every time they are called. These compiled PHP scripts are stored in shared memory on the server on which they’re compiled.

A Data Cache

A data cache stores copies of data, templates, and other types of information-based files. Depending on the cache implementation, it can be either local or specific to one server or distributed across multiple servers. This cache type is ideal when you have a scale-out installation.

In addition, we suggest to use External Transactional File Locking which reduces load on the database significantly.

Supported Caching Backends

The caching backends supported by ownCloud are:

  • Opcache
    This is an opcode cache only and does not cache any data. Opcache is bundled with PHP from version 5.5.0 and later.

  • APCu
    This is a data cache only and does not cache any opcode. APCu 4.0.6 and up is required.

  • Redis
    This is an in-memory data structure store (cache) for single and multi-server ownCloud installations, which provides file locking and can be set up in local or distributed environments. Consider Redis younger, richer in features and more configurable than memcached. At least version 2.2.6 or higher of the PHP Redis extension is required.

  • Memcached
    This is a distributed cache for multi-server ownCloud installations and has no file locking capabilities.

See the following page to learn more about the Redis vs. Memcached – 2021 Comparison.

You may use both a local and a distributed cache. The recommended ownCloud caches are APCu and Redis. If you do not install and enable a local memory cache you will see a warning on your ownCloud admin page. If you enable only a distributed cache in your config.php (memcache.distributed) and not a local cache (memcache.local) you will still see the cache warning.

Cache Directory Location

The cache directory defaults to data/$user/cache where $user is the current user. You may use the 'cache_path' directive in your configuration for different locations. For details see the Define the location of the cache folder description.

Cache Types

Opcache

Opcache should be enabled by default in your php installation. To check it, run the following command:

php -r 'phpinfo();' | grep opcache.enable

APCu

The easiest cache to use is APCu, because it is a pure data cache, very fast as it is memory-based only and nothing needs to be configured. APCu can not be used when running on an external server like in a distributed environment.

Installing APCu

On Ubuntu/Debian/Mint systems, if not already done:

sudo apt install php-apcu

With that done, assuming that you don’t encounter any errors, restart Apache and the extension is ready to use.

Redis

Redis is an excellent modern memory cache to use for both distributed caching and as a local cache for transactional file locking, because it guarantees that cached objects are available for as long as they are needed.

The performance of Redis when used with a socket connection can get close to the performance of APCu.

The Redis PHP module must be at least version 2.2.6 or higher.
  • For Ubuntu 20.04, the default shipped Redis Server version and the php-redis extension is 5.x.

  • For Ubuntu 22.04, the default shipped Redis Server version is 6.0.16.

  • For Ubuntu 22.04, the php7.4-redis extension has version 5.3.x.

  • With Redis version 6, a new authentication mechanism has been introduced named ACL (Access Control Lists). ownCloud does currently not support Redis ACLs, but does support the password protection available with current Redis versions.

Installing Redis

On Ubuntu/Debian/Mint systems, if not already done:

sudo apt install redis-server php-redis

The installer will automatically launch Redis and configure it to launch at startup.

After that, assuming that you don’t encounter any errors, restart Apache and the extension is ready to use.

Redis Performance Consideration

  • Because Redis writes data to disk, it is recommended to use a high performance backend like SSD.

  • If you do not have a distributed environment where the Redis server is installed at a different machine, you can configure Redis to be socket-based instead of TCP-based to increase performance.

Additional notes for Redis vs. APCu on Memory Caching

  • APCu is faster at local caching than Redis when using TCP since APCu is memory-based only.

  • If you have enough memory, use APCu for in memory caching and Redis for file locking.

  • If you are limited in memory or only want to have one caching backend, use Redis for both.

  • Consider using sockets instead of TCP when you decide on Redis but do not have a distributed caching environment.

Clearing the Redis Cache

The Redis cache can be flushed from the command-line using the redis-cli tool, as in the following example:

sudo redis-cli
SELECT <dbIndex>
FLUSHDB

<dbIndex> is the number of the Redis database where the cache is stored. It is zero by default at ownCloud. To check what yours is currently set to for ownCloud, check the dbindex value in config/config.php. To change it, see the Memory caching backend configuration

Out of the box, every Redis instance supports 16 databases so <dbIndex> has to be set between 0 and 15.

Please read more about the instructions for the select and flushdb command.

Memcached

Memcached is a reliable old-timer for shared caching on distributed servers. It performs well with ownCloud with one exception: it is not suitable to use with Transactional File Locking. This is because it does not store locks, and data can disappear from the cache at any time. Given that, Redis is the best memory cache to use.

Be sure to install the memcached PHP module, and not memcache, as in the following examples. ownCloud supports only the memcached PHP module.

Installing Memcached

On Ubuntu/Debian/Mint

On Ubuntu/Debian/Mint run the following command:

sudo apt-get install memcached php-memcached
The installer will automatically start memcached and configure it to launch at startup.

Configuration File Paths

PHP Version Filename

7.4

/etc/php/7.4/mods-available/memcached.ini

Note that the PHP version depends on your envoronment.

After that, assuming that you don’t encounter any errors:

  1. Restart your Web server

  2. Add the appropriate entries to config.php (which you can find an example of below)

  3. Refresh your ownCloud admin page

Clearing the Memcached Cache

The Memcached cache can be flushed from the command line, using a range of common Linux/Unix tools including netcat and telnet. The following example uses telnet to log in, run the flush_all command, and log out:

telnet localhost 11211
flush_all
quit

Configuring Memory Caching

Memory caches must be explicitly configured in ownCloud by:

  1. Installing and enabling your desired cache (whether that be the PHP extension and/or the caching server).

  2. Adding the appropriate entry to ownCloud’s config.php.

See the Memory caching backend configuration for an overview of all possible config parameters, as the examples below only show basic configuration settings. After installing and enabling your chosen memory cache, verify that it is active by viewing the PHP configuration details.

Opcache Configuration

Opcache should already be configured with PHP 7, see the opcache documentation for details.

APCu Configuration

To use APCu, add this line to config.php:

'memcache.local' => '\OC\Memcache\APCu',

With that done, refresh your ownCloud admin page, and the cache warning should disappear.

Redis Configuration

Redis is very configurable; consult the Redis documentation to learn more.

Regardless of whether you have set up Redis to use TCP or a Unix socket, we recommend adding the following for best performance. This enables External Transactional File Locking based on Redis:

'filelocking.enabled' => true,
'memcache.locking' => '\OC\Memcache\Redis',

Redis Configuration Using TCP

The following example config.php configuration connects to a Redis cache via TCP:

'memcache.local' => '\OC\Memcache\Redis',
'redis' => [
    'host' => 'localhost',  // For a Unix domain socket, use '/var/run/redis/redis.sock'
    'port' => 6379,         // Set to 0 when using a Unix socket
    'timeout' => 0,         // Optional, keep connection open forever
    'password' => '',       // Optional, if not defined no password will be used.
    'dbindex' => 0,         // Optional, if undefined SELECT will not run and will
                            // use Redis Server's default DB Index.
],

Redis Configuration Using Unix Sockets

If Redis is running on the same server as ownCloud, it is recommended to configure it to use Unix sockets for increased performance. Follow these steps to do so:

  1. Add the www-data user to the redis group:

    sudo usermod -G redis -a www-data
  2. Create your Redis folder that the Unix socket will be in:

    sudo mkdir -p /var/run/redis/
  3. Set the permissions so the redis user and www-data group own it:

    sudo chown -R redis:www-data /var/run/redis
  4. Open an editor of your choice and change/add the following parameters to the Redis configuration file. Note that in the example vi is used as editor:

    sudo vi /etc/redis/redis.conf
    # create a unix domain socket to listen on
    unixsocket /var/run/redis/redis.sock
    
    # set permissions for the socket
    unixsocketperm 770
  5. Restart Redis to make the changes effective:

    sudo service redis-server restart
  6. Check if the Redis Unix socket was created:

    ls -lh /var/run/redis

    The output should be like the following:

    srwxrwx--- 1 redis redis 0 May 12 12:26 redis.sock

Then, configure ownCloud to communicate with the Redis socket as in the following example.

# Change the host value, based on the socket's location in your distribution
'memcache.local' => '\OC\Memcache\Redis',
'redis' => [
    'host' => '/var/run/redis/redis.sock',
    'port' => 0,       // Set to 0 when using a Unix socket
    'password' => '',  // Optional, if not defined no password will be used.
    'dbindex' => 0,    // Optional, if undefined SELECT will not run and will
                       // use Redis Server's default DB Index.
],

Redis Performance Comparison TCP vs Socket

To see a benchmark comparison, run:

sudo redis-benchmark -q -n 100000
sudo redis-benchmark -s /var/run/redis/redis-server.sock -q -n 100000

In the following table, you will see an example gain of about +20% when using sockets compared to TCP on localhost. The values can differ in your environment. Please do a local check.

Test TCP (requests/s) Socket (requests/s) Gain (%)

PING_INLINE

15527.95

23518.35

+34

PING_BULK

16946.28

23239.60

+27

SET

18351.99

22789.43

+19

GET

18850.14

22747.95

+17

INCR

18663.68

22914.76

+18

LPUSH

19109.50

24183.79

+21

RPUSH

19076.69

23196.47

+18

LPOP

18460.40

23485.21

+21

RPOP

19058.51

24752.47

+23

SADD

18932.22

22391.40

+15

HSET

18491.12

20785.70

+11

SPOP

19069.41

23282.89

+18

LPUSH

19087.61

23764.26

+20

LRANGE_100

15288.18

17882.69

+15

LRANGE_300

9067.00

10004.00

+10

LRANGE_500

6878.53

7496.25

+8

LRANGE_600

5379.24

6102.77

+12

MSET (10 keys)

19297.57

18178.51

-6

Memcached Configuration

This example uses APCu for the local cache, Memcached as the distributed memory cache, and lists all the servers in the shared cache pool with their port numbers:

'memcache.local' => '\OC\Memcache\APCu',
'memcache.distributed' => '\OC\Memcache\Memcached',
'memcached_servers' => [
     ['localhost', 11211],
     ['server1.example.com', 11211],
     ['server2.example.com', 11211],
 ],

Configure Transactional File Locking

Transactional File Locking prevents simultaneous file saving. It is enabled by default and uses the database to store the locking data. This places a significant load on your database. It is recommended to use a cache backend instead. You have to configure it in config.php as in the following example, which uses Redis TCP as the cache backend:

'filelocking.enabled' => true,
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => [
     'host' => 'localhost',
     'port' => 6379,
     'timeout' => 0,
     'password' => '',     // Optional, if not defined no password will be used.
 ],
For enhanced security, it is recommended to configure Redis to require a password. See https://redis.io/topics/security for more information.

Configuration Recommendations Based on Type of Deployment

The examples give you an overview, adapt them to your environment and your needs.

Private Home Server With Low Access Rates

Use APCu for local caching, file locking is not mandatory.

'memcache.local' => '\OC\Memcache\APCu',

Small Server

Use APCu for local caching and Redis for file locking.

'filelocking.enabled' => true,
'memcache.local' => '\OC\Memcache\APCu',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => [
    'host' => 'localhost',
    'port' => 6379,
],

Small Organization, Single-server Setup

Use Redis Socket for local caching and for file locking.

'filelocking.enabled' => true,
'memcache.local' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => [
    'host' => '/var/run/redis/redis.sock',
    'port' => 0,
],

Large Organization, Clustered Setup

Use Redis for everything except a local memory cache. Use the server’s IP address or hostname so that it is accessible to other hosts:

'filelocking.enabled' => true,
'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'memcache.local' => '\OC\Memcache\APCu',
'redis' => [
    'host' => 'server1',      // hostname example
    'host' => '12.34.56.78',  // IP address example
    'port' => 6379,
],

See Define Redis Cluster connection details when using a Redis clustered setup.

Caching Exceptions

If ownCloud is configured to use either Memcached or Redis as a memory cache, you may encounter issues with functionality. When these occur, it is usually a result of PHP being incorrectly configured or the relevant PHP extension not being available.

In the table below, you can see all of the known reasons for reduced or broken functionality related to caching.

Setup/Configuration Result

If file locking is enabled, but the locking cache class is missing, then an exception will appear in the web UI

The application will not be usable

If file locking is enabled and the locking cache is configured, but the PHP module missing.

There will be a white page/exception in web UI. It will be a full page issue, and the application will not be usable

All enabled, but the Redis server is not running

The application will be usable. But any file operation will return a "500 Redis went away" exception

If Memcache is configured for local and distributed, but the class is missing

There will be a white page and an exception written to the logs, This is because autoloading needs the missing class. So there is no way to show a page