• Stars
    star
    141
  • Rank 259,971 (Top 6 %)
  • Language
    Go
  • License
    Creative Commons ...
  • Created over 1 year ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

High-performance Redis library for Go

redjet

Go Reference ci Coverage Status Go Report Card

redjet is a high-performance Go library for Redis. Its hallmark feature is a low-allocation, streaming API. See the benchmarks section for more details.

Unlike redigo and go-redis, redjet does not provide a function for every Redis command. Instead, it offers a generic interface that supports all commands and options. While this approach has less type-safety, it provides forward compatibility with new Redis features.

In the aim of both performance and ease-of-use, redjet attempts to provide an API that closely resembles the protocol. For example, the Command method is really a Pipeline of size 1.

Table of Contents

Basic Usage

Install:

go get github.com/coder/redjet@latest

For the most part, you can interact with Redis using a familiar interface:

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/coder/redjet"
)

func main() {
    client := redjet.New("localhost:6379")
    ctx := context.Background()

    err := client.Command(ctx, "SET", "foo", "bar").Ok()
    // check error

    got, err := client.Command(ctx, "GET", "foo").Bytes()
    // check error
    // got == []byte("bar")
}

Streaming

To minimize allocations, call (*Pipeline).WriteTo instead of (*Pipeline).Bytes. WriteTo streams the response directly to an io.Writer such as a file or HTTP response.

For example:

_, err := client.Command(ctx, "GET", "big-object").WriteTo(os.Stdout)
// check error

Similarly, you can pass in a value that implements redjet.LenReader to Command to stream larger values into Redis. Unfortunately, the API cannot accept a regular io.Reader because bulk string messages in the Redis protocol are length-prefixed.

Here's an example of streaming a large file into Redis:

bigFile, err := os.Open("bigfile.txt")
// check error
defer bigFile.Close()

stat, err := bigFile.Stat()
// check error

err = client.Command(
    ctx, "SET", "bigfile",
    redjet.NewLenReader(bigFile, stat.Size()),
).Ok()
// check error

If you have no way of knowing the size of your blob in advance and still want to avoid large allocations, you may chunk a stream into Redis using repeated APPEND commands.

Pipelining

redjet supports pipelining via the (*Client).Pipeline method. This method accepts a Pipeline, potentially that of a previous, open command.

// Set foo0, foo1, ..., foo99 to "bar", and confirm that each succeeded.
//
// This entire example only takes one round-trip to Redis!
var p *Pipeline
for i := 0; i < 100; i++ {
    p = client.Pipeline(p, "SET", fmt.Sprintf("foo%d", i), "bar")
}

for r.Next() {
    if err := p.Ok(); err != nil {
        log.Fatal(err)
    }
}
p.Close() // allow the underlying connection to be reused.

PubSub

redjet suports PubSub via the NextSubMessage method. For example:

// Subscribe to a channel
sub := client.Command(ctx, "SUBSCRIBE", "my-channel")
sub.NextSubMessage() // ignore the first message, which is a confirmation of the subscription

// Publish a message to the channel
n, err := client.Command(ctx, "PUBLISH", "my-channel", "hello world").Int()
// check error
// n == 1, since there is one subscriber

// Receive the message
sub.NextSubMessage()
// sub.Payload == "hello world"
// sub.Channel == "my-channel"
// sub.Type == "message"

Note that NextSubMessage will block until a message is received. To interrupt the subscription, cancel the context passed to Command.

Once a connection enters subscribe mode, the internal pool does not re-use it.

It is possible to subscribe to a channel in a performant, low-allocation way via the public API. NextSubMessage is just a convenience method.

JSON

redjet supports convenient JSON encoding and decoding via the (*Pipeline).JSON method. For example:

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

// Set a person
// Unknown argument types are automatically encoded to JSON.
err := client.Command(ctx, "SET", "person", Person{
    Name: "Alice",
    Age:  30,
}).Ok()
// check error

// Get a person
var p Person
client.Command(ctx, "GET", "person").JSON(&p)
// check error

// p == Person{Name: "Alice", Age: 30}

Connection Pooling

Redjet provides automatic connection pooling. Configuration knobs exist within the Client struct that may be changed before any Commands are issued.

