src.dualinventive.com/go/redis-proxy/vendor/github.com/mna/redisc/doc.go

179 lines
7.4 KiB
Go

// Package redisc implements a redis cluster client on top of
// the redigo client package. It supports all commands that can
// be executed on a redis cluster, including pub-sub, scripts and
// read-only connections to read data from replicas.
// See http://redis.io/topics/cluster-spec for details.
//
// Design
//
// The package defines two main types: Cluster and Conn. Both
// are described in more details below, but the Cluster manages
// the mapping of keys (or more exactly, hash slots computed from
// keys) to a group of nodes that form a redis cluster, and a
// Conn manages a connection to this cluster.
//
// The package is designed such that for simple uses, or when
// keys have been carefully named to play well with a redis
// cluster, a Cluster value can be used as a drop-in replacement
// for a redis.Pool from the redigo package.
//
// Similarly, the Conn type implements redigo's redis.Conn
// interface, so the API to execute commands is the same -
// in fact the redisc package uses the redigo package as its
// only third-party dependency.
//
// When more control is needed, the package offers some
// extra behaviour specific to working with a redis cluster:
//
// - Slot and SplitBySlot functions to compute the slot for
// a given key and to split a list of keys into groups of
// keys from the same slot, so that each group can safely be
// handled using the same connection.
//
// - *Conn.Bind (or the BindConn package-level helper function)
// to explicitly specify the keys that will be used with the
// connection so that the right node is selected, instead of
// relying on the automatic detection based on the first
// parameter of the command.
//
// - *Conn.ReadOnly (or the ReadOnlyConn package-level helper
// function) to mark a connection as read-only, allowing
// commands to be served by a replica instead of the master.
//
// - RetryConn to wrap a connection into one that automatically
// follows redirections when the cluster moves slots around.
//
// - Helper functions to deal with cluster-specific errors.
//
// Cluster
//
// The Cluster type manages a redis cluster and offers an
// interface compatible with redigo's redis.Pool:
//
// Get() redis.Conn
// Close() error
//
// Along with some additional methods specific to a cluster:
//
// Dial() (redis.Conn, error)
// Refresh() error
//
// If the CreatePool function field is set, then a
// redis.Pool is created to manage connections to each of the
// cluster's nodes. A call to Get returns a connection
// from that pool.
//
// The Dial method, on the other hand, guarantees that
// the returned connection will not be managed by a pool, even if
// CreatePool is set. It calls redigo's redis.Dial function
// to create the unpooled connection, passing along any DialOptions
// set on the cluster. If the cluster's CreatePool field is nil,
// Get behaves the same as Dial.
//
// The Refresh method refreshes the cluster's internal mapping of
// hash slots to nodes. It should typically be called only once,
// after the cluster is created and before it is used, so that
// the first connections already benefit from smart routing.
// It is automatically kept up-to-date based on the redis MOVED
// responses afterwards.
//
// A cluster must be closed once it is no longer used to release
// its resources.
//
// Connection
//
// The connection returned from Get or Dial is a redigo redis.Conn
// interface, with a concrete type of *Conn. In addition to the
// interface's required methods, *Conn adds the following methods:
//
// Bind(...string) error
// ReadOnly() error
//
// The returned connection is not yet connected to any node; it is
// "bound" to a specific node only when a call to Do, Send, Receive
// or Bind is made. For Do, Send and Receive, the node selection is
// implicit, it uses the first parameter of the command, and
// computes the hash slot assuming that first parameter is a key.
// It then binds the connection to the node corresponding to that
// slot. If there are no parameters for the command, or if there is
// no command (e.g. in a call to Receive), a random node is selected.
//
// Bind is explicit, it gives control to the caller over
// which node to select by specifying a list of keys that the caller
// wishes to handle with the connection. All keys must belong to the
// same slot, and the connection must not already be bound to a node,
// otherwise an error is returned. On success, the connection is
// bound to the node holding the slot of the specified key(s).
//
// Because the connection is returned as a redis.Conn interface, a
// type assertion must be used to access the underlying *Conn and
// to be able to call Bind:
//
// redisConn := cluster.Get()
// if conn, ok := redisConn.(*redisc.Conn); ok {
// if err := conn.Bind("my-key"); err != nil {
// // handle error
// }
// }
//
// The BindConn package-level function is provided as a helper for
// this common use-case.
//
// The ReadOnly method marks the connection as read-only, meaning that
// it will attempt to connect to a replica instead of the master node
// for its slot. Once bound to a node, the READONLY redis command is
// sent automatically, so it doesn't have to be sent explicitly before
// use. ReadOnly must be called before the connection is bound to a
// node, otherwise an error is returned.
//
// For the same reason as for Bind, a type assertion must be used to
// call ReadOnly on a *Conn, so a package-level helper function is
// also provided, ReadOnlyConn.
//
// There is no ReadWrite method, because it can be sent as a normal
// redis command and will essentially end that connection (all commands
// will now return MOVED errors). If the connection was wrapped in
// a RetryConn call, then it will automatically follow the redirection
// to the master node (see the Redirections section).
//
// The connection must be closed after use, to release the underlying
// resources.
//
// Redirections
//
// The redis cluster may return MOVED and ASK errors when the node
// that received the command doesn't currently hold the slot corresponding
// to the key. The package cannot reliably handle those redirections
// automatically because the redirection error may be returned for
// a pipeline of commands, some of which may have succeeded.
//
// However, a connection can be wrapped by a call to RetryConn, which
// returns a redis.Conn interface where only calls to Do, Close and Err
// can succeed. That means pipelining is not supported, and only a single
// command can be executed at a time, but it will automatically handle
// MOVED and ASK replies, as well as TRYAGAIN errors.
//
// Note that even if RetryConn is not used, the cluster always updates
// its mapping of slots to nodes automatically by keeping track of
// MOVED replies.
//
// Concurrency
//
// The concurrency model is similar to that of the redigo package:
//
// - Cluster methods are safe to call concurrently (like redis.Pool).
//
// - Connections do not support concurrent calls to write methods
// (Send, Flush) or concurrent calls to the read method (Receive).
//
// - Connections do allow a concurrent reader and writer.
//
// - Because the Do method combines the functionality of Send, Flush
// and Receive, it cannot be called concurrently with other methods.
//
// - The Bind and ReadOnly methods are safe to call concurrently, but
// there is not much point in doing so for as both will fail if
// the connection is already bound.
//
package redisc