The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Memcached::Client - All-singing, all-dancing Perl client for Memcached

VERSION

version 2.01

SYNOPSIS

  use Memcached::Client;
  my $client = Memcached::Client->new ({servers => ['127.0.0.1:11211']});

  # Synchronous interface
  my $value = $client->get ($key);

  # Asynchronous-ish interface (using your own condvar)
  use AnyEvent;
  my $cv = AnyEvent->cv;
  $client->get ($key, $cv);
  my $value = $cv->recv;

  # Asynchronous (AnyEvent) interface (using callback)
  use AnyEvent;
  $client->get ($key, sub {
    my ($value) = @_;
    warn "got $value for $key";
  });

  # You have to have an event loop running.
  my $loop = AnyEvent->cv;
  $loop->recv;

  # Done
  $client->disconnect();

DESCRIPTION

Memcached::Client attempts to be a versatile Perl client for the memcached protocol.

It is built to be usable in a synchronous style by most Perl code, while also being capable of being used as an entirely asynchronous library running under AnyEvent.

In theory, being based on AnyEvent means that it can be integrated in asynchrous programs running under EV, Event, POE, Glib, IO::Async, etc., though it has only really been tested using AnyEvent's pure-Perl and EV back-ends.

It allows for pluggable implementations of hashing, protcol, serialization and compression---it currently implements the traditional Cache::Memcached hashing, both text and binary protocols, serialization using Storable or JSON, and compression using gzip.

METHODS

new

new takes a hash or a hashref containing any or all of the following parameters, to define various aspects of the behavior of the client.

parameters

compress_threshold => 10_000

Don't consider compressing items whose length is smaller than this number.

compressor => Gzip

You may provide the name of the class to be instantiated by Memcached::Client to handle compressing data for the servers.

If the $classname is prefixed by a +, it will be used verbatim. If it is not prefixed by a +, we will look for the name under Memcached::Client::Compressor.

compressor defaults to Gzip, so a protocol object of the Memcached::Client::Compressor::Gzip type will be created by default. This is intended to be compatible with the behavior of Cache::Memcached.

namespace => ""

This string will be used to prefix all keys stored or retrieved by this client.

hash_namespace => 1

If hash_namespace is true, any namespace prefix will be added to the key before hashing. If it is false, any namespace prefix will be added to the key after hashing.

no_rehash => 1

This parameter is only made available for compatiblity with Cache::Memcached, and is ignored. Memcached::Client will never rehash.

preprocessor => undef

This allows you to set a preprocessor routine to normalize all keys before they're sent to the server. Expects a coderef that will transform its first argument and then return it. The identity preprocessor would be:

 sub {
     return $_[0];
 }

This can be useful for mapping keys to a consistent case or encoding them as to allow spaces in keys or the like.

procotol => Text

You may provide the name of the class to be instantiated by Memcached::Client to handle encoding details.

If the $classname is prefixed by a +, it will be used verbatim. If it is not prefixed by a +, we will look for the name under Memcached::Client::Protocol.

protocol defaults to Text, so a protocol object of the Memcached::Client::Protocol::Text type will be created by default. This is intended to be compatible with the behavior of Cache::Memcached

readonly => 0

This parameter is only made available for compatiblity with Cache::Memcached, and is, for the moment, ignored. Memcached::Client does not currently have a readonly mode.

selector => Traditional

You may provide the name of the class to be instantiated by Memcached::Client to handle mapping keys to servers.

If the $classname is prefixed by a +, it will be used verbatim. If it is not prefixed by a +, we will look for the name under Memcached::Client::Selector.

selector defaults to Traditional, so a protocol object of the Memcached::Client::Selector::Traditional type will be created by default. This is intended to be compatible with the behavior of Cache::Memcached

serializer => Storable

You may provide the name of theclass to be instantiated by Memcached::Client to handle serializing data for the servers.

If the $classname is prefixed by a +, it will be used verbatim. If it is not prefixed by a +, we will look for the name under Memcached::Client::Serializer.

serializer defaults to Storable, so a protocol object of the Memcached::Client::Serializer::Storable type will be created by default. This is intended to be compatible with the behavior of Cache::Memcached.

servers => \@servers

A reference to an array of servers to use.

Each item can either be a plain string in the form hostname:port, or an array reference of the form ['hostname:port' => weight]. In the absence of a weight specification, it is assumed to be 1.

log

Log with an appropriate prefix.

compress_threshold

This routine returns the current compress_threshold, and sets it to the new value if it's handed one.

namespace

This routine returns the current namespace, and sets it to the new value if it's handed one.

hash_namespace

Whether to prepend the namespace to the key before hashing, or after

This routine returns the current setting, and sets it to the new value if it's handed one.

