Redis

Envoy can act as a Redis proxy, partitioning commands among instances in a cluster. In this mode, the goals of Envoy are to maintain availability and partition tolerance over consistency. This is the key point when comparing Envoy to Redis Cluster. Envoy is designed as a best-effort cache, meaning that it will not try to reconcile inconsistent data or keep a globally consistent view of cluster membership. It also supports routing commands from different workloads to different upstream clusters based on their access patterns, eviction, or isolation requirements.

The Redis project offers a thorough reference on partitioning as it relates to Redis. See “Partitioning: how to split data among multiple Redis instances”.

Features of Envoy Redis:

  • Redis protocol codec.

  • Hash-based partitioning.

  • Redis transaction support.

  • Ketama distribution.

  • Detailed command statistics.

  • Active and passive healthchecking.

  • Hash tagging.

  • Prefix routing.

  • Separate downstream client and upstream server authentication.

  • Request mirroring for all requests or write requests only.

  • Control read requests routing. This only works with Redis Cluster.

Planned future enhancements:

  • Additional timing stats.

  • Circuit breaking.

  • Request collapsing for fragmented commands.

  • Replication.

  • Built-in retry.

  • Tracing.

Configuration

For filter configuration details, see the Redis proxy filter configuration reference.

The corresponding cluster definition should be configured with ring hash load balancing.

If active health checking is desired, the cluster should be configured with a custom health check which configured as a Redis health checker.

If passive healthchecking is desired, also configure outlier detection.

For the purposes of passive healthchecking, connect timeouts, command timeouts, and connection close map to 5xx. All other responses from Redis are counted as a success.

Redis Cluster Support

Envoy offers support for Redis Cluster.

When using Envoy as a sidecar proxy for a Redis Cluster, the service can use a non-cluster Redis client implemented in any language to connect to the proxy as if it’s a single node Redis instance. The Envoy proxy will keep track of the cluster topology and send commands to the correct Redis node in the cluster according to the spec. Advance features such as reading from replicas can also be added to the Envoy proxy instead of updating redis clients in each language.

Envoy proxy tracks the topology of the cluster by sending periodic cluster slots commands to a random node in the cluster, and maintains the following information:

  • List of known nodes.

  • The primaries for each shard.

  • Nodes entering or leaving the cluster.

Envoy proxy supports identification of the nodes via both IP address and hostnames in the cluster slots command response. In case of failure to resolve a primary hostname, Envoy will retry resolution of all nodes periodically until success. Failure to resolve a replica simply skips that replica. On the other hand, if the enable_redirection option is set and a MOVED or ASK response containing a hostname is received Envoy will not automatically do a DNS lookup and instead bubble the error to the client verbatim. To have Envoy do the DNS lookup and follow the redirection, you need to configure the DNS cache option dns_cache_config under the connection pool settings. For a configuration example on how to enable DNS lookups for redirections, see the filter configuration reference.

For topology configuration details, see the Redis Cluster v3 API reference.

Every Redis cluster has its own extra statistics tree rooted at cluster.<name>.redis_cluster. with the following statistics:

Name

Type

Description

max_upstream_unknown_connections_reached

Counter

Total number of times that an upstream connection to an unknown host is not created after redirection having reached the connection pool’s max_upstream_unknown_connections limit

upstream_cx_drained

Counter

Total number of upstream connections drained of active requests before being closed

upstream_commands.upstream_rq_time

Histogram

Histogram of upstream request times for all types of requests

Per-cluster command statistics can be enabled via the setting enable_command_stats.:

Name

Type

Description

upstream_commands.[command].success

Counter

Total number of successful requests for a specific Redis command

upstream_commands.[command].failure

Counter

Total number of failed or cancelled requests for a specific Redis command

upstream_commands.[command].total

Counter

Total number of requests for a specific Redis command (sum of success and failure)

upstream_commands.[command].latency

Histogram

Latency of requests for a specific Redis command

Transactions

Transactions (MULTI) are supported. Their use is no different from regular Redis: you start a transaction with MULTI, and you execute it with EXEC. Within the transaction only commands that are supported by Envoy (see below) and are single-key commands are supported, i.e. MGET and MSET are not supported. The DISCARD command is supported.

When working in Redis Cluster mode, Envoy will relay all the commands in the transaction to the node handling the first key-based command in the transaction. It is the user’s responsibility to ensure that all keys in the transaction are mapped to the same hashslot, as commands will not be redirected.

Supported commands

At the protocol level, pipelines are supported. Use pipelining wherever possible for the best performance.

At the command level, Envoy only supports commands that can be reliably hashed to a server. AUTH and PING are the only exceptions. AUTH is processed locally by Envoy if a downstream password has been configured, and no other commands will be processed until authentication is successful when a password has been configured. Envoy will transparently issue AUTH commands upon connecting to upstream servers, if upstream authentication passwords are configured for the cluster. Envoy responds to PING immediately with PONG. Arguments to PING are not allowed. All other supported commands must contain a key. Supported commands are functionally identical to the original Redis command except possibly in failure scenarios.

For details on each command’s usage see the official Redis command reference.

Command

Group

AUTH

Authentication

PING

Connection

QUIT

Connection

DEL

Generic

DISCARD

Transaction

DUMP

Generic

EXEC

Transaction

EXISTS

Generic

EXPIRE

Generic

EXPIREAT

Generic

PERSIST

Generic

PEXPIRE

Generic

PEXPIREAT

Generic

PTTL

Generic

RESTORE

Generic

TOUCH

Generic

TTL

Generic

TYPE

Generic

UNLINK

Generic

GEOADD

Geo

GEODIST

Geo

GEOHASH

Geo

GEOPOS

Geo

GEORADIUS_RO

Geo

GEORADIUSBYMEMBER_RO

Geo

HDEL

Hash

HEXISTS

Hash

HGET

Hash

HGETALL

Hash

HINCRBY

Hash

HINCRBYFLOAT

Hash

HKEYS

Hash

HLEN

Hash

HMGET

Hash

HMSET

Hash

HSCAN

Hash

HSET

Hash

HSETNX

Hash

HSTRLEN

Hash

HVALS

Hash

PFADD

HyperLogLog

PFCOUNT

HyperLogLog

LINDEX

List

LINSERT

List

LLEN

List

LPOP

List

LPUSH

List

LPUSHX

List

LRANGE

List

LREM

List

LSET

List

LTRIM

List

MULTI

Transaction

RPOP

List

RPUSH

List

RPUSHX

List

EVAL

Scripting

EVALSHA

Scripting

SADD

Set

SCARD

Set

SISMEMBER

Set

SMEMBERS

Set

SPOP

Set

SRANDMEMBER

Set

SREM

Set

SSCAN

Set

ZADD

Sorted Set

ZCARD

Sorted Set

ZCOUNT

Sorted Set

ZINCRBY

Sorted Set

ZLEXCOUNT

Sorted Set

ZRANGE

Sorted Set

ZRANGEBYLEX

Sorted Set

ZRANGEBYSCORE

Sorted Set

ZRANK

Sorted Set

ZREM

Sorted Set

ZREMRANGEBYLEX

Sorted Set

ZREMRANGEBYRANK

Sorted Set

ZREMRANGEBYSCORE

Sorted Set

ZREVRANGE

Sorted Set

ZREVRANGEBYLEX

Sorted Set

ZREVRANGEBYSCORE

Sorted Set

ZREVRANK

Sorted Set

ZPOPMIN

Sorted Set

ZPOPMAX

Sorted Set

ZSCAN

Sorted Set

ZSCORE

Sorted Set

APPEND

String

BITCOUNT

String

BITFIELD

String

BITPOS

String

DECR

String

DECRBY

String

GET

String

GETBIT

String

GETRANGE

String

GETSET

String

INCR

String

INCRBY

String

INCRBYFLOAT

String

MGET

String

MSET

String

PSETEX

String

SET

String

SETBIT

String

SETEX

String

SETNX

String

SETRANGE

String

STRLEN

String

Failure modes

If Redis throws an error, we pass that error along as the response to the command. Envoy treats a response from Redis with the error datatype as a normal response and passes it through to the caller.

Envoy can also generate its own errors in response to the client.

Error

Meaning

no upstream host

The ring hash load balancer did not have a healthy host available at the ring position chosen for the key.

upstream failure

The backend did not respond within the timeout period or closed the connection.

invalid request

Command was rejected by the first stage of the command splitter due to datatype or length.

unsupported command

The command was not recognized by Envoy and therefore cannot be serviced because it cannot be hashed to a backend server.

finished with n errors

Fragmented commands which sum the response (e.g. DEL) will return the total number of errors received if any were received.

upstream protocol error

A fragmented command received an unexpected datatype or a backend responded with a response that not conform to the Redis protocol.

wrong number of arguments for command

Certain commands check in Envoy that the number of arguments is correct.

NOAUTH Authentication required.

The command was rejected because a downstream authentication password has been set and the client has not successfully authenticated.

ERR invalid password

The authentication command failed due to an invalid password.

ERR Client sent AUTH, but no password is set

An authentication command was received, but no downstream authentication password has been configured.

In the case of MGET, each individual key that cannot be fetched will generate an error response. For example, if we fetch five keys and two of the keys’ backends time out, we would get an error response for each in place of the value.

$ redis-cli MGET a b c d e
1) "alpha"
2) "bravo"
3) (error) upstream failure
4) (error) upstream failure
5) "echo"