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.