set_preprocessor

Sets a routine to preprocess keys before they are transmitted.

If you want to do some transformation to all keys before they hit the wire, give this a subroutine reference and it will be run across all keys.

set_servers()

Change the list of servers to the listref handed to the function.

connect()

Immediately initate connections to all servers.

While connections are implicitly made upon first need, and thus are invisible to the user, it is sometimes helpful to go ahead and start connections to all servers at once. Calling connect() will do this.

disconnect()

Immediately disconnect from all handles and shutdown everything.

While connections are implicitly made upon first need, and thus are invisible to the user, there are circumstances where it can be important to call disconnect() explicitly.

add

[$rc = ] add ($key, $value[, $exptime, $cb->($rc) || $cv])

If the specified key does not already exist in the cache, it will be set to the specified value. If an expiration is included, it will determine the lifetime of the object on the server.

If the add succeeds, 1 will be returned, if it fails, 0 will be returned.

add_multi

[$rc = ] add_multi (@([$key, $value, $exptime]), [$cb->($rc) || $cv])

Given an array of [key, value, $exptime] tuples, iterate over them and if the specified key does not already exist in the cache, it will be set to the specified value. If an expiration is included, it will determine the lifetime of the object on the server.

Returns a hashref of {key, boolean} pairs, where 1 means the add succeeded, 0 means it failed.

append

[$rc = ] append ($key, $value[, $cb->($rc) || $cv])

If the specified key already exists in the cache, it will have the specified content appended to it.

If the append succeeds, 1 will be returned, if it fails, 0 will be returned.

append_multi

[$rc = ] append_multi (@([$key, $value]), [$cb->($rc) || $cv])

Given an array of [key, value] tuples, iterate over them and if the specified key already exists in the cache, it will have the the specified value appended to it.

Returns a hashref of {key, boolean} pairs, where 1 means the add succeeded, 0 means it failed.

decr

[$value = ] decr ($key, [$delta (= 1), $initial, $cb->($value) || $cv])

If the specified key already exists in the cache, it will be decremented by the specified delta value, or 1 if no delta is specified.

If the value does not exist in the cache, and an initial value is supplied, the key will be set to that value.

If the decr succeeds, the resulting value will be returned, otherwise undef will be the result.

decr_multi

[$value = ] decr_multi (@($key, [$delta (= 1), $initial]), $cb->($value) || $cv])

Given an array of either keys, [key, delta] tuples, or [key, delta, initial] tuples, iterate over them and if the specified key already exists in the cache, it will be decremented by the specified delta, or 1 if no delta is specified. If the value does not exist in the cache, and an initial value is supplied, the key will be set to that value.

Returns a hashref of {key, value} pairs, giving the new values of each key.

delete

[$rc = ] delete ($key, [$cb->($rc) || $cv])

If the specified key exists in the cache, it will be deleted.

If the delete succeeds, 1 will be returned, otherwise 0 will be the result.

delete_multi

[\%keys = ] delete_multi (@keys, [$cb->($rc) || $cv])

For each key specified, if the specified key exists in the cache, it will be deleted.

If the delete succeeds, 1 will be returned, otherwise 0 will be the result.

flush_all

[\%servers = ] flush_all ([$cb->(\%servers) || $cv])

Clears the keys on each memcached server.

Returns a hashref indicating which servers the flush succeeded on.

get

[$value = ] get ($key, [$cb->($value) || $cv])

Retrieves the specified key from the cache, otherwise returning undef.

get_multi

[\%values = ] get_multi (@values, [$cb->(\%values) || $cv])

Retrieves the specified keys from the cache, returning a hashref of key => value pairs.

incr

[$value = ] incr ($key, [$delta (= 1), $initial, $cb->($value) || $cv])

If the specified key already exists in the cache, it will be incremented by the specified delta value, or 1 if no delta is specified.

If the value does not exist in the cache, and an initial value is supplied, the key will be set to that value.

If the incr succeeds, the resulting value will be returned, otherwise undef will be the result.

incr_multi

[$value = ] incr_multi (\@($key, [$delta (= 1), $initial]), $cb->($value) || $cv])

Given an array of either keys, [key, delta] tuples, or [key, delta, initial] tuples, iterate over them and if the specified key already exists in the cache, it will be incremented by the specified delta, or 1 if no delta is specified. If the value does not exist in the cache, and an initial value is supplied, the key will be set to that value.

Returns a hashref of {key, value} pairs, giving the new values of each key.

prepend($key, $value, $cb->($rc));

[$rc = ] append ($key, $value[, $cb->($rc) || $cv])

If the specified key already exists in the cache, it will have the specified content prepended to it.

If the prepend succeeds, 1 will be returned, if it fails, 0 will be returned.

