Advanced Caching Technique – Block Randomization


I’m currenlty working on a site where I want to improve performance of dynamic pages. One of the greatest techniques to do is to cache dynamic content and serve the generated output (HTML).

It’s not as easy as we all want it to be when you have all sorts of weird blocks on the page: User login area, random content, ..etc

As I had a very pleasent experience with eZ components last week, I decided to take a look at the components, but then i remembered it works on PHP5. This project is on PHP4, I had to look for an alternative and decided to use PEAR::Cache_Lite.


In the figure above we can see that we have 4 content blocks coming from tha database, let’s assume this is our homepage. And let’s also assume that we are trying to get random content, e.g. 3 random blogs, 3 random posts ..etc

An example would look something like this before caching

  1. $query = "SELECT title, username FROM blogs ORDER BY RAND() LIMIT 3";
  2. $result=mysql_query($query);
  4. while( $row = mysql_fetch_assoc($result) ){
  6. echo $row['title'];
  8. }

Caching: Take 1

We can easily cache this block using Cache_Lite output caching as follows:

  1. require_once 'Cache/Lite/Output.php';
  3. $options = array(
  4. 'cacheDir'     => '/tmp/site_cache/',
  5. 'lifeTime'    => 1000,
  6. );
  8. $cache = new Cache_Lite_Output($options);
  9. if (!($cache->start('blogs_block' ))) {
  10. // Cache missed... start caching this block
  12. $query = "SELECT title, username FROM blogs ORDER BY RAND() LIMIT 3";
  13. $result=mysql_query($query);
  15. while( $row = mysql_fetch_assoc($result) ){
  17. echo $row['title'];
  19. }
  21. }

Well, there’s a clear problem, after the first hit, the block will be cached, and anyone who vists the page during the lifetime of the cache will keep seeing the same block! This abuses the whole concept of serving random content. We need to figure out a solution…

Caching: Take 2

I came up with a very simple solution! I will make the content appear as random, but infact it is cached, just modify the line that starts the cache as follows:

  1. if (!($cache->start('blogs_block' . rand(1,10) ))) {

What this does is allow for caching of 10 blocks, this will do the trick, give the users 10 cached blocks. If we have 4 different content blocks and allow 10 random blocks each, we end up by having 10x10x10x10 =10000 different page combinations.

Caching: Take 3

While the solution above meets my needs, I need something a bit cleaner than having rand() everytime. The first solution I came up with was to write the following class that extends Cache_lite and allows for cache randomization. Download the Class.

Using the cache randomizer is very simple, here’s an example.

  1. require_once 'Cache/Lite/Output/Random.php';
  3. $options = array(
  4. ..........
  5. );
  7. $cache = new Cache_Lite_Output_Random($options);
  9. //Set the number of random blocks to be cached
  10. $cache->setRand( 10 );
  12. if (!($cache->start('blogs_block' ))) {
  13. // Cache missed... start caching this block
  15. $query = "SELECT title, username FROM blogs ORDER BY RAND() LIMIT 3";
  16. $result=mysql_query($query);
  18. while( $row = mysql_fetch_assoc($result) ){
  20. echo $row['title'];
  21. }
  23. }
  25. //to disable caching and go back to normal behaviour to keep using the same object
  26. $cache->clearRand();
  28. //to change the number of random blocks for another block
  29. $cache->setRand( 20 );


Random block caching is very useful when you want to acheive high performance, yet allow random content from a datasource (Database). If we had a page with 4 blocks, and allow 10 random blocks, we get (Theoritically) 10000 page combinations. Although we only have 40 cache blocks stored on the server.

Tags: , , , , , , , , , , ,

  • Pingback:

  • Ivo Jansch

    The Smarty template engine is able to handle dynamic blocks within static pages very well. I would recommend having a look at it.

  • Pingback: Web 2.0 Announcer

  • Danko –

    I’m looking for suggestions on how to cache blocks of queries in WordPress. Caching the whole page is easy. I only need to instantiate the Cache object on index.php and the job is done. But, caching blocks are more confusing for me to apply.

  • Webby Dev Rob

    That’s a very simple solution to a potentially hard issue. Good read!

    Another solution may be to set a lower cache lifetime for this particular block and go from there – there would then be no need to create 10 different cache files, only needing a single one. The latter would be particularly useful for high traffic sites.

  • Pingback: Replica Louis vuitton handbag