cfmemcached v1.1 released today
I released a new version of cfmemcached today. I recently went through and made some changes that would make it easier to deploy in different situations. I also made some changes to the new memcached client to make it easier to use and to avoid some timeout issues.
I found a problem that when you use a get() command, the java client will continue to make requests to find the memcached server and will hold the coldfusion connection open waiting for a response from the memcached server. In the case of failure to reach the memcached server, this could mean that the connection would stay open indefinately and would start blocking processes on the webserver. In general i see that as a problem, while it's nice that it will wait around and pick up as soon as the memcached server comes back up, it's also bad, because 1. generally when memcached comes back up, it will have lost the info anyway and will still need to reget from the database, 2. because if it just sits and waits for a response from the server, it will eventually bring down the web server because of too many open connections and 3. it causes a bad user experience (because the user will just see the web page trying to load indefinately, until the memcached server comes back up).
So, accordingly, I put a timeout in the coldfusion client. There are a couple of ways that you can specify this timeout. you can set a clientwide timeout (a preset is now also hardcoded, just to make sure that it doesn't take down your server) Also, you can set the timeout to be longer or shorter depending on what you need.
To use the client, and set up the timeout, you can send the timeout in to the memcached_factory
memcached = server.memcached.getInstance();
memcached.set("somekey","a value for that key");
myval = memcached.get("somekey",200,"milliseconds");
// or you can use the client default by just doing a // a get as normal.
myval = memcached.get("somekey");
Pretty simple, but effective.
1. memcached is a shared datastore. if you store your queries, etc in the application scope, every system is maintaining it's own cache independently, with memcached, everything pulls from one repository. so if you have several coldfusion app servers in front of one database, you can pull your cache from one repository.
2. With large amounts of cache going on, you can run into situations where the garbage collection on the coldfusion jrun process very quickly runs into trouble with the main running processes, to the point where in massive storage situations, you can run into problems with coldfusion where it tips over and fails because of internal memory conflicts. I don't know what causes it to happen, but i've seen it happen. having a memcached instance in a separate java instance allows you to off load all of that garbage collection on to the separate instance (which has less need for the garbage collection).
Coldfusion needs to run the garbage collection frequently to clear up room because of generated cfc, old page information, that it needs to clean out of it's memory to make room for new memory sets. The less it has to deal with/ keep track of, the better it does.
3. if your app server dies and you have all of your caching in the application scope in coldfusion, you have to regen all of that cache because it's all stored in ram. with memcached, you have that running in a separate instance, which means that as long as your instance stays up, you have your cache. and the likelihood that your cache is going to remain in-tact is better, because you have less that you have to deal with.
what's even better is that you can spread memcached around on whatever servers you have that aren't using all of their ram, and you can run instances of memcached, wheever and however you'd like, thereby reducing how badly a catastrophic failure (or other kind of failure) will affect your site.
I'm not saying that in all instances memcached is going to be right for you or everyone iand that that in every case its the right way to go. if you don't have the need for a cluster or you aren't getting massive hits on your database that you need to offload into a different cache, or if you aren't trying to store massive quantities of info in a ram cache, then the amount of benefit you are going to get from memcached is going to be very diminished.
It looks like the keyExists() method is missing from the memcached.cfc. Can you verify this?
Also, what's the main difference between this memcached client and the other one that's on RIAForge? Overall, nice work!
so for example, you can do the follwoing
thisval = memcached.get("mykey") ;
if ( isSimpleVal(thisVal) and thisval eq "") {
/// need to refetch
} else {
// got a good val... take it an run with it.
}
For the second part of your question. There are two clients that are available for download here:
1. the new client - this is built on a new client, the one built by dustin sallings with is a great client and has more built-in optimizations around key retrieval, memcached failorver and also optimal storage. The other big thing is asyncronous connections which allow the client to set a var and not have to wait around to finish processing until the value has been completely set in the memcached client. very nice!
2. the old client - this is essentially the same client as can be found at memcached.riaforge.org. That was a great start. it can get you up and running with the basic functionality, only there are some problems with it, namely, the getMulti and getmultiarray functions don't work. I based the old client off of that memcached client and added in more deserialization for the getmuliti and getmultiArray functions, and added in some helper functions which i found were really nice. -remind me to blog about the helper functions :) they just make it a little easier to do caching, so that it can be a whole lot more like coldfusion's caching engine.
Anyway, hope that answers the question.
Few comments about memcached:
1) Facebook is a very heavy user of memcached. What's nice about it is that you don't necessarily have to store just queries in it. Basically if you have this big complex object graph (you friends, their preferences, your favorite feeds etc) you can store the entire object graph in memory and have it be available to all of the app servers in your farm (that's why they can return your profile page so quickly, they've already stored the entire object graph in memory)
2) Does this coldfusion memcached client support the storage of an entire object graph in memory? Are you aware of any limitations in doing this using this client?
There have been a couple of things that i have run into with the cache, they are wierd issues that i don't know what is causing the problem.
1. when storing objects they serialize just fine, and come back out just fine, however, if you have any inheritances with externally cached objects, ie an object stoered in the application or request scope, those linkages can cause some wierd problems where the name of the object gets changed and Causes a cfc not found exception. This is somethhing that i've been able to reproduce in my own system however, not by itself.
2. we've had a wierd issue where the serializing sometimes breaks when trying to serialize a large query object. I say wierd, because i can only replicate this on our linux systems and not on my own windows system. also, i've been able to store queries of as large as 200,000 rows, however, the query that causes problems only has about 2000 rows. definately wierd stuff. and stuff that i'm looking into.