prepend_multi

[$rc = ] prepend_multi (@([$key, $value]), [$cb->($rc) || $cv])

Given an array of [key, value] tuples, iterate over them and if the specified key already exists in the cache, it will have the the specified value prepended to it.

Returns a hashref of {key, boolean} pairs, where 1 means the add succeeded, 0 means it failed.

remove

Alias to delete

replace

[$rc = ] replace ($key, $value[, $exptime, $cb->($rc) || $cv])

If the specified key already exists in the cache, it will be replaced by the specified value. If it doesn't already exist, nothing will happen. If an expiration is included, it will determine the lifetime of the object on the server.

If the replace succeeds, 1 will be returned, if it fails, 0 will be returned.

replace_multi

[$rc = ] replace_multi (@([$key, $value, $exptime]), [$cb->($rc) || $cv])

Given an array of [key, value, $exptime] tuples, iterate over them and if the specified key already exists in the cache, it will be set to the specified value. If an expiration is included, it will determine the lifetime of the object on the server.

Returns a hashref of {key, boolean} pairs, where 1 means the replace succeeded, 0 means it failed.

set()

[$rc = ] set ($key, $value[, $exptime, $cb->($rc) || $cv])

Set the specified key to the specified value. If an expiration is included, it will determine the lifetime of the object on the server.

If the set succeeds, 1 will be returned, if it fails, 0 will be returned.

set_multi

[$rc = ] set_multi (@([$key, $value, $exptime]), [$cb->($rc) || $cv])

Given an array of [key, value, $exptime] tuples, iterate over them and set the specified key to the specified value. If an expiration is included, it will determine the lifetime of the object on the server.

Returns a hashref of {key, boolean} pairs, where 1 means the set succeeded, 0 means it failed.

stats ()

[\%stats = ] stats ([$name, $cb->(\%stats) || $cv])

Retrieves stats from all memcached servers.

Returns a hashref of hashrefs with the named stats.

version()

[\%versions = ] stats ([$cb->(\%versions) || $cv])

Retrieves the version number from all memcached servers.

Returns a hashref of server => version pairs.

METHODS (INTERACTION)

All methods are intended to be called in either a synchronous or asynchronous fashion.

A method is considered to have been called in a synchronous fashion if it is does not have a callback (or AnyEvent::CondVar) as its last parameter. Because of the way the synchronous mode is implemented, it must not be used with programs that will call an event loop on their own (often by calling ->recv on a condvar)---you will likely get an error:

        AnyEvent::CondVar: recursive blocking wait detected

A method is considered to have been called in an asynchronous fashion if it is called with a callback as its last parameter. If you make a call in asynchronous mode, your program is responsible for making sure that an event loop is run...otherwise your program will probably just exit.

When, in discussing the methods below, the documentation says a value will be returned, it means that in synchronous mode, the result will be returned from the function, or in asynchronous mode, the result will be passed to the callback when it is invoked.

RATIONALE

Like the world needs another Memcached client for Perl. Well, I hope this one is worth inflicting on the world.

First there was Cache::Memcached, the original implementation.

Then there was Cache::Memcached::Managed, which was a layer on top of Cache::Memcached providing additional capablities. Then people tried to do it in XS, spawning Cache::Memcached::XS and then Cache::Memcached::Fast and finally Memcached::libmemcached, based on the libmemcached C-library. Then people tried to do it asynchronously, spawning AnyEvent::Memcached and Cache::Memcached::AnyEvent. There are probably some I missed.

I have used all of them except for Cache::Memcached::Managed (because I didn't need its additional capabilities) and Cache::Memcached::XS, which never seems to have really gotten off the ground, and Memcached::libmemcached which went through long periods of stagnation. In fact, I've often worked with more than one at a time, because my day job has both synchronous and asynchronous memcached clients.

Diasuke Maki created the basics of a nice asynchronous implementation of the memcached protocol as Cache::Memcached::AnyEvent, and I contributed some fixes to it, but it became clear to me that our attitudes diverged on some things, and decided to fork the project (for at its base I thought was some excellent code) to produce a client that could support goals.

My intention with Memcached::Client is to create a reliable, well-tested, well-documented, richly featured and fast Memcached client library that can be used idiomatically in both synchronous and asynchronous code, and should be configurabe to interoperate with other clients.

I owe a great debt of gratitude to Diasuke Maki, as I used his Cache::Memcached::AnyEvent as the basis for this implementation, though the code has basically been rewritten from the groune up---which is to say, all bugs are mine.

AUTHOR

Michael Alan Dorman <mdorman@ironicdesign.com>

COPYRIGHT AND LICENSE

This software is copyright (c) 2010 by Michael Alan Dorman.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.