If you want synchronous command execution over the same connection, use the Pipeline method and consume the Pipeline after each call to Pipeline. Storing a long-lived Pipeline offers the same functionality as storing a long-lived connection.

Benchmarks

On a pure throughput basis, redjet will perform similarly to redigo and go-redis. But, since redjet doesn't allocate memory for the entire response object, it consumes far less resources when handling large responses.

Here are some benchmarks (reproducible via make gen-bench) to illustrate:

.fullname: Get/1_B-10
 │   redjet    │               redigo               │           go-redis            │               rueidis                │
 │   sec/op    │   sec/op     vs base               │   sec/op     vs base          │    sec/op     vs base                │
   908.2n ± 2%   962.4n ± 1%  +5.97% (p=0.000 n=10)   913.8n ± 3%  ~ (p=0.280 n=10)   1045.0n ± 1%  +15.06% (p=0.000 n=10)

 │    redjet     │                redigo                │            go-redis             │               rueidis                │
 │      B/s      │      B/s       vs base               │      B/s       vs base          │     B/s       vs base                │
   1074.2Ki ± 2%   1015.6Ki ± 1%  -5.45% (p=0.000 n=10)   1069.3Ki ± 2%  ~ (p=0.413 n=10)   937.5Ki ± 1%  -12.73% (p=0.000 n=10)

 │  redjet   │            redigo            │           go-redis            │            rueidis            │
 │   B/op    │    B/op     vs base          │    B/op      vs base          │    B/op      vs base          │
   0.00 ± 0%   41.00 ± 0%  ? (p=0.000 n=10)   275.50 ± 2%  ? (p=0.000 n=10)   249.00 ± 0%  ? (p=0.000 n=10)

 │   redjet   │            redigo            │           go-redis           │           rueidis            │
 │ allocs/op  │ allocs/op   vs base          │ allocs/op   vs base          │ allocs/op   vs base          │
   0.000 ± 0%   3.000 ± 0%  ? (p=0.000 n=10)   4.000 ± 0%  ? (p=0.000 n=10)   2.000 ± 0%  ? (p=0.000 n=10)

.fullname: Get/1.0_kB-10
 │   redjet    │               redigo                │              go-redis               │               rueidis               │
 │   sec/op    │   sec/op     vs base                │   sec/op     vs base                │   sec/op     vs base                │
   1.302µ ± 2%   1.802µ ± 1%  +38.42% (p=0.000 n=10)   1.713µ ± 3%  +31.58% (p=0.000 n=10)   1.645µ ± 1%  +26.35% (p=0.000 n=10)

 │    redjet    │                redigo                │               go-redis               │               rueidis                │
 │     B/s      │     B/s       vs base                │     B/s       vs base                │     B/s       vs base                │
   750.4Mi ± 2%   542.1Mi ± 1%  -27.76% (p=0.000 n=10)   570.3Mi ± 3%  -24.01% (p=0.000 n=10)   593.8Mi ± 1%  -20.87% (p=0.000 n=10)

 │    redjet    │             redigo             │            go-redis            │            rueidis             │
 │     B/op     │     B/op      vs base          │     B/op      vs base          │     B/op      vs base          │
   0.000Ki ± 0%   1.039Ki ± 0%  ? (p=0.000 n=10)   1.392Ki ± 0%  ? (p=0.000 n=10)   1.248Ki ± 1%  ? (p=0.000 n=10)

 │   redjet   │            redigo            │           go-redis           │           rueidis            │
 │ allocs/op  │ allocs/op   vs base          │ allocs/op   vs base          │ allocs/op   vs base          │
   0.000 ± 0%   3.000 ± 0%  ? (p=0.000 n=10)   4.000 ± 0%  ? (p=0.000 n=10)   2.000 ± 0%  ? (p=0.000 n=10)

