Using cas() command from PECL Memcached

Here a simple example on how using cas() command from PECL Memcached to update data that must be at all time up to date

In Memcached, series of commands are not atomic :

A series of commands is not atomic. If you issue a ‘get’ against an item, operate on the data, then wish to ‘set’ it back into memcached, you are not guaranteed to be the only process working on that value. In parallel, you could end up overwriting a value set by something else.

But PECL Memcached come with a useful function : cas()

The principle is :

  • Make a get() to get a key value and a cas token (checksum of the value that the get return)
  • Make some update on the value
  • Ask memcached to update the value with cas() method with the cas token as parameter, to let memcached see if the actual value of the key you want to update is the same as he give before or if another script has changed it

Here the code example, we update an index array, adding values in it when not present

With that little script, we are sure that :

  • If no index are present at start of our script but the index is created in another thread, we retrieve it before adding our value because we use the add() command (Memcached::RES_NOTSTORED)
  • If the index is modified by another script while we are working on it, we get the up to date version before trying to add our new data, thanks to the cas() method (Memcached::RES_DATA_EXISTS)

Remember to be careful with cas(), under heavy concurrent updates, the do … while() can easily take a lot of execution time, you must add a maximum try count break condition.

And remember to not check command success in a while loop with something like

Memcached::RES_SERVER_ERROR or anything like this and your script will loop forever

Leave a Reply