A tutorial of using redis in golang

Posted by phynias on Fri, 26 Jun 2020 10:36:55 +0200

Original link: https://blog.csdn.net/wangshubo1989/article/details/75050024/

Life goes on, go go go!!!

Previously, I introduced how to use sqlite3 in golang:
<Go practice - go language operates sqlite database (The way to go)>

Today I want to share with you how to use redis database in golang.

##What is redis

Official website:
https://redis.io/

Redis is an in-memory database open-source software project implementing a networked, in-memory Key-Value store with optional durability.Redis It is an open-source key value database written in C language, which supports network interaction and can be memory based or persistent.

Redis advantages
Very high performance - Redis can read 110000 times / s and write 81000 times / s.

Rich data types - Redis supports string, lists, hashes, sets and Ordered Sets data type operations of binary cases.

Atom - all operations of Redis are atomic. At the same time, Redis also supports atomic execution after several operations are fully combined.

Rich features - Redis also supports publish/subscribe, notification, key expiration and other features.

How is Redis different from other key value stores?
Redis has a more complex data structure and provides atomic operations on them, which is a different evolution path from other databases. Redis's data types are based on the basic data structure and transparent to programmers without any additional abstraction.

Redis runs in memory but can be persisted to disk, so it needs to balance memory when reading and writing different data sets at high speed, because the amount of data cannot be greater than the hardware memory. Another advantage of in memory database is that compared with the same complex data structure on disk, it is very simple to operate in memory, so redis can do many internal complex things. At the same time, in terms of disk format, they are generated in a compact and additional way, because they do not need random access.

##windows install redis
Here is a brief introduction to the installation of redis on Windows:
You can see this description on the official website:
Windows
The Redis project does not officially support Windows. However, the Microsoft Open Tech group develops and maintains this Windows port targeting Win64



download
Just go to github and download it:
https://github.com/MicrosoftArchive/redis/releases

Here you can download the msi file and the zip file. The difference between them is that the msi file is an installation file. During the installation process, it will help us configure the environment variables, so it is recommended.

Here you need to note that during the installation process, if you change the port number, you must remember:
Figure 1

Start server
After the installation is successful, type the following command through the terminal:

redis-server.exe redis.windows.conf

If everything is OK, the following prompt will appear:
[11368] 13 Jul 10:10:31.487 # Creating Server TCP listening socket 127.0.0.1:6379: bind: No error

Start client
Open a new terminal, start the redis client, and type the command:
 

redis-cli.exe -h 127.0.0.1 -p 6379

Test:

127.0.0.1:6379> set mykey abc
OK
127.0.0.1:6379> get mykey
"abc"

##The use of redigo
github address:
https://github.com/garyburd/redigo

Document address:
http://godoc.org/github.com/garyburd/redigo/redis

obtain:

go get github.com/garyburd/redigo/redis

Connect to redis
 

package main
import (
	"fmt"
	"github.com/garyburd/redigo/redis"
)

func main() {
	c, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("Connect to redis error", err)
		return
	}
	defer c.Close()
}

Reading and writing
The value written here will never expire

package main

import (
	"fmt"

	"github.com/garyburd/redigo/redis"
)

func main() {
	c, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("Connect to redis error", err)
		return
	}
	defer c.Close()

	_, err = c.Do("SET", "mykey", "superWang")
	if err != nil {
		fmt.Println("redis set failed:", err)
	}

	username, err := redis.String(c.Do("GET", "mykey"))
	if err != nil {
		fmt.Println("redis get failed:", err)
	} else {
		fmt.Printf("Get mykey: %v \n", username)
	}
}

How to SET expiration? You can use SET's additional parameters:

package main

import (
	"fmt"
	"time"

	"github.com/garyburd/redigo/redis"
)

func main() {
	c, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("Connect to redis error", err)
		return
	}
	defer c.Close()

	_, err = c.Do("SET", "mykey", "superWang", "EX", "5")
	if err != nil {
		fmt.Println("redis set failed:", err)
	}

	username, err := redis.String(c.Do("GET", "mykey"))
	if err != nil {
		fmt.Println("redis get failed:", err)
	} else {
		fmt.Printf("Get mykey: %v \n", username)
	}

	time.Sleep(8 * time.Second)

	username, err = redis.String(c.Do("GET", "mykey"))
	if err != nil {
		fmt.Println("redis get failed:", err)
	} else {
		fmt.Printf("Get mykey: %v \n", username)
	}
}

Output:
Get mykey: superWang
redis get failed: redigo: nil returned

Bulk write read

MGET key [key ...]
MSET key value [key value ...]

Bulk write read object (Hashtable)
HMSET key field value [field value ...]
HMGET key field [field ...]

Check whether the value exists
EXISTS key
 

package main

import (
	"fmt"

	"github.com/garyburd/redigo/redis"
)

func main() {
	c, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("Connect to redis error", err)
		return
	}
	defer c.Close()

	_, err = c.Do("SET", "mykey", "superWang")
	if err != nil {
		fmt.Println("redis set failed:", err)
	}

	is_key_exit, err := redis.Bool(c.Do("EXISTS", "mykey1"))
	if err != nil {
		fmt.Println("error:", err)
	} else {
		fmt.Printf("exists or not: %v \n", is_key_exit)
	}

}

