Cache
Jadu caches the results of many database queries to improve performance. By default, cache files are stored on the server file system.
When deploying a site over multiple servers it is desirable to synchronise the deleting of particular parts of the cache. For example, if a Jadu Central user updates a piece of content then the cache should be cleared on all servers so that users of the web site all see the new content.
Types of cache
As well as the data cache used for storing the result of database queries, a number of other caches are used.
Application cache
Jadu Central uses Symfony, and after applying an update or changing template files or service definitons, the Symfony cache will require clearing and warming.
When deploying a package, this is handled automatically by the meteor patching tool, however this can also be carried out manually using cli.php
:
php cli.php cms:clear-cache
php -d memory_limit=500M cli.php cache:warmup --kernel=frontend
php -d memory_limit=500M cli.php cache:warmup --kernel=cc
There are distinct caches for the frontend website and Control Center application, so these both need to be warmed separately.
Config cache
Although the general application cache may be stored in Redis or memcached, the config cache is always stored on the filesystem. After any change to application configuration you will therefore need to remove these cache files for the changes to take effect. This can be done from the cacheBash.php
page.
Cache configuration
There are 3 supported locations for cache storage:
- filesystem
- memcached
- Redis
Filesystem
Filesystem is the default storage location of the cache. Jadu can be configured to use the filesystem by editing <install_path>/config/system.xml
and changing the value of CACHE_DATA_STORE
to file
.
<cache_data_store>file</cache_data_store>
Redis
Redis is an in-memory data structure store that can be used as a cache. It is necessary for the redis PHP extension to be installed to take advantage of this functionality.
Redis is our recommended cache solution for clustered Windows systems.
Jadu can be configured to use memcached by editing <install_path>/config/datastore.xml
.
First add details of the memcached servers as follows.
<?xml version="1.0" encoding="utf-8" ?>
<datastore xmlns:config="http://www.jadu.co.uk/schema/config">
<redis>
<servers>
<server host="localhost" port="6379"/>
</servers>
</redis>
</datastore>
It is also necessary to change the value of the CACHE_DATA_STORE
(within the system.xml config) constant to redis
, rather than file
.
<cache_data_store>redis</cache_data_store>
Memcached
Memcached is a distributed object caching system. It can be used to store a single copy of the Jadu cache over multiple servers rather than on each individual file system. It is necessary for the memcached PHP extension to be installed to take advantage of this functionality.
Jadu can be configured to use memcached by editing <install_path>/config/datastore.xml
.
First add details of the memcached servers as follows.
<?xml version="1.0" encoding="utf-8" ?>
<datastore xmlns:config="http://www.jadu.co.uk/schema/config">
<memcached>
<servers>
<server host="memcached-1" port="11211"/>
</servers>
</memcached>
</datastore>
It is also necessary to change the value of the CACHE_DATA_STORE
constant to memcached
, rather than file
.
<cache_data_store>memcached</cache_data_store>
Use of caching in the application
Caching is handled by the Cache
class, which is located in <install_path>/jadu/JaduCache.php
. The following code demonstrates how to create an instance of the Cache
class and store the results of a database query in the cache.
require_once('JaduCache.php');
$params = [
'select' => ['name', 'value'],
'table' => 'my_table',
'where' => [
'id' => 1234
],
'orderBy' => [
['value', 'ASC']
]
];
$cache = new Cache('my_table', json_encode($params));
$result = null;
if ($cache->isEmpty()) {
// run the query against the database and store the data in $result
$cache->setData($result);
} else {
$result = $cache->data;
}
The following extracts from the code above demonstrates a number of features of the Cache
class.
$cache = new Cache('my_table', json_encode($params));
This creates a cache object for the my_table
namespace with the key of the data passed in as the second parameter. The namespace is used to group together cache items so that they can be deleted when data under the namespace is updated. The most common analogy of a namespace is the name of the database table that a query relates to.
If the database table name is used as the namespace, when a record in the table is added, updated or deleted, the items cached under the namespace are deleted so that future queries are based on the latest data.
The second parameter, the key of the data, is used to identify a particular piece of data under a namespace, such as a database query. This allows a specific piece of data to be identified as being in the cache and fetched if necessary.
if ($cache->isEmpty()) {
The isEmpty
function for a Cache
object returns true
or false
, depending on if the data for the requested key and namespace is available in the cache. This can then be used to determine whether to generate the data afresh or return the data from the cache.
$cache->setData($result);
The setData
function adds data to the cache under the namespace and key set in the constructor when instantiating the Cache
object. The data will remain in the cache until a request is made to delete the namespace under which the data is stored. Any serializable data type can be stored in the cache. The data need not be serialized before it is passed to the setData
method; serialization is handled by the Cache
class.
$result = $cache->data;
When instantiating a cache object, if data is available for the namespace and key provided in the constructor then it is retrieved and stored in the $data
variable in the Cache
class.
Deleting a Cache Namespace
To delete a cache namespace call the deleteTableCache function. This function resides in <install_path>/JaduCache.php
, however it is not part of the Cache class. To delete all data in the cache within the “users” namespace, call the function as follows:
require_once('JaduCache.php');
deleteTableCache('my_table');
Timed Based Caching
As an alternative to caching data indefinitely (until it is deleted) it is also possible to cache data for a specific period of time. This can be achieved using the TimedCache
class.
The main difference between the interface of the standard Cache
class and the TimedCache
class is when using the setData
function. After a TimedCache
instance has been created, a time (in the form of a unix timestamp) can be provided to the setData
function to determine when the cache will expire, for example:
require_once('JaduCache.php');
$timedCache = new TimedCache('namespace', 'timer');
$timedCache->setData('fred', time() + 120);
The preceding code would cache the value ”fred” under the “namespace” namespace for the key “timer” for 120 seconds. If the same cache object is created after 120 seconds the cache would be classed as empty, i.e. calls to the isEmpty
function would return false
.
Clearing the Cache
Any Jadu files that update database table records should clear the caches of any tables that are updated. In this way the Jadu Central cache becomes self-regulating. Should a file or database table be updated manually, i.e. not through using a Jadu Central user interface, then it will be necessary to clear the cache of the respective table. This can be done by manually deleting the directory with the name associated with the database table from the file system. Jadu also provide a user interface for clearing table caches.