Module Memcache

module Memcache: sig .. end
Memcache support for OCaml. Based on it's text protocol.

All text below is mainly revised protocol specification with some markups and simplifications.

Nearly all functions in this module use Lwt. Lwt is a library for cooperative threads in OCaml. It is using monadic style, which makes it really easy to use.
Author(s): 2010 Alexander Markov ([email protected])
See also

exception Failure of string
This is non-regular exception, which raised only when library can't understand server's behavior. It's reasonably to send a bug report when this exception raises.


Clients of memcached communicate with server through TCP connections. A given running memcached server listens on some (configurable) port; clients connect to that port, send commands to the server, read responses, and eventually close the connection.

type connection 
val open_connection : string -> int -> connection Lwt.t
val close_connection : connection -> unit Lwt.t


Data stored by memcached is identified with the help of a key. A key is a text string which should uniquely identify the data for clients that are interested in storing and retrieving it. Currently the length limit of a key is set at 250 characters (of course, normally clients wouldn't need to use such long keys); the key must not include control characters or whitespace.

Expiration times

Some commands involve a client sending some kind of expiration time (relative to an item or to an operation requested by the client) to the server. In all such cases, the actual value sent may either be Unix time (number of seconds since January 1, 1970, as a 32-bit value), or a number of seconds starting from current time. In the latter case, this number of seconds may not exceed 60*60*24*30 (number of seconds in 30 days); if the number sent by a client is larger than that, the server will consider it to be real Unix time value rather than an offset from current time.


type error =
| CLIENT_ERROR of string
| SERVER_ERROR of string
Each command sent by a client may be answered with an error from the server. These errors come in three types:

In the descriptions of individual commands below, these errors are not again specifically mentioned, but clients must allow for their possibility.
exception Error of error

Storage commands

Storage commands (there are six: set, add, replace, append prepend and cas) ask the server to store some data identified by a key. The client sends a command and a data block; after that the client expects response, which will indicate success or faulure.

type reply =
After sending the command and the data the client awaits the reply, which may be:

val set : connection ->
string ->
?flags:int -> ?exptime:int -> ?noreply:bool -> string -> reply Lwt.t
set means "store this data".
val add : connection ->
string ->
?flags:int -> ?exptime:int -> ?noreply:bool -> string -> reply Lwt.t
add means "store this data, but only if the server doesn't already hold data for this key".
val replace : connection ->
string ->
?flags:int -> ?exptime:int -> ?noreply:bool -> string -> reply Lwt.t
replace means "store this data, but only if the server does already hold data for this key".
val append : connection ->
string ->
?flags:int -> ?exptime:int -> ?noreply:bool -> string -> reply Lwt.t
append means "add this data to an existing key after existing data".
val prepend : connection ->
string ->
?flags:int -> ?exptime:int -> ?noreply:bool -> string -> reply Lwt.t
prepend means "add this data to an existing key before existing data".
val cas : connection ->
string ->
?flags:int ->
?exptime:int -> ?noreply:bool -> int64 -> string -> reply Lwt.t
cas is a check and set operation which means "store this data but only if no one else has updated since I last fetched it."

Retrieval command

Retrieval commands (there are four: get, getl, gets and getsl) ask the server to retrieve data corresponding to a set of keys (one or more keys in one request). The client sends a command, which includes all the requested keys; after that for each item the server finds it sends to the client one response with information about the item, and one data block with the item's data.
val get : connection -> string -> (string * (int * string)) option Lwt.t
get conn key returns Some (key, (flags, value) or None if the item with this key was not found.
val getl : connection -> string list -> (string * (int * string)) list Lwt.t
The same, but takes a list of keys and returns list of founded values.
val geth : connection -> string list -> (string, int * string) Hashtbl.t Lwt.t
The same, but returns hash table of founded values.
val gets : connection ->
string -> (string * ((int * int64) * string)) option Lwt.t
gets is similar to get but returns Some (key, ((flags, unique), value) if item was found.
val getsl : connection ->
string list -> (string * ((int * int64) * string)) list Lwt.t
The same, but takes a list of keys and returns list of founded values.
val getsh : connection ->
string list -> (string, (int * int64) * string) Hashtbl.t Lwt.t
The same, but returns hash table of founded values.


val delete : connection -> ?noreply:bool -> string -> bool Lwt.t
delete key allows for explicit deletion of items.

This function can return:

See the flush_all function below for immediate invalidation of all existing items.


val incr64 : connection -> string -> ?noreply:bool -> int64 -> int64 option Lwt.t
val decr64 : connection -> string -> ?noreply:bool -> int64 -> int64 option Lwt.t
Commands incr and decr are used to change data for some item in-place, incrementing or decrementing it. The data for the item is a 64-bit unsigned integer. If the current data value does not conform to such a representation, the incr/decr commands return an error (memcached <= 1.2.6 treated the bogus value as if it were 0, leading to confusing). Also, the item must already exist for incr/decr to work; these commands won't pretend that a non-existent key exists with value 0; instead, they will fail.

Example of usage: incr conn key value

The response will be one of:

Note that underflow in the "decr" command is caught: if a client tries to decrease the value below 0, the new value will be 0. Overflow in the "incr" command will wrap around the 64 bit mark.
val incr : connection ->
string -> ?noreply:bool -> string -> string option Lwt.t
val decr : connection ->
string -> ?noreply:bool -> string -> string option Lwt.t
The same, but brings and returns decimal representations of 64-bit unsigned integer. These functions are faster and more dangerous to use.


General-purpose statistics

Settings statistics

Item statistics

Item size statistics

Slab statistics

Other commands

val flush_all : ?delay:int -> connection -> unit Lwt.t
flush_all is a command with an optional numeric argument. It always succeeds, and the function returns (). Its effect is to invalidate all existing items immediately (by default) or after the expiration specified. After invalidation none of the items will be returned in response to a retrieval command (unless it's stored again under the same key after flush_all has invalidated the items). flush_all doesn't actually free all the memory taken up by existing items; that will happen gradually as new items are stored. The most precise definition of what flush_all does is the following: it causes all items whose update time is earlier than the time at which flush_all was set to be executed to be ignored for retrieval purposes.

The intent of flush_all with a delay, was that in a setting where you have a pool of memcached servers, and you need to flush all content, you have the option of not resetting all memcached servers at the same time (which could e.g. cause a spike in database load with all clients suddenly needing to recreate content that would otherwise have been found in the memcached daemon).

The delay option allows you to have them reset in e.g. 10 second intervals (by passing 0 to the first, 10 to the second, 20 to the third, etc. etc.).

val version : connection -> string Lwt.t
In response, the server sends the version string for the server.

UDP protocol