Using Redis in Fork to cache large amounts of data

Fork CMS is a loved tool for developers who create websites of any size. Even big e-commerce shops. That's exactly what we are doing at SIESQOAt Siesqo we have been using Fork CMS since 2001 for creating websites and webshops, each tailored on the client needs. For a specific case we needed to create an ecommerce website wherein a lot of data should be cached.

What is Redis?

As redis.io states: Redis is an open source (BSD licensed), in-memory data structure store, used as database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries. Redis has built-in replication, Lua scripting, LRU eviction, transactions and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.

Why did we use Redis in Fork CMS?

The situation

We had to create a webshop linked to external software, which is responsible for managing tens of thousands of products and categories. Unfortunately that external database was missing important tree-structure information about how the website should show categories and their products. So when the import of categories and products is done, a cronjob needs to run a CacheBuilder script. Which is actually a class that contains how the website tree structure should be builts. All products and categories need to be fetched from the database and then added into arrays for every "category-combination" filters.

Filesystem is a no-go in this situation

I used the default "cache.adapter" filesystem to save these arrays (in files). Working locally that was allright, but not über fast. Since the webshop is probably going to receive thousands of visitors. I wanted something faster... Using Redis would make it blazingly fast.

How did we integrate Redis in Fork CMS?

In the Fork CMS `/app/config/config.yml` file you can find the following.

cache.filesystem.adapter:
    class: League\Flysystem\Adapter\Local
    arguments:
        - %kernel.cache_dir%
cache.filesystem.filesystem:
    class: League\Flysystem\Filesystem
    arguments:
        - "@cache.filesystem.adapter"
cache.adapter:
    class: MatthiasMullie\Scrapbook\Adapters\Flysystem
    arguments:
        - "@cache.filesystem.filesystem"
cache.buffer:
    class: MatthiasMullie\Scrapbook\Buffered\BufferedStore
    arguments:
        - "@cache.adapter"
cache.pool:
    class: MatthiasMullie\Scrapbook\Psr6\Pool
    arguments:
        - "@cache.buffer" 

At first we converted the above to be using Redis, but this gave us some issues in the import script.

Thats why we decided to add some extra config rules for redis + cache builder. In the Fork CMS /app/config/config.yml file we added the following.

# Caching using Redis Adapter
products_cache.redis.adapter:
    class: Redis
    calls:
        - [connect, ['%redis.server%', '%redis.port%']]
        - [auth, ['%redis.password%']]
        - [select, ['%redis.database_index%']]
products_cache.adapter:
    class: MatthiasMullie\Scrapbook\Adapters\Redis
    arguments:
        - "@products_cache.redis.adapter"
products_cache.buffer:
    class: MatthiasMullie\Scrapbook\Buffered\BufferedStore
    arguments:
        - "@products_cache.adapter"
products_cache.pool:
    class: MatthiasMullie\Scrapbook\Psr6\Pool
    arguments:
        - "@products_cache.buffer" 

In the Fork CMS /app/config/parameters.yml file we added the following.

redis.server:           127.0.0.1
redis.port:             6379
redis.password:             # This is by default null
redis.database_index:   0   # This is by default 0, I've used 1 for my staging environment

The next thing was to install Redis locally, so I could start testing things. Here is how I installed Redis locally + MAMP On the server, my hosting provider activated Redis and just gave me the redis.server/port and password.

Once you have installed Redis, the website will fly like never before.

You can ask questions below or follow me on GitHub or Twitter (@desloovere_j).