Redis資料庫4:Go與Redis的互動

尹成發表於2018-11-16

1. Redis簡介
Redis是一個開源的、使用C語言編寫的、支援網路互動的、可基於記憶體也可持久化的Key-Value資料庫。

特點

  • 支援更多資料型別

和Memcached類似,它支援儲存的value型別相對更多,包括string(字串)、list(連結串列)、set(集合)、zset(sorted set 有序集合)和hash(雜湊型別)。

  • 支援複雜操作

這些資料型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,Redis支援各種不同方式的排序。

  • 支援主從同步。

與memcached一樣,為了保證效率,資料都是快取在記憶體中。區別的是Redis會週期性的把更新的資料寫入磁碟或者把修改操作寫入追加的記錄檔案,並且在此基礎上實現了master-slave(主從)同步。資料可以從主伺服器向任意數量的從伺服器上同步,從伺服器可以是關聯其他從伺服器的主伺服器。這使得Redis可執行單層樹複製。從盤可以有意無意的對資料進行寫操作。由於完全實現了釋出/訂閱機制,使得從資料庫在任何地方同步樹時,可訂閱一個頻道並接收主伺服器完整的訊息釋出記錄。同步對讀取操作的可擴充套件性和資料冗餘很有幫助。

Redis的出現,很大程度補償了memcached這類key/value儲存的不足,在部 分場合可以對關聯式資料庫起到很好的補充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客戶端,使用很方便。Redis的官網地址,非常好記,是redis.io。目前,Vmware在資助著Redis專案的開發和維護。
匯入包

import (
	"fmt"
	"github.com/garyburd/redigo/redis"
	"strconv"
	"sync"
	"time"
)

連線資料庫

func main11() {

	//連線本地redis
	conn, err := redis.Dial("tcp", "localhost:6379")
	if err != nil {
		fmt.Println("conn redis failed,", err)
		return
	}
	fmt.Println("connect ok!")

	//關閉連線
	defer conn.Close()
}

鍵值對操作set,get

func main12() {
	//連線本地redis
	conn, err := redis.Dial("tcp", "localhost:6379")
	if err != nil {
		fmt.Println("conn redis failed,", err)
		return
	}

	//延時關閉redis連線
	defer conn.Close()

	//設定鍵值abc=100,等同set abc 100
	reply, err := conn.Do("Set", "abc", 100)
	fmt.Printf("reply=%#v,err=%v\n", reply, err)
	if err != nil {
		fmt.Println(err)
		return
	}

	//執行get abc,將結果轉化為int
	reply, err = conn.Do("Get", "abc")
	fmt.Printf("reply=%#v,err=%v\n", reply, err)
	r, err := redis.Int(reply, err)
	if err != nil {
		fmt.Println("get abc failed,", err)
		return
	}

	//列印結果100
	fmt.Println(r)
}

批量存取mset和mget

func main13() {

	//連線本地redis
	conn, err := redis.Dial("tcp", "localhost:6379")
	if err != nil {
		fmt.Println("conn redis failed,", err)
		return
	}

	//延時關閉連線
	defer conn.Close()

	//存入兩個鍵值
	cdoReply, err := conn.Do("MSet", "abc", 100, "efg", 300)
	fmt.Printf("reply=%#v,err=%v\n", cdoReply, err)
	if err != nil {
		fmt.Println(err)
		return
	}
	//cdoReply= OK
	fmt.Println("cdoReply=", cdoReply)

	//獲取存入的鍵值
	cdoReply, err = conn.Do("MGet", "abc", "efg")
	fmt.Printf("reply=%#v,err=%v\n", cdoReply, err)
	retInts, err := redis.Ints(conn.Do("MGet", "abc", "efg"))
	if err != nil {
		fmt.Println("get abc failed,", err)
		return
	}

	//列印獲取到的結果
	for i, v := range retInts {
		fmt.Println(i, "=", v)
	}

}

設定資料過期時間

