Cache (Basic) Part 1

January 22, 2010 · By Michael Offner · 9 Comments

Since version 3.1.2 Railo supports the possibility of using a cache. This blog entry will go into the details of this feature. The blog is divided into 3 parts, the first part will deal with the base functionality, the second part show how the cache is used in backend and the last part takes care of specialties when using the cache and shows a reference.

What is the Cache good for?

This feature allows storing data, that previously had to be written to a database, a variable or to the file system to now be stored in a cache. Here are some advantages:
  • The access is much faster than to the file system
  • You can determine the lifetime of the stored elements
  • The data can (but need not) be persistent, ie they survive a restart
  • The memory used for storing is not as intense as when stored in a variable, since caches usually have an intelligent paging
  • Data can be easily distributed across multiple systems (peer-2-peer) or can be centrally maintained (for several servers client-server)

How to use the cache?

For the caching support Railo provides a set of functions and one tag. Furthermore, the cache also serves as a backend cache for various systems. Note that you can define more than one cache per web context and server context.

Create a cache

In the Railo Admin, you can create and manage cache instances. Railo allows you to create as many instances as you need. The concept is similar to the creation of Datasource connection under "Services / Datasource". In order to create a new cache go to the Railo admin and select the menu item "Services / Cache (Beta)". You will see something like this:

At the moment it displays a statement as well that this is a beta version of the cache implementation. Out of the box you only have the possibility to create a "RamCache. This is the default cache implementation for Railo. Let's create a "Cache connection" by giving it a name (note: without spaces and special characters) and clicking on the "create" button. Let's call it "mycache". Then you can use it immediately for examples further below.

After we clicked the button we see the details of the cache. Here it is possible to set other configuration features which totally depends on the used cache type. The RamCache does not have additional options. In addition you can specify whether this cache should be the default cache for a specific service (more on this later). We simply choose "Object" and press "submit".


now we return to the list of the defined caches and we can see that the new cache is listed here, we can also create a default cache for various purposes. But as mentioned we'll get to that later. We will now leave the admin and test the cache.

Direct invocation (Object Cache)

We have successfully created a default cache declared it as the "Default Object" cache. Since the cache implementation is still in the beta phase, the documentation of the tags and functions are not yet in the wiki. But you will find a simple one in the Railo admin under "Documentation".

Let us have a look at a simple example: <cfset cachePut('hello','Hello World')>
<cfoutput> #cacheGet( 'hello')#</ cfoutput>
Output:
Hello World

On the first line the element "Hello World" with the key "hello" is put into the cache and on the second line Railo reads it back from the cache.

Now we extend the example a little <cfset cachePut('hello','Hello World',createTimespan(0,0,0,10),createTimespan(0,0,0,10),'mycache')>
<cfoutput> #cacheGet( 'hello', true, 'myCache')#</ cfoutput>
Output:
Hello World

Okay, what has changed, on line 1 is that the function cachePut now uses more arguments. The third and fourth argument define the lifespan of the element. The third one defines how long the element will remain in the cache and the fourth one defines after which period of time the element will be deleted from the cache if it is not used. The fifth argument defines the name of a specific cache to be used if you do not want to use the default object cache.
The function on line two has received two further arguments. The second defines whether the function will throw an error if the element does not exist and the third one defines the cache name to be used.

This is really the whole deal. The only things now to be added are the tags and functions to manipulate the cache. Let's look at some of the function that allow manipulating the cache: <cfset cachePut('terra','Hello Terra')>
<cfset cachePut('mars','Hello Mars')>
<cfset cachePut('pluto','Hello Pluto')>
<cfset cachePut('2003UB313','Hello 2003UB313')>
<cfdump var="#cacheCount()#">
<cfdump var="#cacheGetAllIds()#">
<cfdump var="#cacheGetAllIds('*r*')#">
<cfdump var="#cacheGetAll('*r*')#">
<cfdump var="#cacheKeyExists("terra")#">
<cfset cacheDelete("terra")>
<cfset cacheRemove("mars,pluto")>
<cfset cacheClear()>
The functions will be discussed individually later in detail, here is just a small overview of them: The first 4 elements are written into the default object cache with the help of the function "CachePut". Then we output the number of elements in the cache by using the function "cacheCount". The following function "CacheGetAllIds" returns all ids of the cache in an array. The second call to the function "CacheGetAllIds" contains a filter argument ( "*r*") so that only the ids are returned which match the filter. The next function call "CacheGetAll" differs from the Function CacheGetAllIds only in the fact that instead of an array the function returns a struct with all keys and their appropriate values. Next, the function "CacheKeyExists" is used, which checks if an element exists in the cache or not. After that the functions "CacheDelete" and "CacheRemove" follow. Both functions allow deleting elements from the cache. The difference of these functions is that the function "CacheDelete" takes only a single id as an argument whereas "CacheRemove" can take a list. The reason for introducing the function "CacheDelete" is that with the function "CacheRemove" it is not possible to delete an item, which contains a "," in the key.
Example: <cfset cachePut('hello,world','Hello World')>
<cfset cacheRemove("hello,world")>
<cfset cacheDelete("hello,world")>
In this example, CacheRemove attempts to delete two keys named "hello" and "world" but not the key "hello,world".
"CacheDelete" however can delete the element.
And finally we have the function "CacheClear", this function remove all Elememts from cache, like "CacheGetAllIds" this functon supports a optional argument filter.
Note also that each function takes the cache name as the last argument

