tags:

views:

45

answers:

1

Hi all,

I am thinking of integrating some caching logic in my app.

Mainly, it will cache objects and objects lists to APC. I will implement a way for them to be automatically invalidated, once the object is updated/removed.

However, what about atomicity? How can I make sure that operations are atomic?

Thanks

A: 

Well, if you're talking about a single operation, it will be atomic (based upon how APC works). Either it will all be written, or none of it will...

If you're talking about multiple operations (As in updating every place an object is referenced), then there's nothing built in to prevent a race condition. Instead, what you'll need to do is implement some sort of locking to prevent other processes from trying to update that data.

One way you can do this is to "lock" each cached item by writing a special lock "cached" item to a known id before starting the operation (think row level locking in databases).

So, assuming an array of affected cache ids:

function getLocks($cacheIds) {
    $locked = array();
    foreach ($cacheIds as $cacheId) {
        if (apc_exists($cacheId . '_locked')) {
            //Another process has this id locked, clear all locks and return
            foreach ($locked as $id) apc_delete($id . '_locked');
            return false;
        } else {
            //Use a short TTL to prevent issues if this process dies
            apc_store($cacheId . '_locked', 60);
            $locked[] = $cacheId;
        }
    }
    return true;
}

function releaseLocks($cacheIds) {
    foreach ($cacheIds as $cacheId) {
        apc_delete($cacheId . '_locked');
    }
}

So, then you can simply call:

if (getLocks($cacheIds)) {
    //Do your operation here
    releaseLocks($cacheIds);
}

Now, beware that this doesn't prevent the tiny probability of two processes checking for the same key at the same time (and hence both returning false for apc_exists, yet overwriting each other). If this is a big problem, then you should read up on double-checked locking

ircmaxell