func main14() {

	//連線本地redis
	c, err := redis.Dial("tcp", "localhost:6379")
	if err != nil {
		fmt.Println("conn redis failed,", err)
		return
	}

	//延時關閉
	defer c.Close()

	//設定abc過期
	cdoReply, err := c.Do("expire", "abc", 1000)
	fmt.Printf("reply=%#v,err=%v\n", cdoReply, err)
	if err != nil {
		fmt.Println(err)
		return
	} else {
		fmt.Println(cdoReply)
		fmt.Println("abc將於1000秒後過期!")
	}

}

雜湊(物件)操作

func main15() {

	//連線本地redis
	conn, err := redis.Dial("tcp", "localhost:6379")
	if err != nil {
		fmt.Println("conn redis failed,", err)
		return
	}

	//延時關閉
	defer conn.Close()

	//設定books下的鍵值:abc=100
	_, err = conn.Do("HSet", "books", "price", 56.78)
	if err != nil {
		fmt.Println(err)
		return
	}

	//獲取books下的鍵值abc,並轉化為int
	//hget books abc
	r, err := redis.Float64(conn.Do("HGet", "books", "price"))
	if err != nil {
		fmt.Println("get abc failed,", err)
		return
	}

	//列印結果
	fmt.Println(r)
}

list相關操作

func main16() {
	//連線本地redis
	c, err := redis.Dial("tcp", "localhost:6379")
	if err != nil {
		fmt.Println("conn redis failed,", err)
		return
	}

	//延時關閉
	defer c.Close()

	//向一個鍵為books_list的列表中追加3個元素
	//lpush book_list abc ceg 300
	_, err = c.Do("lpush", "book_list", "abc", "ceg", 300)
	if err != nil {
		fmt.Println(err)
		return
	}

	//彈出books_list中最左側的元素:300,轉化為字串
	//lpop book_list
	r, err := redis.String(c.Do("lpop", "book_list"))
	if err != nil {
		fmt.Println("get abc failed,", err)
		return
	}

	//輸出結果
	fmt.Println(r)
}

sort-set相關操作

func main17() {
	conn, e := redis.Dial("tcp", "localhost:6379")
	if e != nil {
		fmt.Println("e=", e)
		return
	}
	defer conn.Close()

	reply, err := conn.Do("zadd", "gozset", 10, "bill", 5, "jack", 7, "jobs")
	fmt.Printf("reply=%#v,err=%v\n", reply, err)
}

複雜命令舉例:zset求交集

func main18() {
	conn, e := redis.Dial("tcp", "localhost:6379")
	if e != nil {
		fmt.Println("e=", e)
		return
	}
	defer conn.Close()

	reply, err := conn.Do("zadd", "comezset", 10, "bill", 5, "jack", 7, "mark")
	fmt.Printf("reply=%#v,err=%v\n", reply, err)

	reply, err = conn.Do("ZINTERSTORE", "interZset", 2, "gozset", "comezset")
	fmt.Printf("reply=%#v,err=%v\n", reply, err)
}

連線池

var wg sync.WaitGroup
func ConnSetName(pool *redis.Pool, i int) {
	conn := pool.Get()
	defer conn.Close()
	reply, _ := conn.Do("set", "name"+strconv.Itoa(i), "123")
	fmt.Printf("conn=%v reply=%v\n", conn, reply)
	<-time.After(3 * time.Second)
	wg.Done()
}

func main() {

	//定義redis連線池指標poot
	//var pool *redis.Pool

	//新建連線池物件,指標丟給pool
	pool := &redis.Pool{
		//最大閒置連線數
		MaxIdle: 16,

		//最大活動連線數,0=無限
		MaxActive: 0,

		//閒置超時時間:300秒,超時自動斷開連線
		IdleTimeout: 300,

		//連線函式
		Dial: func() (redis.Conn, error) {
			//返回連線物件(或錯誤資訊)
			return redis.Dial("tcp", "localhost:6379")
		},
	}
	defer pool.Close()

	for i := 0; i < 50; i++ {
		wg.Add(1)
		go ConnSetName(pool, i)
	}
	wg.Wait()
}

學院Go語言視訊主頁
https://edu.csdn.net/lecturer/1928

[清華團隊帶你實戰區塊鏈開發]
(https://ke.qq.com/course/344443?tuin=3d17195d)
掃碼獲取海量視訊及原始碼 QQ群:721929980
在這裡插入圖片描述

相關文章