I've just uploaded the first Release Candidate version of Bullet Cache! It is basically feature complete and done, and I'm happy to say that it looks like I have a small number of users and also some feedback on the project - so keep it up :) At this point I'd like to shortly talk about what made me write Bullet Cache - which also leads to why it was done the way it is and what are its main strengths. For the impatient, these are flexibility in cached data expiry and performance, but read on for the details...
Previous posts in the Bullet Cache series:
I have been using memcached almost as soon as it appeared, and I can testify that the improvements it brought to the game were impressive. But that early version of memcached was single-threaded, ran a slow ASCII-based network protocol and had very little options for advanced data managament. As I was slow in writing Bullet Cache (hey, life got in the way), memcached gradually fixed all but the last quibble: it is still a pure key-value data store.
One thing in particular always irked me: the inability to delete data from the cache (i.e. "expire" it) by some criteria external to the usual "list of keys" approach. What matters in real-life application is the ability to e.g. expire all cached records belonging to a certain web page, or to a certain user, or whatever other group, without actually maintaining a list of keys which contain such information (because then you need to store this list somewhere...). This was my primary motivation, feature-wise, and Bullet Cache now contains very flexible bulk data management functionalities.
The key to this ability is that Bullet Cache records have simple metadata "tags" associated with them, and these tags can be used to perform simple data queries. By using record tags, loosely defined groups of records can be expired (or indeed retrieved) in a single efficient operation. This gives the application developers freedom to implement functions like: "fetch all cached data relevant to a single Web page" and "expire all cached data relevant to a single user." Since records can have an arbitrary number of tags assigned to them, complex behaviour can be implemented, for example by "tainting" certain composite records with tags representing user data or page data, and then expiring (or retrieving) in bulk all records having specific tags. See the User Guide for some more examples!
And of course, Bullet Cache is very fast, of which I'm especially proud of. There are no single global locks for reading or writing, and concurrency is extreme.
Try it! If the SourceForge download servers are busy, try again :D