Expand description
redis-rs is a Rust implementation of a client library for Redis. It exposesa general purpose interface to Redis and also provides specific helpers forcommonly used functionality.
The crate is calledredis
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 andmight take some liberties in how it speaks the protocol. The low-levelpart of the API allows you to express any request on the redis level.You can fluently switch between both API levels at any point.
§TLS / SSL
The user can enable TLS support using either RusTLS or native support (usually OpenSSL),using thetls-rustls
ortls-native-tls
features respectively. In order to enable TLSfor async usage, the user must enable matching features for their runtime - eithertokio-native-tls-comp
,tokio-rustls-comp
,async-std-native-tls-comp
, orasync-std-rustls-comp
. Additionally, thetls-rustls-webpki-roots
allows usage of of webpki-roots for the root certificate store.
§TCP settings
The user can set parameters of the underlying TCP connection by using thetcp_nodelay
andkeep-alive
features.Alternatively, users of async connections can setcrate::io::tcp::TcpSettings on the connection configuration objects,and set the TCP parameters in a more specific manner there.
§Connection Handling
For connecting to redis you can use a client object which then can produceactual connections. Connections and clients as well as results ofconnections and clients are consideredConnectionLike
objects andcan be used anywhere a request is made.
The full canonical way to get a connection is to create a client andto ask for a connection from it:
extern crateredis;fndo_something() -> redis::RedisResult<()> {letclient = redis::Client::open("redis://127.0.0.1/")?;letmutcon = client.get_connection()?;/* do something here */Ok(())}
§Connection Pooling
When using a sync connection, it is recommended to use a connection pool in order to handledisconnects or multi-threaded usage. This can be done using ther2d2
feature.
useredis::Commands;letclient = redis::Client::open("redis://127.0.0.1/").unwrap();letpool = r2d2::Pool::builder().build(client).unwrap();letmutconn = pool.get().unwrap();let _: () = conn.set("KEY","VALUE").unwrap();letval: String = conn.get("KEY").unwrap();
For async connections, connection pooling isn’t necessary. TheMultiplexedConnection
iscloneable and can be used safely from multiple threads, so a single connection can be easilyreused. For automatic reconnections consider usingConnectionManager
with theconnection-manager
feature.Async cluster connections also don’t require pooling and are thread-safe and reusable.
§Optional Features
There are a few features defined that can enable additional functionalityif so desired. Some of them are turned on by default.
acl
: enables acl support (enabled by default)tokio-comp
: enables support for async usage with the Tokio runtime (optional)async-std-comp
: enables support for async usage with any runtime which is async-std compliant, such as Smol. (optional)geospatial
: enables geospatial support (enabled by default)script
: enables script support (enabled by default)streams
: enables high-level interface for interaction with Redis streams (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)cluster-async
: enables async redis cluster support (optional)connection-manager
: enables support for automatic reconnection (optional)keep-alive
: enables keep-alive option on socket by means ofsocket2
crate (enabled by default)tcp_nodelay
: enables the no-delay flag on communication sockets (optional)rust_decimal
,bigdecimal
,num-bigint
: enables type conversions to large number representation from different crates (optional)uuid
: enables type conversion to UUID (optional)sentinel
: enables high-level interfaces for communication with Redis sentinels (optional)json
: enables high-level interfaces for communication with the JSON module (optional)cache-aio
: enablesexperimental client side caching for MultiplexedConnection (optional)disable-client-setinfo
: disables theCLIENT SETINFO
handshake during connection initialization
§Connection Parameters
redis-rs knows different ways to define where a connection shouldgo. The parameter toClient::open
needs to implement theIntoConnectionInfo
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 isredis://[<username>][:<password>@]<hostname>[:port][/[<db>][?protocol=<protocol>]]
If Unix socket support is available you can use a unix URL in this format:
redis+unix:///<path>[?db=<db>[&pass=<password>][&user=<username>][&protocol=<protocol>]]
For compatibility with some other libraries for Redis, the “unix” schemeis also supported:
unix:///<path>[?db=<db>][&pass=<password>][&user=<username>][&protocol=<protocol>]]
§Executing Low-Level Commands
To execute low-level commands you can use thecmd
function which allowsyou to build redis requests. Once you have configured a command objectto your liking you can send a query into anyConnectionLike
object:
fndo_something(con:&mutredis::Connection) -> redis::RedisResult<()> { redis::cmd("SET").arg("my_key").arg(42).exec(con)?;Ok(())}
Upon querying the return value is a result object. If you do not careabout 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 separatearg
:
fndo_something(con:&mutredis::Connection) -> redis::RedisResult<usize> {// This will result in a server error: "unknown command `MEMORY USAGE`" // because "USAGE" is technically a sub-command of "MEMORY".redis::cmd("MEMORY USAGE").arg("my_key").query::<usize>(con)?;// However, this will work as you'd expectredis::cmd("MEMORY").arg("USAGE").arg("my_key").query(con)}
§Executing High-Level Commands
The high-level interface is similar. For it to become available youneed to use theCommands
trait in which case allConnectionLike
objects the library provides will also have high-level methods whichmake working with the protocol easier:
extern crateredis;useredis::Commands;fndo_something(con:&mutredis::Connection) -> redis::RedisResult<()> {let _: () = con.set("my_key",42)?;Ok(())}
Note that high-level commands are work in progress and many are stillmissing!
§Type Conversions
Because redis inherently is mostly type-less and the protocol is notexactly friendly to developers, this library provides flexible supportfor casting values to the intended results. This is driven through theFromRedisValue
andToRedisArgs
traits.
Thearg
method of the command will accept a wide range of types throughtheToRedisArgs
trait and thequery
method of a command can convert thevalue to what you expect the function to return through theFromRedisValue
trait. This is quite flexible and allows vectors, tuples, hashsets, hashmapsas well as optional values:
letcount : i32 = con.get("my_counter")?;letcount = con.get("my_counter").unwrap_or(0i32);letk :Option<String> = con.get("missing_key")?;letname : String = con.get("my_name")?;letbin : Vec<u8> = con.get("my_binary")?;letmap : HashMap<String, i32> = con.hgetall("my_hash")?;letkeys : Vec<String> = con.hkeys("my_hash")?;letmems : HashSet<i32> = con.smembers("my_set")?;let(k1, k2) : (String, String) = con.get(&["k1","k2"])?;
§RESP3 support
Since Redis / Valkey version 6, a newer communication protocol called RESP3 is supported.Using this protocol allows the user both to receive a more variedValue
results, for userswho use the low-levelValue
type, and to receive out of band messages on the same connection. This allows the user to receive PubSubmessages on the same connection, instead of creating a new PubSub connection (see “RESP3 async pubsub”).
§Iteration Protocol
In addition to sending a single query, iterators are also supported. Whenused with regular bulk responses they don’t give you much over querying andconverting into a vector (both use a vector internally) but they can alsobe used withSCAN
like commands in which case iteration will send morequeries until the cursor is exhausted:
letmutiter : redis::Iter<isize> = redis::cmd("SSCAN").arg("my_set") .cursor_arg(0).clone().iter(&mutcon)?;forxiniter {// do something with the item}
As you can see the cursor argument needs to be defined withcursor_arg
instead ofarg
so that the library knows which argument needs updatingas the query is run for more items.
§Pipelining
In addition to simple queries you can also send command pipelines. Thisis provided through thepipe
function. It works very similar to sendingindividual commands but you can send more than one in one go. This alsoallows you to ignore individual results so that matching on the end resultis easier:
let(k1, k2) : (i32, i32) = redis::pipe() .cmd("SET").arg("key_1").arg(42).ignore() .cmd("SET").arg("key_2").arg(43).ignore() .cmd("GET").arg("key_1") .cmd("GET").arg("key_2").query(&mutcon)?;
If you want the pipeline to be wrapped in aMULTI
/EXEC
block you caneasily do that by switching the pipeline intoatomic
mode. From thecaller’s point of view nothing changes, the pipeline itself will takecare of the rest for you:
let(k1, k2) : (i32, i32) = redis::pipe() .atomic() .cmd("SET").arg("key_1").arg(42).ignore() .cmd("SET").arg("key_2").arg(43).ignore() .cmd("GET").arg("key_1") .cmd("GET").arg("key_2").query(&mutcon)?;
You can also use high-level commands on pipelines:
let(k1, k2) : (i32, i32) = redis::pipe() .atomic() .set("key_1",42).ignore() .set("key_2",43).ignore() .get("key_1") .get("key_2").query(&mutcon)?;
§Transactions
Transactions are available through atomic pipelines. In order to usethem in a more simple way you can use thetransaction
function of aconnection:
useredis::Commands;letkey ="the_key";let(new_val,) : (isize,) = redis::transaction(&mutcon,&[key], |con, pipe| {letold_val : isize = con.get(key)?; pipe .set(key, old_val +1).ignore() .get(key).query(con)})?;println!("The incremented number is: {}", new_val);
For more information see thetransaction
function.
§PubSub
Pubsub is provided through thePubSub
connection object for sync usage, or theaio::PubSub
for async usage.
Example usage:
letclient = redis::Client::open("redis://127.0.0.1/")?;letmutcon = client.get_connection()?;letmutpubsub = con.as_pubsub();pubsub.subscribe(&["channel_1","channel_2"])?;loop{letmsg = pubsub.get_message()?;letpayload : String = msg.get_payload()?;println!("channel '{}': {}", msg.get_channel_name(), payload);}
In order to update subscriptions while concurrently waiting for messages, the async PubSub can be split into separate sink & stream components. The sink can be receive subscription requests while the stream is awaited for messages.
usefutures_util::StreamExt;letclient = redis::Client::open("redis://127.0.0.1/")?;let(mutsink,mutstream) = client.get_async_pubsub().await?.split();sink.subscribe("channel_1").await?;loop{letmsg = stream.next().await.unwrap();letpayload : String = msg.get_payload().unwrap();println!("channel '{}': {}", msg.get_channel_name(), payload);}
§RESP3 async pubsub
If you’re targeting a Redis/Valkey server of version 6 or above, you can receivepubsub messages from it without creating another connection, by setting a push sender on the connection.
letclient = redis::Client::open("redis://127.0.0.1/?protocol=resp3").unwrap();let(tx,mutrx) = tokio::sync::mpsc::unbounded_channel();letconfig = redis::AsyncConnectionConfig::new().set_push_sender(tx);letmutcon = client.get_multiplexed_async_connection_with_config(&config).await?;con.subscribe(&["channel_1","channel_2"]).await?;loop{println!("Received {:?}", rx.recv().await.unwrap());}
§Scripts
Lua scripts are supported through theScript
type in a convenientway. It will automatically load the script if it does not exist and invoke it.
Example:
letscript = redis::Script::new(r" return tonumber(ARGV[1]) + tonumber(ARGV[2]);");letresult: isize = script.arg(1).arg(2).invoke(&mutcon)?;assert_eq!(result,3);
Scripts can also be pipelined:
letscript = redis::Script::new(r" return tonumber(ARGV[1]) + tonumber(ARGV[2]);");let(a, b): (isize, isize) = redis::pipe() .invoke_script(script.arg(1).arg(2)) .invoke_script(script.arg(2).arg(3)) .query(&mutcon)?;assert_eq!(a,3);assert_eq!(b,5);
Note: unlike a call toinvoke
, if the script isn’t loaded during the pipeline operation,it will not automatically be loaded and retried. The script can be loaded using theload
operation.
§Async
In addition to the synchronous interface that’s been explained above there also exists anasynchronous interface based onfutures
andtokio
, orasync-std
.
This interface exists under theaio
(async io) module (which requires that theaio
featureis enabled) and largely mirrors the synchronous with a few concessions to make it fit theconstraints offutures
.
usefutures::prelude::*;useredis::AsyncCommands;letclient = redis::Client::open("redis://127.0.0.1/").unwrap();letmutcon = client.get_multiplexed_async_connection().await?;let _: () = con.set("key1",b"foo").await?;redis::cmd("SET").arg(&["key2","bar"]).exec_async(&mutcon).await?;letresult = redis::cmd("MGET") .arg(&["key1","key2"]) .query_async(&mutcon) .await;assert_eq!(result,Ok(("foo".to_string(),b"bar".to_vec())));
§Sentinel
Sentinel types allow users to connect to Redis sentinels and find primaries and replicas.
useredis::{ Commands, RedisConnectionInfo };useredis::sentinel::{ SentinelServerType, SentinelClient, SentinelNodeConnectionInfo };letnodes =vec!["redis://127.0.0.1:6379/","redis://127.0.0.1:6378/","redis://127.0.0.1:6377/"];letmutsentinel = SentinelClient::build( nodes, String::from("primary1"),Some(SentinelNodeConnectionInfo { tls_mode:Some(redis::TlsMode::Insecure), redis_connection_info:None, }), redis::sentinel::SentinelServerType::Master,).unwrap();letprimary = sentinel.get_connection().unwrap();
An async API also exists:
usefutures::prelude::*;useredis::{ Commands, RedisConnectionInfo };useredis::sentinel::{ SentinelServerType, SentinelClient, SentinelNodeConnectionInfo };letnodes =vec!["redis://127.0.0.1:6379/","redis://127.0.0.1:6378/","redis://127.0.0.1:6377/"];letmutsentinel = SentinelClient::build( nodes, String::from("primary1"),Some(SentinelNodeConnectionInfo { tls_mode:Some(redis::TlsMode::Insecure), redis_connection_info:None, }), redis::sentinel::SentinelServerType::Master,).unwrap();letprimary = sentinel.get_async_connection().await.unwrap();
Modules§
- acl
acl
- Defines types to use with the ACL commands.
- aio
aio
- Adds async IO support to redis.
- caching
cache-aio
- This module providesexperimental support for Server-assisted client-side caching in Redis.
- cluster
cluster
- This module extends the library to support Redis Cluster.
- cluster_
async cluster
andaio
- This module provides async functionality for connecting to Redis / Valkey Clusters.
- cluster_
routing cluster
- Routing information for cluster commands.
- geo
geospatial
- Defines types to use with the geospatial commands.
- io
- Module for defining I/O behavior.
- sentinel
sentinel
- Defines a Sentinel type that connects to Redis sentinels and creates clients tomaster or replica nodes.
- streams
streams
- Defines types to use with the streams commands.
Structs§
- Async
Connection Config - Options for creation of async connection
- Async
Iter aio
- Represents a redis iterator that can be used with async connections.
- Client
- The client type.
- Client
TlsConfig tls-rustls
- Structure to hold mTLS clientcertificate andkey binaries in PEM format
- Cmd
- Represents redis commands.
- Command
Cache Config - CommandCacheConfig is used to define caching behaviour of individual commands.
- Connection
- Represents a stateful redis TCP connection.
- Connection
Info - Holds the connection information that redis should use for connecting.
- Info
Dict - An info dictionary type.
- Iter
- Represents a redis iterator.
- Lpos
Options - Options for theLPOS command
- Msg
- Represents a pubsub message.
- Parser
- The internal redis response parser.
- Pipeline
- Represents a redis command pipeline.
- PubSub
- Represents a pubsub connection.
- Push
Info - A push message from the server.
- Redis
Connection Info - Redis specific/connection independent information used to establish a connection to redis.
- Redis
Error - Represents a redis error.
- Replica
Info - Replication information for a replica, as returned by the
ROLE
command. - Scan
Options - Options for theSCAN command
- Script
script
- Represents a lua script.
- Script
Invocation script
- Represents a prepared script call.
- SetOptions
- Options for theSET command
- TlsCertificates
tls-rustls
- Structure to hold TLS certificates
Enums§
- Arg
- An argument to a redis command
- Connection
Addr - Defines the connection address.
- Control
Flow - Allows pubsub callbacks to stop receiving messages.
- Direction
- Enum for the LEFT | RIGHT args used by some commands
- Error
Kind - An enum of all error kinds.
- Existence
Check - Helper enum that is used to define existence checks
- Expire
Option - Helper enum that is used to define option for the hash expire commands
- Expiry
- Helper enum that is used to define expiry time
- Numeric
Behavior - Helper enum that is used in some situations to describethe behavior of arguments in a numeric context.
- Protocol
Version - Enum representing the communication protocol with the server.
- Push
Kind Push
type’s currently known kinds.- Retry
Method - What method should be used if retrying this request.
- Role
- High level representation of response to the
ROLE
command. - SetExpiry
- Helper enum that is used to define expiry time for SET command
- TlsMode
- TlsMode indicates use or do not use verification of certification.
- Value
- Internal low-level redis value enum.
- Verbatim
Format VerbatimString
’s format types defined by spec
Traits§
- Async
Commands aio
- Implements common redis commands over asynchronous connections.
- Commands
- Implements common redis commands for connection like objects.
- Connection
Like - Implements the “stateless” part of the connection interface that is used by thedifferent objects in redis-rs.
- From
Redis Value - This trait is used to convert a redis value into a more appropriatetype.
- Into
Connection Info - Converts an object into a connection info struct. This allows theconstructor of the client to accept connection information in arange of different formats.
- Json
Async Commands json
andaio
- Implements RedisJSON commands over asynchronous connections. Thisallows you to send commands straight to a connection or client.
- Json
Commands json
- Implements RedisJSON commands for connection like objects. Thisallows you to send commands straight to a connection or client. Itis also implemented for redis results of clients which makes forvery convenient access in some basic cases.
- PubSub
Commands - The PubSub trait allows subscribing to one or more channelsand receiving a callback whenever a message arrives.
- Redis
Write - Abstraction trait for redis command abstractions.
- ToRedis
Args - Used to convert a value into one or multiple redis argumentstrings. Most values will produce exactly one item but insome cases it might make sense to produce more than one.
Functions§
- cmd
- Shortcut function to creating a command with a single argument.
- from_
owned_ redis_ value - A shortcut function to invoke
FromRedisValue::from_owned_redis_value
to make the API slightly nicer. - from_
redis_ value - A shortcut function to invoke
FromRedisValue::from_redis_value
to make the API slightly nicer. - pack_
command - Packs a bunch of commands into a request.
- parse_
redis_ url - This function takes a redis URL string and parses it into a URLas used by rust-url.
- parse_
redis_ value - Parses bytes into a redis value.
- parse_
redis_ value_ async aio
- Parses a redis value asynchronously.
- pipe
- Shortcut for creating a new pipeline.
- transaction
- This function simplifies transaction management slightly. What itdoes is automatically watching keys and then going into a transactionloop util it succeeds. Once it goes through the results arereturned.
Type Aliases§
- Redis
Future aio
- Library generic future type.
- Redis
Result - Library generic result type.