.fullname: Get/1.0_MB-10
 │   redjet    │            redigo             │              go-redis               │            rueidis            │
 │   sec/op    │   sec/op     vs base          │   sec/op     vs base                │   sec/op     vs base          │
   472.5µ ± 7%   477.3µ ± 2%  ~ (p=0.190 n=10)   536.8µ ± 6%  +13.61% (p=0.000 n=10)   475.3µ ± 6%  ~ (p=0.684 n=10)

 │    redjet    │             redigo             │               go-redis               │            rueidis             │
 │     B/s      │     B/s       vs base          │     B/s       vs base                │     B/s       vs base          │
   2.067Gi ± 8%   2.046Gi ± 2%  ~ (p=0.190 n=10)   1.819Gi ± 6%  -11.98% (p=0.000 n=10)   2.055Gi ± 6%  ~ (p=0.684 n=10)

 │   redjet    │                    redigo                    │                   go-redis                   │                   rueidis                    │
 │    B/op     │      B/op        vs base                     │      B/op        vs base                     │      B/op        vs base                     │
   51.00 ± 12%   1047849.50 ± 0%  +2054506.86% (p=0.000 n=10)   1057005.00 ± 0%  +2072458.82% (p=0.000 n=10)   1048808.50 ± 0%  +2056387.25% (p=0.000 n=10)

 │   redjet   │               redigo                │              go-redis               │               rueidis               │
 │ allocs/op  │ allocs/op   vs base                 │ allocs/op   vs base                 │ allocs/op   vs base                 │
   1.000 ± 0%   3.000 ± 0%  +200.00% (p=0.000 n=10)   4.000 ± 0%  +300.00% (p=0.000 n=10)   2.000 ± 0%  +100.00% (p=0.000 n=10)

Limitations

  • redjet does not have convenient support for client side caching. But, the redjet API is flexible enough that a client could implement it themselves by following the instructions here.
  • RESP3 is not supported. Practically, this means that connections aren't multiplexed, and other Redis libraries may perform better in high-concurrency scenarios.
  • Certain features have not been tested but may still work:
    • Redis Streams
    • Monitor

More Repositories

1

code-server

VS Code in the browser
TypeScript
67,974
star
2

coder

Provision remote development environments via Terraform
Go
8,129
star
3

sshcode

Run VS Code on any server over SSH.
Go
5,736
star
4

websocket

Minimal and idiomatic WebSocket library for Go
Go
3,892
star
5

deploy-code-server

Deploy code-server to the cloud with a few clicks ☁️ 👨🏼‍💻
Shell
874
star
6

wush

simplest & fastest way to transfer files between computers via WireGuard
Go
779
star
7

sail

Deprecated: Instant, pre-configured VS Code development environments.
Go
628
star
8

slog

Minimal structured logging library for Go
Go
334
star
9

picopilot

GitHub Copilot in 70 lines of JavaScript
JavaScript
244
star
10

quartz

A Go time testing library for writing deterministic unit tests
Go
233
star
11

code-marketplace

Open source extension marketplace for VS Code.
Go
221
star
12

awesome-code-server

Projects, resources, and tutorials that take code-server to the next level
165
star
13

envbuilder

Build development environments from a Dockerfile on Docker, Kubernetes, and OpenShift. Enable developers to modify their development environment quickly.
Go
143
star
14

awesome-coder

A curated list of awesome Coder resources.
130
star
15

aicommit

become the world's laziest committer
Go
125
star
16

nbin

Fast and robust node.js binary compiler.
TypeScript
107
star
17

hnsw

In-memory vector index for Go
Go
98
star
18

enterprise-images

Example Docker images for use with Coder
Shell
95
star
19

coder-v1-cli

Command line for Coder v1. For Coder v2, go to https://github.com/coder/coder
72
star
20

vscode-coder

Open any Coder workspace in VS Code with a single click.
TypeScript
66
star
21

cli

A minimal Go CLI package.
Go
49
star
22

enterprise-helm

Operate Coder v1 on Kubernetes
Go
45
star
23

retry

A tiny retry package for Go.
Go
39
star
24

backstage-plugins

Official Coder plugins for the Backstage platform
TypeScript
38
star
25

hat

HTTP API testing for Go
Go
37
star
26

wgtunnel

HTTP tunnels over Wireguard
Go
37
star
27

envbox

envbox is an image that enables creating non-privileged containers capable of running system-level software (e.g. dockerd, systemd, etc) in Kubernetes.
Go
34
star
28

modules

A collection of Terraform Modules to extend Coder templates.
HCL
32
star
29

terraform-provider-coder

Go
30
star
30

cursor-arm

Cursor built for ARM Linux and Windows
Nix
30
star
31

wsep

High performance command execution protocol
Go
27
star
32

node-browser

Use Node in the browser.
TypeScript
27
star
33

packages

Deploy Coder to your preferred cloud with a pre-built package.
HCL
27
star
34

exectrace

Simple eBPF-based exec snooping on Linux packaged as a Go library.
Go
25
star
35

labeler

A GitHub app that labels your issues for you
Go
24
star
36

jetbrains-coder

A JetBrains Plugin for Coder Workspaces
Kotlin
24
star
37

flog

Pretty formatted log for Go
Go
23
star
38

docs

Markdown content for Coder v1 Docs.
Shell
22
star
39

code-server-aur

code-server AUR package
Shell
15
star
40

coder-logstream-kube

Stream Kubernetes Pod events to the Coder startup logs
Go
13
star
41

pretty

TTY styles for Go
Go
13
star
42

ts-logger

TypeScript
13
star
43

requirefs

Create a readable and requirable file system from tars, zips, or a custom provider.
TypeScript
12
star
44

serpent

CLI framework for scale and configurability inspired by Cobra
Go
11
star
45

cloud-agent

The agent for Coder Cloud
Go
11
star
46

homebrew-coder

Coder Homebrew Tap
Ruby
11
star
47

coder.rs

[EXPERIMENTAL] Asynchronous Rust wrapper around the Coder Enterprise API
Rust
10
star
48

bigdur

A Go package for parsing larger durations.
Go
9
star
49

timer

Accurately measure how long a command takes to run
Go
9
star
50

terraform-provider-coderd

Manage a Coder deployment using Terraform
Go
9
star
51

webinars

HCL
8
star
52

presskit

press kit and brand assets for Coder.com
7
star
53

envbuilder-starter-devcontainer

A sample project for getting started with devcontainer.json in envbuilder
Dockerfile
7
star
54

coder-doctor

A preflight check tool for Coder
Go
6
star
55

observability

Go
6
star
56

blogs

Content for coder.com/blog
D2
6
star
57

terraform-provider-envbuilder

Go
6
star
58

nfy

EXPERIMENTAL: Pumped up install scripts
Go
5
star
59

ghlabels

A tool to synchronize labels on GitHub repositories sanely.
Go
5
star
60

codercord

A Discord bot for our community server
Dart
5
star
61

devcontainer-webinar

The Good, The Bad, And The Future of Dev Containers
Shell
5
star
62

jetbrains-backend-coder

Kotlin
5
star
63

coder-xray

JFrog XRay Integration
Go
4
star
64

gke-disk-cleanup

Go
4
star
65

cla

The Coder Contributor License Agreement (CLA)
4
star
66

starquery

Query in near-realtime if a user has starred a GitHub repository.
Go
4
star
67

setup-action

Downloads and Configures Coder.
4
star
68

support-scripts

Things for Coder Customer Success.
Shell
3
star
69

.github

3
star
70

enterprise-terraform

Terraform modules and examples for deploying Coder
HCL
3
star
71

sail-aur

sail AUR package
Shell
3
star
72

styleguide

2
star
73

grip

extensible logging and messaging framework for go processes.
Go
2
star
74

presentations

Talks and presentations related to Coder released under CC0 which permits remixing and reuse!
2
star
75

coder-docs-generator

Generates off-line docs for Coder Docs
TypeScript
2
star
76

community-templates

Unofficial templates for Coder for various platforms and cloud providers
HCL
2
star
77

gott

go test timer
Go
2
star
78

wxnm

A library for providing TypeScript typed communication between your web extension and your native Node application using Native Messaging
TypeScript
2
star
79

internal

Non-community issues related to coder/coder
2
star
80

synology

a work in progress prototype
Shell
2
star
81

feeltty

Quantify the typing experience of a TTY
Go
1
star
82

merge-queue-test

Shell
1
star
83

containers-test

Container images compatible with Coder
Dockerfile
1
star
84

sshcode-aur

sshcode AUR package
Shell
1
star
85

sandbox-for-github

a sandpit for playing around with GitHub configuration stuff such as GitHub actions or issue templates
1
star