RedisJSON with Golang
Recently, I've been working on an authentication system where multiple services push user information through RabbitMQ and a consumer store record into the MongoDB database.
To reduce the frequent requests to the database, redis cache would be a better fit but I had very basic knowledge about redis. I knew that it stores information in key value
.
As MongoDB schema design all the information sent by services will be stored in JSON format. So, I need to store JSON data in redis.
After surfing in internet I came to know that redis has a module RedisJSON which provides JSON support for Redis.Since, I'm using Golang to write service, found go-rejson package which supports write and read JSON in redis.
These are the steps that I try to Implementation RedisJSON in Golang. You can find code at Github Repo
step 1 Setup a Redis Server in Docker
docker run -n redis -p 6379:6379 redislabs/redismod
You can connect to redis server with redis-cli
step 2 Verify RedisJSON module in redis Server
#1
docker exec -it (container name / id )) bash
#2
redis-cli
#3
info moudles
Check modules with Name rejson
Step 3 Initialise Go module
go mod init github/prabeshmagar/go-redis-json
Example with Go-redis
Go-redis is a type-safe, Redis client library for Go with support for features like Pub/Sub, sentinel, and pipelining.It is a Redis client able to support a Redis cluster and is designed to store and update slot info automatically with a cluster change.
The go-redis library is located in the https://github.com/go-redis/redis.
step 1 Install go-redis
go get github.com/go-redis/redis/v8
step 2 Write goredis service
package service
import (
"bytes"
"context"
"encoding/gob"
"fmt"
"log"
"github.com/go-redis/redis/v8"
"github.com/nitishm/go-rejson/v4"
)
type GoRedis struct {
Client *redis.Client
Handler *rejson.Handler
}
func GoRedisExample(url string) *GoRedis {
client := redis.NewClient(&redis.Options{
Addr: url,
})
rh := rejson.NewReJSONHandler()
rh.SetGoRedisClient(client)
return &GoRedis{
Client: client,
Handler: rh,
}
}
func (r GoRedis) GoRedisSetJSON(key string, value interface{}) error {
res, err := r.Handler.JSONSet(key, ".", value)
if err != nil {
log.Fatalf("Failed to JSONSet with go redis")
return err
}
if res.(string) == "OK" {
fmt.Printf("GoRedis Success: %s\n", res)
}
return nil
}
func (r GoRedis) GoRedisGetJSON(key string) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
ctx := context.Background()
val, err := r.Client.Do(ctx, "JSON.GET", key, ".name").Result()
if err != nil {
fmt.Println("unable to get data from redis")
}
er := enc.Encode(val)
if er != nil {
panic("unable to encode value")
}
fmt.Printf("Reading data from redis with goredis : %#v\n", val)
}
step 3 Main code
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/prabeshmagar/go-redis-json/service"
)
var redisHost = "localhost:6379"
func main() {
anotherStudent := service.Student{
Name: service.Name{
First: "Prabesh",
Middle: "",
Last: "Magar",
},
Rank: 2,
}
// Goredis example
goRedisService := service.GoRedisExample(redisHost)
err = goRedisService.GoRedisSetJSON("another", anotherStudent)
if err != nil {
fmt.Println("failed to store json in redis with goredis")
}
goRedisService.GoRedisGetJSON("another")
}
Output
<img src="go-redis-out.png" style="width:100%; height:auto;>
Example with redigo
Redigo is a Go client for the Redis database. Features. A Print-like API with support for all Redis commands. Pipelining, including pipelined transactions. Publish/Subscribe. Connection pooling. Script helper type with optimistic use of EVALSHA. Helper functions for working with command replies.
The redigo library is located in the https://github.com/gomodule/redigo
step 1 Install redigo
go get github.com/gomodule/redigo/redis
step 2 Write redigo service
package service
import (
"fmt"
"log"
"github.com/gomodule/redigo/redis"
"github.com/nitishm/go-rejson/v4"
)
// Name - student name
type Name struct {
First string `json:"first,omitempty"`
Middle string `json:"middle,omitempty"`
Last string `json:"last,omitempty"`
}
// Student - student object
type Student struct {
Name Name `json:"name,omitempty"`
Rank int `json:"rank,omitempty"`
}
type RedigoService struct {
Client redis.Conn
Handler *rejson.Handler
}
func RedigoExample(url string) RedigoService {
conn, err := redis.Dial("tcp", url)
rh := rejson.NewReJSONHandler()
if err != nil {
log.Fatalf("Failed to connect to redis-server @ %s", url)
panic(err)
}
rh.SetRedigoClient(conn)
return RedigoService{
Client: conn,
Handler: rh,
}
}
func (r RedigoService) SetJson(key string, value interface{}) error {
res, err := r.Handler.JSONSet(key, ".", value)
if err != nil {
log.Fatalf("Failed to JSONSet")
return err
}
if res.(string) == "OK" {
fmt.Printf("Redigo Success: %s\n", res)
}
return nil
}
func (r RedigoService) GetJson(key string) []byte {
studentJSON, err := redis.Bytes(r.Handler.JSONGet(key, "."))
if err != nil {
log.Fatalf("Failed to JSONGet")
return nil
}
return studentJSON
}
Application code with Redigo
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/prabeshmagar/go-redis-json/service"
)
var redisHost = "localhost:6379"
func main() {
student := service.Student{
Name: service.Name{
First: "Mark",
Middle: "S",
Last: "Pronto",
},
Rank: 1,
}
//RedigoExample
redigoService := service.RedigoExample(redisHost)
err := redigoService.SetJson("student", student)
if err != nil {
fmt.Println("failed to store json in redis with redigo")
}
studentJSON := redigoService.GetJson("student")
readStudent := service.Student{}
err = json.Unmarshal(studentJSON, &readStudent)
if err != nil {
log.Fatalf("Failed to JSON Unmarshal")
}
fmt.Printf("Reading data from redis with redigo : %#v\n", readStudent)
}
Output
Conclusion
This article explain about working with json in Redis using Golang and redis package redigo and go-redis and go-rejson package.