Perl6 bindings on top of Eredis
Other
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
doc
eg
lib
logotype
t
xt
.gitignore
META6.json
NASA_Open_Source_Agreement_1.3 GSC-17829.pdf
README.md

README.md

Redis::Async - A high-performance client for Redis

This module includes bindings for the Eredis client library for Redis.

Eredis is a C client library built over Hiredis. It is lightweight, high performance, reentrant and thread-safe.

INSTALLATION

This module depends on the Eredis library, so it must be installed first. Then just use zef to install this package from the Perl 6 ecosystem:

zef install Redis::Async

Basic Usage

use Redis::Async;

my $r = Redis::Async.new("localhost:6379");

$r.set('foo', 'bar');

say $r.get('foo'); # bar

Notes

Case doesn't matter for commands $r.GET and $r.get are the same thing with a few exceptions:

  • hgetall returns a Hash

  • info returns a Hash

  • keys defaults to pattern '*' -- Caution, this can take a very long time if you have a lot of keys! For production, scan may be a better option.

  • subscribe and psubscribe should be lower case.

  • scan, sscan, hscan, and zscan should be lower case.

An Instant will be converted into epoch seconds.

$r.expireat('foo', now+5);  # same as $r.expire('foo', 5)

See redis.io for the complete list of commands. Note carefully the version of your Redis server and if you are using an older version, which commands are valid.

Timeouts

You can set the Redis timeout with $r.timeout($seconds). You can disable timeouts entirely with $r.timeout(0). This is highly recommended if you use blocking read requests -- instead specify a timeout with the command. Timeouts should probably also be disabled for publish/subscribe. You can also set timeout on creation:

my $r = Redis::Async.new('localhost:6379', timeout => 0);

Multiple Redis servers

You can configure multiple redundant (NOT clustered) Redis servers in several ways.

List multiple servers on creation:

my $r = Redis::Async.new('server1:6379', 'server2:6379');

Add additional servers:

$r.host-add('server3:6379');

Or list servers in a configuration file, one line per host:port and add the file, alone, or as an option to .new(host-file => 'my-hosts.conf')

$r.host-file('my-hosts.conf');

The first host provided becomes the "preferred" one. It will always reconnect to that one in case of a down/up event.

You can set the number of retries on failure with $r.retry($retries) (defaults to 1) after which the client will fall back to the next server. You can also set retries with an option to new:

my $r = Redis::Async.new('localhost:6379', retries => 2);

Associative usage

Redis::Async also does the Associative role:

$r<foo> = 'bar';

say $r<foo> if $r<foo>:exists;

$r<foo>:delete;

Binary data

Strings are encoded as utf8 by default, but you can also pass in Blobs of binary data. Some commands like RESTORE require this.

Strings are also decoded as utf8 by default, you can request binary values with the :bin flag. It is highly recommended for dump.

say $r.get('foo', :bin);  # Blob:0x<62 61 72>

my $x = $r.dump('foo', :bin);

$r<foo>:delete;

$r.restore('foo', 0, $x);

Async writing

If you use the :async option, the write calls will be queued and sent to the Redis server in the background and the call will return immediately. This can dramatically speed up multiple writes. You can wait for pending writes to complete with $r.write-wait.

for ^100 { $r.set("key:$_", $_, :async) }
say "Pending writes: $r.write-pending()";
$r.write-wait;

Pipeline reads

You can also issue multiple reads without waiting for the replies, then later read the replies. This will pipeline the requests more efficiently and speed up performance.

for ^100 { $r.get("key:$_", :pipeline) }

for ^100 { say $r.value }

SCANing

The SCAN commands have special lower case functions that return a Redis::Cursor object that has a .next method to get the next element.

my $cursor = $r.scan('key:*');

while $cursor.next -> $x {
    say "$x = $r{$x}";
}

The scan commands also just take the parameters themselves, not the 'MATCH' and 'COUNT' strings.

Publish/Subscribe

The subscribe and psubscribe commands return a Redis::PubSub object that can read messages with .message:

$r.timeout(0);
my $sub = $r.subscribe('foo');

while $sub.message -> @m {
    if @m[0] eq 'message' {
        say "Received message @m[2] on channel @m[1]";
    }
    last if @m[2] eq 'QUIT';
}

Multiple threads

You can use a single Redis::Async object to issue requests from multiple threads simultaneously. Internally each thread will get its own communication channel so the requests won't get mixed up. You can't, therefore issue a pipelined read request in one thread and the corresponding reply request in a different thread. You can set the maximum number of readers with max-readers:

$r.max-readers(50);

Max readers will default to 16, so if you want to access Redis from more threads than that, increase it. As a convenience for Rakudo users, if you set the RAKUDO_MAX_THREADS environment variable, max-readers will be set to that number. You can also specify the max-readers option to new():

$r = Redis::Async.new('localhost:6379', max-readers => 50);

Redis::Objects Perlish objects tied to Redis Objects

EXPERIMENTAL, not everything works yet

You can bind to a Redis List like this:

use Redis::Async;
use Redis::Objects;

my $redis = Redis::Async.new('localhost:6379');

my @list := Redis::List.new(:$redis, key => 'some-list-key');
@list.push(1,2,3);
say @list[1];        # 2
.say for @list;

push() acts more like append() in that it flattens arrays since you can't really store objects in Redis (though maybe in the future this will serialize objects for you...)

or a Redis Hash like this:

my %hash := Redis::Hash.new(:$redis, key => 'some-hash-key');
%hash<a> = 'something';
say %hash<a>;              # something
.say for %hash;            # pairs

say %hash.kv;
say %hash.keys;
say %hash.values;
say %hash.elems;

Transactions

TBD

Clusters

TBD

SEE ALSO

There is another Perl6 Redis module Redis that uses a Perl 6 implementation of the protocol so it doesn't depend on external libraries like this module. If you don't need the performance, it may be easier to use.

LICENSE

Redis, and the Redis logo are the trademarks of Salvatore Sanfilippo in the U.S. and other countries.

Eredis is written and maintained by Guillaume Fougnies and released under the BSD license.

This software is released under the NASA-1.3 license. See NASA Open Source Agreement

Copyright © 2017 United States Government as represented by the Administrator of the National Aeronautics and Space Administration. No copyright is claimed in the United States under Title 17, U.S.Code. All Other Rights Reserved.