package
0.0.0-20240819164739-f47aed85de5a
Repository: https://github.com/unix-world/smartgo.git
Documentation: pkg.go.dev
# README
Redis compatible server framework for Go
Features
- Create a Fast custom Redis compatible server in Go
- Simple interface. One function
ListenAndServe
and two typesConn
&Command
- Support for pipelining and telnet commands
- Works with Redis clients such as redigo, redis-py, node_redis, and jedis
- TLS Support
- Compatible pub/sub support
- Multithreaded
This library is also avaliable for Rust and C.
Installing
go get -u github.com/tidwall/redcon
Example
Here's a full example of a Redis clone that accepts:
- SET key value
- GET key
- DEL key
- PING
- QUIT
- PUBLISH channel message
- SUBSCRIBE channel
You can run this example from a terminal:
go run example/clone.go
package main
import (
"log"
"strings"
"sync"
"github.com/tidwall/redcon"
)
var addr = ":6380"
func main() {
var mu sync.RWMutex
var items = make(map[string][]byte)
var ps redcon.PubSub
go log.Printf("started server at %s", addr)
err := redcon.ListenAndServe(addr,
func(conn redcon.Conn, cmd redcon.Command) {
switch strings.ToLower(string(cmd.Args[0])) {
default:
conn.WriteError("ERR unknown command '" + string(cmd.Args[0]) + "'")
case "ping":
conn.WriteString("PONG")
case "quit":
conn.WriteString("OK")
conn.Close()
case "set":
if len(cmd.Args) != 3 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
mu.Lock()
items[string(cmd.Args[1])] = cmd.Args[2]
mu.Unlock()
conn.WriteString("OK")
case "get":
if len(cmd.Args) != 2 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
mu.RLock()
val, ok := items[string(cmd.Args[1])]
mu.RUnlock()
if !ok {
conn.WriteNull()
} else {
conn.WriteBulk(val)
}
case "del":
if len(cmd.Args) != 2 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
mu.Lock()
_, ok := items[string(cmd.Args[1])]
delete(items, string(cmd.Args[1]))
mu.Unlock()
if !ok {
conn.WriteInt(0)
} else {
conn.WriteInt(1)
}
case "publish":
if len(cmd.Args) != 3 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
conn.WriteInt(ps.Publish(string(cmd.Args[1]), string(cmd.Args[2])))
case "subscribe", "psubscribe":
if len(cmd.Args) < 2 {
conn.WriteError("ERR wrong number of arguments for '" + string(cmd.Args[0]) + "' command")
return
}
command := strings.ToLower(string(cmd.Args[0]))
for i := 1; i < len(cmd.Args); i++ {
if command == "psubscribe" {
ps.Psubscribe(conn, string(cmd.Args[i]))
} else {
ps.Subscribe(conn, string(cmd.Args[i]))
}
}
}
},
func(conn redcon.Conn) bool {
// Use this function to accept or deny the connection.
// log.Printf("accept: %s", conn.RemoteAddr())
return true
},
func(conn redcon.Conn, err error) {
// This is called when the connection has been closed
// log.Printf("closed: %s, err: %v", conn.RemoteAddr(), err)
},
)
if err != nil {
log.Fatal(err)
}
}
TLS Example
Redcon has full TLS support through the ListenAndServeTLS
function.
The same example is also provided for serving Redcon over TLS.
go run example/tls/clone.go
Benchmarks
Redis: Single-threaded, no disk persistence.
$ redis-server --port 6379 --appendonly no
redis-benchmark -p 6379 -t set,get -n 10000000 -q -P 512 -c 512
SET: 941265.12 requests per second
GET: 1189909.50 requests per second
Redcon: Single-threaded, no disk persistence.
$ GOMAXPROCS=1 go run example/clone.go
redis-benchmark -p 6380 -t set,get -n 10000000 -q -P 512 -c 512
SET: 2018570.88 requests per second
GET: 2403846.25 requests per second
Redcon: Multi-threaded, no disk persistence.
$ GOMAXPROCS=0 go run example/clone.go
$ redis-benchmark -p 6380 -t set,get -n 10000000 -q -P 512 -c 512
SET: 1944390.38 requests per second
GET: 3993610.25 requests per second
Running on a MacBook Pro 15" 2.8 GHz Intel Core i7 using Go 1.7
Contact
Josh Baker @tidwall
License
Redcon source code is available under the MIT License.
# Packages
No description provided by the author
# Functions
AppendAny appends any type to valid Redis type.
AppendArray appends a Redis protocol array to the input bytes.
AppendBulk appends a Redis protocol bulk byte slice to the input bytes.
AppendBulkFloat appends a float64, as bulk bytes.
AppendBulkInt appends an int64, as bulk bytes.
AppendBulkString appends a Redis protocol bulk string to the input bytes.
AppendBulkUint appends an uint64, as bulk bytes.
AppendError appends a Redis protocol error to the input bytes.
AppendInt appends a Redis protocol int64 to the input bytes.
AppendNull appends a Redis protocol null to the input bytes.
AppendOK appends a Redis protocol OK to the input bytes.
AppendString appends a Redis protocol string to the input bytes.
AppendTile38 appends a Tile38 message to the input bytes.
AppendUint appends a Redis protocol uint64 to the input bytes.
BaseWriter returns the underlying connection writer, if any.
ListenAndServe creates a new server and binds to addr configured on "tcp" network net.
ListenAndServeNetwork creates a new server and binds to addr.
ListenAndServeNetworkTLS creates a new TLS server and binds to addr.
ListenAndServeTLS creates a new TLS server and binds to addr configured on "tcp" network net.
NewReader returns a command reader which will read RESP or telnet commands.
NewServeMux allocates and returns a new ServeMux.
NewServer returns a new Redcon server configured on "tcp" network net.
NewServerNetwork returns a new Redcon server.
NewServerNetworkTLS returns a new TLS Redcon server.
NewServerTLS returns a new Redcon TLS server configured on "tcp" network net.
NewWriter creates a new RESP writer.
Parse parses a raw RESP message and returns a command.
ReadNextCommand reads the next command from the provided packet.
ReadNextRESP returns the next resp in b and returns the number of bytes the took up the result.
Serve creates a new server and serves with the given net.Listener.
# Structs
Command represent a command.
PubSub is a Redis compatible pub/sub server.
Reader represent a reader for RESP or telnet commands.
No description provided by the author
ServeMux is an RESP command multiplexer.
Server defines a server for clients for managing client connections.
TLSServer defines a server for clients for managing client connections.
Writer allows for writing RESP messages.
# Interfaces
Conn represents a client connection.
DetachedConn represents a connection that is detached from the server.
A Handler responds to an RESP request.
Marshaler is the interface implemented by types that can marshal themselves into a Redis response type from an *Any call.
# Type aliases
The HandlerFunc type is an adapter to allow the use of ordinary functions as RESP handlers.
Kind is the kind of command.
SimpleError is for representing an error without adding the "ERR" prefix from an *Any call.
SimpleInt is for representing a non-bulk representation of a int from an *Any call.
SimpleString is for representing a non-bulk representation of a string from an *Any call.
Type of RESP.