Use cases for Bullet Cache are numerous - on the one hand it is a very convenient (and fast) memory cache server, but on the other it implements some advanced features which make it applicable in surprisingly many different scenarios. This post starts a series of descriptions on some of the real-world use cases which fit Bullet Cache suprisingly nicely, and some of these are already described in the Bullet Cache User's manual.
Previously in the series of posts about Bullet Cache:
- Installation and testing
- The C API tutorial
- RC1 announcement
- Lessons leared in its development, 1.0 announcement
At its core, Bullet Cache is a standard memory cache server, not unlike Memcached which has inspired its development. However, the reason why it was developed in its today's form was because Memcached is somewhat inflexible. As a pure key-value database, it requires a relatively large amount of book-keeping on the application side to keep track of what the different cached records are and where they belong. In addition to that, real-world tasks often require the manipulation of multiple records at the same time, which Memcached can only do by having the application specify a list of records. Bullet Cache improves on that by introducing a flexible metadata mechanism called "record tags." These tags are numerical values (integers) which may be used in complex record queries.
Bulk data operations using record tags
An application can add records to the Bullet Cache server with associated record tags which make it easy to operate on classes or groups of records with some kind of meaningful relation. This makes it trivially easy to implement operations such as "retrieve all cache records beloning to a web page," "delete/expire all cache records belonging to a single forum thread," or "delete/expire all cache records belonging to a single user."
The structure of record tags is the familiar key-value pair but with the limitation that both the key and the value are signed integers (as this ensures the fastest possible operations and prevents the misuse of record tags for actual data storage). As a practical example, if an Web application needs to cache data records for a Web page, of which some of them intrinsically belong to a page, some of them belong to a forum on a page, and some of the ones in the forum are created by certain users, it could do it this way:
- Make sure that each cached entity has a unique integer identifier within its class; the record tags are pairs of (tag_key, entity_id)
- Choose three different tag key numbers: 1 for "record belongs to a page", 2 for "record belongs to a forum", 3 for "record belongs to a user"
- Tag the cache records intrisically belonging to a page (for example, they may be a part of the page's design) with (tag_key=1, tagvalue=page_id)
- Tag the cache records belonging to the forum on that page with both (1,page_id) and (2,forum_id)
- Tag the cache records belonging to the user with (1,page_id), (2,forum_id) and (3,user_id)
For example, if page_id=42, forum_id=99 and user_id=77, and there are three records, they might carry the following tags:
record #1: (1,42)
record #2: (1,42), (2,99)
record #3: (1,42), (2,99), (3,77)
This makes it possible to issue the following operations / queries to the cache server (in addition to the "normal" operations on the record keys):
- Retrieve all cached records belonging to page 42 - useful for building and outputting the entire Web page by issuing only a single cache server query
- Expire all cached records belonging to forum 99 - useful for refreshing the cache for an entire forum
- Remove all cached records belonging to user 77 - useful either for refreshing the cache for a single user (e.g. when the user's profile information changes) or when deleting / banning the user from a forum.
Some of these operations could have been done by keeping entire data sets (for a single page, a single forum, etc.) in single cached records, but this is highly inefficient. The use of record tags makes it easy to access records which are a part of larger structure (e.g. single posts in a specific forum) while allowing very efficient bulk operations.
This principle can be obviously extended to allow much more complex operations, such as sharing data between different applications.
Vote on the Bullet Cache's future development!
There are several directions in which Bullet Cache could take off in the future. Here is your chance to vote for a favourite feature!