Now we have looked at the basic functionality of the cache. In the next part we'll look at what other things the cache can be used for and how to install other cache types.

Tags: cache · CFML · Configuration · Features · HowTo · New release · Railo 3.1.2

9 responses so far ↓

  • 1 Peter Z // Jan 22, 2010 at 7:42 PM

    This is a great post, I'm looking forward to the next two parts.

    Are there any plans to implement cache dependancies? It appears that when I rewrite my cache component to use Railo's caches I'll still have to manage these dependencies in a separate object. It would be so nice though if this was baked in.

    A sixth option added to cachePut that allows you to pass in an array of cache ids that the object would be dependent on would freaking rock.
  • 2 Gert Franz // Jan 22, 2010 at 7:59 PM

    Peter,

    I guess this is something that we should discuss in the mailing list and something that needs to go through the advisory committee as well.

    For now we should leave it like this and see what the advisory committee decides. Maybe Sean would like to comment it as well.

    Gert Franz
    Railo Technologies
  • 3 Sean Corfield // Jan 22, 2010 at 8:53 PM

    The committee's position at the moment is all caching functions are vendor-specific.
  • 4 Michael Offner // Jan 22, 2010 at 10:23 PM

    pherhaps some kind of listeners would make sense
    a cfc that has to implement function that follows a certain pattern, similar to the application.cfc
  • 5 Jeremy Bruck // Jan 24, 2010 at 8:54 PM

    Thanks for the great blog post on the caching! I am creating a new CFC for it and am looking forward to using it in more places in production!

    I am looking forward to the next posts on this as well -- it is a place that more sites can take advantage of with a serious effect on the load times.

    Jeremy
  • 6 Sebastiaan // Feb 14, 2010 at 9:33 PM

    Customtags on Railo are a pain in the butt - everytime I make a change in the Customtag I have to restart Railo in order to see the change. This is absurd - sure there must be a better way...

    Please tell me how! I'm running Railo on Jetty for development purposes (the version with a start/stop .bat file).
  • 7 Gert Franz // Feb 15, 2010 at 6:29 AM

    Sebasitaan,

    you can check whether the custom tag directory is marked as trusted or not. If it is, just uncheck it in your local environment. You can define per mapping or custom tag directory whether files should be trusted (cached) or not. Just like the trusted cache in ACF.
    If on the other hand you are using CFC based custom tags that are placed in the internal library/tag folders, you indeed have to restart the engine to see the effects. But there are other possibilities you have when developing them. Just develop them as a regular custom tag (using CF_) and then when you're done and they work you can copy them into these directories. Then you can use them as regular internal tags.

    Hope that helps...

    Gert Franz
    Railo Technologies GmbH
  • 8 Sebastiaan // Feb 15, 2010 at 11:28 AM

    Gert, thanx, that did it, never really understood what that trusted was for (not even after having read the livedocs - wiki). Maybe cached would be a better word for it ;-) But it works now, thank you. In the process I found the Google Groups for Railo and there was a similar question regarding customtags not showing changes. Your answer there was &quot;trusted&quot; as well. So got it fixed yesterday, but good that Google now has one more website page to index (this one) for people facing the same question.

    Is the Wiki the only real place where one can get information on Railo? The CF-community is rather good at ACF-stuff, but still need to embrace Railo I think blogwise. I for one am sold, a free engine that does most of what ACF does and a promise that it will continue to be developed in close proximity and cooperation with the CF-standards working group. This can only get better ;-)
  • 9 Jay // Aug 27, 2012 at 8:18 AM

    In case others run acsors the same problem, I have figured out what the deal is with making this work for RTMP (streaming) URLs. What you need to do is feed only the last part of the url, everything after "cloudfront.net/cfx/st/" into the function. This is not the case with HTTP (works to feed the function the entire URL).So if your URL is:rtmp://s17f59fd6dzkkt.cloudfront.net/cfx/st/folder/filename.mp4You would call the function like this to make a signed URL:cf.signUrlWithTimeout("folder/filename.mp4 ,9000)

Leave a Comment

Leave this field empty: