go-redis joins Redis org on GitHub

Today the go-redis team is thrilled to release go-redis v9, which adds support for the RESP3 protocolopen in new window, introduces the new hooks API, improves pipelines retries, and allows performance monitoring via OpenTelemetry.

With this release, we also took the opportunity to move the go-redisopen in new window repository under the Redis GitHub organizationopen in new window, joining other popular Redis clients.

The new repository location means that you should use a new import path for go-redis v9:

// old, v8
import "github.com/go-redis/redis/v8"

// new, v9
import "github.com/redis/go-redis/v9"

Beyond that, the API remains the same, and previous releases will continue to work, with their current paths:

package main

import (
	"context"

	"github.com/redis/go-redis/v9"
)

func main() {
	ctx := context.Background()

	rdb := redis.NewClient(&redis.Options{
		Addr:	  "localhost:6379",
		Password: "", // no password set
		DB:		  0,  // use default DB
	})

	if err := rdb.Set(ctx, "key", "value", 0).Err(); err != nil {
		panic(err)
	}

	val, err := rdb.Get(ctx, "key").Result()
	if err != nil {
		panic(err)
	}
	fmt.Println("key", val)
}

RESP3

@monkey92topen in new window did the hard work to seamlessly support the RESP3open in new window protocol in go-redis v9!

RESP3 is an updated version of RESP v2, the protocol used in Redis. It supports more data typesopen in new window and lays the groundwork that will allow us to implement client side cachingopen in new window in future releases.

Improved hooks

v9 comes with the simplified design of execution hooks, used to instrument the following Redis client operations:

  • DialHook establishes a new connection.
  • ProcessHook processes a Redis command.
  • ProcessPipelineHook processes Redis commands in a pipeline.

The hooks API now looks like the following:

import "github.com/redis/go-redis/v9"

type redisHook struct{}

var _ redis.Hook = redisHook{}

func (redisHook) DialHook(hook redis.DialHook) redis.DialHook {
	return func(ctx context.Context, network, addr string) (net.Conn, error) {
		fmt.Printf("dialing %s %s\n", network, addr)
		conn, err := hook(ctx, network, addr)
		fmt.Printf("finished dialing %s %s\n", network, addr)
		return conn, err
	}
}

func (redisHook) ProcessHook(hook redis.ProcessHook) redis.ProcessHook {
	return func(ctx context.Context, cmd redis.Cmder) error {
		fmt.Printf("starting processing: <%s>\n", cmd)
		err := hook(ctx, cmd)
		fmt.Printf("finished processing: <%s>\n", cmd)
		return err
	}
}

func (redisHook) ProcessPipelineHook(hook redis.ProcessPipelineHook) redis.ProcessPipelineHook {
	return func(ctx context.Context, cmds []redis.Cmder) error {
		fmt.Printf("pipeline starting processing: %v\n", cmds)
		err := hook(ctx, cmds)
		fmt.Printf("pipeline finished processing: %v\n", cmds)
		return err
	}
}

OpenTelemetry

OpenTelemetryopen in new window is an open source and vendor-neutral API for distributed tracing, logs, and metrics. go-redis integrates with OpenTelemetry, instrumentation is based on redisotelopen in new window. The hooks API supports instrumentation in the go-redis client.

In v9, the redisotel package was fully reworked to support both OpenTelemetry tracingopen in new window and OpenTelemetry metricsopen in new window as follows:

import (
	"github.com/go-redis/redis/extra/redisotel/v9"
	"github.com/redis/go-redis/v9"
)

rdb := redis.NewClient(...)
// rdb := redis.NewClusterClient(...)

// Enable tracing instrumentation.
if err := redisotel.InstrumentTracing(rdb); err != nil {
	panic(err)
}

// Enable metrics instrumentation.
if err := redisotel.InstrumentMetrics(rdb); err != nil {
	panic(err)
}

See this exampleopen in new window on GitHub and OpenTelemetry Redis Monitoringopen in new window for further details.

Redis Metrics

Starting with v9, redisotel reports the following metrics:

  • db.client.connections.usage - the number of connections that are currently in state described by the state attribute.
  • db.client.connections.timeouts - the number of connection timeouts that have occurred trying to obtain a connection from the pool.
  • db.client.connections.create_time - the time it took to create a new connection.
  • db.client.connections.use_time - the time between borrowing a connection and returning it to the pool.

You can visualize and monitor those metrics using Uprace, an open source APMopen in new window tool, developed by by the go-redis authors 😃

Uptrace is a DataDog alternative with an intuitive query builder, rich dashboards, automatic alerts, and integrations for many languages and frameworks.

OpenTelemetry metrics can also be sent to Prometheus via OpenTelemetry Prometheus exporteropen in new window.

ParseClusterURL

In v8, an url based connection was supported by ParseURL as below:

options, err := redis.ParseURL("redis://<user>:<pass>@localhost:6379/<db>")
if err != nil {
	panic(err)
}
rdb := redis.NewClient(options)

In v9, Redis cluster support was added via ParseClusterURL:

options, err := redis.("redis://user:password@localhost:6789?dial_timeout=3&read_timeout=6s&addr=localhost:6790&addr=localhost:6791")
if err != nil {
	panic(err)
}
rdb := redis.NewClusterClient(options)
Last Updated:

Uptrace is an open source APM and DataDog alternative that supports OpenTelemetry traces, metrics, and logs. You can use it to monitor apps and set up alerts to receive notifications via email, Slack, Telegram, and more.

Uptrace can process billions of spans on a single server, allowing you to monitor your software at 10x less cost. View on GitHub →

Uptrace Demo