Output:
exists or not: false

delete
DEL key [key ...]

package main

import (
	"fmt"

	"github.com/garyburd/redigo/redis"
)

func main() {
	c, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("Connect to redis error", err)
		return
	}
	defer c.Close()

	_, err = c.Do("SET", "mykey", "superWang")
	if err != nil {
		fmt.Println("redis set failed:", err)
	}

	username, err := redis.String(c.Do("GET", "mykey"))
	if err != nil {
		fmt.Println("redis get failed:", err)
	} else {
		fmt.Printf("Get mykey: %v \n", username)
	}

	_, err = c.Do("DEL", "mykey")
	if err != nil {
		fmt.Println("redis delelte failed:", err)
	}

	username, err = redis.String(c.Do("GET", "mykey"))
	if err != nil {
		fmt.Println("redis get failed:", err)
	} else {
		fmt.Printf("Get mykey: %v \n", username)
	}
}

Output:
Get mykey: superWang
redis get failed: redigo: nil returned

Read and write json to redis

package main

import (
	"encoding/json"
	"fmt"

	"github.com/garyburd/redigo/redis"
)

func main() {
	c, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("Connect to redis error", err)
		return
	}
	defer c.Close()

	key := "profile"
	imap := map[string]string{"username": "666", "phonenumber": "888"}
	value, _ := json.Marshal(imap)

	n, err := c.Do("SETNX", key, value)
	if err != nil {
		fmt.Println(err)
	}
	if n == int64(1) {
		fmt.Println("success")
	}

	var imapGet map[string]string

	valueGet, err := redis.Bytes(c.Do("GET", key))
	if err != nil {
		fmt.Println(err)
	}

	errShal := json.Unmarshal(valueGet, &imapGet)
	if errShal != nil {
		fmt.Println(err)
	}
	fmt.Println(imapGet["username"])
	fmt.Println(imapGet["phonenumber"])
}

Set expiration time
EXPIRE key seconds

// Set expiration time to 24 hours  
n, _ := rs.Do("EXPIRE", key, 24*3600)  
if n == int64(1) {  
    fmt.Println("success")  
}  

List operation
Command:

redis 127.0.0.1:6379> LPUSH runoobkey redis
(integer) 1
redis 127.0.0.1:6379> LPUSH runoobkey mongodb
(integer) 2
redis 127.0.0.1:6379> LPUSH runoobkey mysql
(integer) 3
redis 127.0.0.1:6379> LRANGE runoobkey 0 10

1) "mysql"
2) "mongodb"
3) "redis"

Code implementation:

 

package main

import (
	"fmt"

	"github.com/garyburd/redigo/redis"
)

func main() {
	c, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println("Connect to redis error", err)
		return
	}
	defer c.Close()

	_, err = c.Do("lpush", "runoobkey", "redis")
	if err != nil {
		fmt.Println("redis set failed:", err)
	}

	_, err = c.Do("lpush", "runoobkey", "mongodb")
	if err != nil {
		fmt.Println("redis set failed:", err)
	}
	_, err = c.Do("lpush", "runoobkey", "mysql")
	if err != nil {
		fmt.Println("redis set failed:", err)
	}

	values, _ := redis.Values(c.Do("lrange", "runoobkey", "0", "100"))

	for _, v := range values {
		fmt.Println(string(v.([]byte)))
	}
}

Output:
mysql
mongodb
redis


The Conduit

The request / response service enables continuous processing of new requests, even if the client is not ready to read the old response. In this way, the client can send multiple commands to the server without waiting for a response, and finally read multiple responses at a time. This is pipelining, which has been widely used for many years. Distance, many POP3 protocol implementations already support this feature, significantly accelerating the process of downloading new mail from the server.
Redis supports pipelining very early, so no matter what version you use, you can use pipelining technology

Connection supports the use of Send(), Flush(), Receive() method to support pipelining operation
 

Send(commandName string, args ...interface{}) error
Flush() error
Receive() (reply interface{}, err error)

Send writes a command to the output buffer of the connection. Flush clears the output buffer of the connection and writes it to the server. Recevie reads the server's responses in FIFO order. The following example shows a simple pipeline:

c.Send("SET", "foo", "bar")
c.Send("GET", "foo")
c.Flush()
c.Receive() // reply from SET
v, err = c.Receive() // reply from GET

The Do method combines the Send,Flush, and Receive methods. The Do method first writes the command, then clears the output buffer, and finally receives all the pending responses including the results of the command issued by the Do party. If any response contains an error, Do returns an error. If there are no errors, the Do method returns the last response.

##Use of open source library go redis / redis
github address:
https://github.com/go-redis/redis

Document address:
https://godoc.org/github.com/go-redis/redis

obtain:

go get -u github.com/go-redis/redis

Application:

package main

import (
	"fmt"

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

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

	pong, err := client.Ping().Result()
	fmt.Println(pong, err)

	err = client.Set("key", "value", 0).Err()
	if err != nil {
		panic(err)
	}

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

	val2, err := client.Get("key2").Result()
	if err == redis.Nil {
		fmt.Println("key2 does not exists")
	} else if err != nil {
		panic(err)
	} else {
		fmt.Println("key2", val2)
	}
}

Output:
PONG
key value
key2 does not exists


Topics: Redis github Windows Database