redis-rs is a rust implementation of a Redis client library. It exposes a general purpose interface to Redis and also provides specific helpers for commonly used functionality.
The crate is called redis
and you can depend on it via cargo:
[dependencies.redis]
version = "*"
If you want to use the git version:
[dependencies.redis]
git = "https://github.com/redis-rs/redis-rs.git"
Basic Operation
redis-rs exposes two API levels: a low- and a high-level part. The high-level part does not expose all the functionality of redis and might take some liberties in how it speaks the protocol. The low-level part of the API allows you to express any request on the redis level. You can fluently switch between both API levels at any point.
Connection Handling
For connecting to redis you can use a client object which then can produce
actual connections. Connections and clients as well as results of
connections and clients are considered ConnectionLike
objects and
can be used anywhere a request is made.
The full canonical way to get a connection is to create a client and to ask for a connection from it:
extern crate redis;
Optional Features
There are a few features defined that can enable additional functionality if so desired. Some of them are turned on by default.
acl
: enables acl support (enabled by default)aio
: enables async IO support (enabled by default)geospatial
: enables geospatial support (enabled by default)script
: enables script support (enabled by default)r2d2
: enables r2d2 connection pool support (optional)ahash
: enables ahash map/set support & uses ahash internally (+7-10% performance) (optional)cluster
: enables redis cluster support (optional)tokio-comp
: enables support for tokio (optional)connection-manager
: enables support for automatic reconnection (optional)
Connection Parameters
redis-rs knows different ways to define where a connection should
go. The parameter to Client::open
needs to implement the
IntoConnectionInfo
trait of which there are three implementations:
- string slices in
redis://
URL format. - URL objects from the redis-url crate.
ConnectionInfo
objects.
The URL format is redis://[<username>][:<password>@]<hostname>[:port][/<db>]
If Unix socket support is available you can use a unix URL in this format:
redis+unix:///<path>[?db=<db>[&pass=<password>][&user=<username>]]
For compatibility with some other redis libraries, the "unix" scheme is also supported:
unix:///<path>[?db=<db>][&pass=<password>][&user=<username>]]
Executing Low-Level Commands
To execute low-level commands you can use the cmd
function which allows
you to build redis requests. Once you have configured a command object
to your liking you can send a query into any ConnectionLike
object:
Upon querying the return value is a result object. If you do not care
about the actual return value (other than that it is not a failure)
you can always type annotate it to the unit type ()
.
Note that commands with a sub-command (like "MEMORY USAGE", "ACL WHOAMI",
"LATENCY HISTORY", etc) must specify the sub-command as a separate arg
:
Executing High-Level Commands
The high-level interface is similar. For it to become available you
need to use the Commands
trait in which case all ConnectionLike
objects the library provides will also have high-level methods which
make working with the protocol easier:
extern crate redis;
use Commands;
Note that high-level commands are work in progress and many are still missing!
Type Conversions
Because redis inherently is mostly type-less and the protocol is not
exactly friendly to developers, this library provides flexible support
for casting values to the intended results. This is driven through the FromRedisValue
and ToRedisArgs
traits.
The arg
method of the command will accept a wide range of types through
the ToRedisArgs
trait and the query
method of a command can convert the
value to what you expect the function to return through the FromRedisValue
trait. This is quite flexible and allows vectors, tuples, hashsets, hashmaps
as well as optional values:
# use Commands;
# use ;
#
Iteration Protocol
In addition to sending a single query, iterators are also supported. When
used with regular bulk responses they don't give you much over querying and
converting into a vector (both use a vector internally) but they can also
be used with SCAN
like commands in which case iteration will send more
queries until the cursor is exhausted:
#
As you can see the cursor argument needs to be defined with cursor_arg
instead of arg
so that the library knows which argument needs updating
as the query is run for more items.
Pipelining
In addition to simple queries you can also send command pipelines. This
is provided through the pipe
function. It works very similar to sending
individual commands but you can send more than one in one go. This also
allows you to ignore individual results so that matching on the end result
is easier:
#
If you want the pipeline to be wrapped in a MULTI
/EXEC
block you can
easily do that by switching the pipeline into atomic
mode. From the
caller's point of view nothing changes, the pipeline itself will take
care of the rest for you:
#
You can also use high-level commands on pipelines:
#
Transactions
Transactions are available through atomic pipelines. In order to use
them in a more simple way you can use the transaction
function of a
connection:
#
For more information see the transaction
function.
PubSub
Pubsub is currently work in progress but provided through the PubSub
connection object. Due to the fact that Rust does not have support
for async IO in libnative yet, the API does not provide a way to
read messages with any form of timeout yet.
Example usage:
#