天天看點

go語言系列-redis

Redis的使用

Redis 基本介紹

  1. Redis是NoSQL資料庫,不是傳統的關系型資料庫 官網: https://redis.io/ 和 http://www.redis.cn/
  2. Redis:REmote DIctionary Server(遠端字典伺服器),Redis性能非常高,單機能夠達到15w qps,通常适合做緩存,也可以持久化。
  3. 是完全開源免費的,高性能的(key/value)分布式記憶體資料庫,基于記憶體運作并支援持久化的NoSQL資料庫,是最熱門的NoSq|資料庫之一也稱為資料結構伺服器

Redis的安裝

連結:https://pan.baidu.com/s/1QTYTKepSGZA93KCA76eatQ

提取碼:au10

下載下傳後直接解壓就有Redis的伺服器端程式(redis- server.exe)和用戶端程式(redis-cli.exe),直接輕按兩下即可運作,并不需要安裝。

Redis 操作的基本原理圖

go語言系列-redis

Redis的安裝和基本使用

Redis的啟動

go語言系列-redis

啟動Redis的伺服器端程式(redis-server.exe),直接輕按兩下即可運作

go語言系列-redis

Redis的操作指令一覽

go語言系列-redis

Redis的基本使用

說明:Redis安裝好後,預設有16個資料庫,初始預設使用0号庫,編号..15

  1. 添加key-val [set]
  2. 檢視目前redis的所有key [keys *]
  3. 擷取key對應的值. [get key]
  4. 切換redis資料庫[select index]
  5. 如何檢視目前資料庫的key-val數量[dbsize]
  6. 清空目前資料庫的key-val和清空所有資料庫的key-val [fiushdb flushall]
    go語言系列-redis

Redis的Crud操作

Redis的五大資料類型

Redis的五大資料類型是: String(字元串)、Hash (哈希)、List(清單)、Set(集 合)和zset(sorted set:有序集合)

String(字元串) -介紹

string是redis最基本的類型,一個key對應一個value.

string類型是二進制安全的。除普通的字元串外,也可以存放圖檔等資料。

redis中字元串value最大是512M

舉例,存放一個位址資訊:

address 北京天安門

說明:

key : address

value:北京天安門

127.0.0.1:6379> set address beijing
OK
127.0.0.1:6379> get address
"beijing"
           

String(字元串)-CRUD

舉例說明Redis的String 字元串的CRUD操作.

set[如果存在就相當于修改,不存在就是添加]/get/del

127.0.0.1:6379> del address
(integer) 1
127.0.0.1:6379> get address
(nil)
           

String(字元串)-使用細節和注意事項

setex(set with expire)鍵秒值

127.0.0.1:6379> SETEX mess01 10 hello,you
OK
127.0.0.1:6379> get mess01
"hello,you"
127.0.0.1:6379> get mess01
"hello,you"
127.0.0.1:6379> get mess01
(nil)
           

mset[同時設定一個或多個key-value 對]

mget[同時擷取多個key-val]

127.0.0.1:6379> MSET worker01 tom worker02 scott
OK
127.0.0.1:6379> get worker02
"scott"
127.0.0.1:6379> MGET worker01 worker02
1) "tom"
2) "scott"
           

Hash (哈希,類似golang裡的Map)-介紹

基本的介紹

Redis hash是一個鍵值對集合。var user1 map[string]string

Redis hash是一個string類型的field和value的映射表,hash特别适合用于存儲對象。

舉例,存放一個User資訊:(user1)

userl name "smith" age 30 job "golang coder"

key : userl

name張三 和age 30 就是兩對field-value

go語言系列-redis

Hash (哈希,類似golang裡的Map) -CRUD

舉例說明Redis的Hash 的CRUD的基本操作.

hset/hget/hgetall/hdel

示範添加user資訊的案例(name,age )

127.0.0.1:6379> HGETALL user1
1) "name"
2) "smith"
3) "age"
4) "30"
5) "job"
6) "golang coder"
           

Hash-使用細節和注意事項

在給user設定name和age時,前面我們是一一步-一步設定,使用hmset和hmget 可以一次性來設定多個filed 的值和傳回多個field 的值。

hlen 統計一個hash有幾個元素

hexists key field 檢視哈希表key中,給定域field是否存在

127.0.0.1:6379> hmset user2 name jerry age 110 job "java coder"
OK
127.0.0.1:6379> hmget user2 name age job
1) "jerry"
2) "110"
3) "java coder"
127.0.0.1:6379> hlen user2
(integer) 3
127.0.0.1:6379> HEXISTS user2 name
(integer) 1
127.0.0.1:6379> hexists user2 name2
(integer) 0
           

Hash練習

舉例,存放一個Student資訊:

stu1 name張三age 30 score 80 address北京

說明:

通過相關指令,完成對Student的crud操作

List(清單) - 介紹

清單是簡單的字元串清單,按照插入順序排序。你可以添加一個元素到清單的頭部(左邊)或者尾部(右邊)。

List本質是個連結清單,List的元素是有序的,元素的值可以重複.

舉例 存放多個位址資訊:

city 北京 天津 上海

key:city

北京 天津 上海 就是三個元素

入門案例

127.0.0.1:6379> LPUSH city berjing shanghai tianjing
(integer) 3
127.0.0.1:6379> lrange city 0 -1
1) "tianjing"
2) "shanghai"
3) "berjing"
           

List (清單) -CRUD

舉例說明Redis的List的CRUD操作。

lpush/rpush/lrange/lpop/rpop/del/

說明

List畫圖幫助了解(可以把List想象成一根管道)

go語言系列-redis

herolist的示範

127.0.0.1:6379> lpush herolist aaa bbb ccc
(integer) 3
127.0.0.1:6379> LRANGE herolist 0 -1
1) "ccc"
2) "bbb"
3) "aaa"
127.0.0.1:6379> rpush herolist ddd eee
(integer) 5
127.0.0.1:6379> lrange herolist 0 -1
1) "ccc"
2) "bbb"
3) "aaa"
4) "ddd"
5) "eee"
127.0.0.1:6379>  rpop herolist
"eee"
127.0.0.1:6379> lrange herolist 0 -1
1) "ccc"
2) "bbb"
3) "aaa"
4) "ddd"
127.0.0.1:6379> del herolist
(integer) 1
127.0.0.1:6379> lrange herolist 0 -1
(empty list or set)
           

List-使用細節和注意事項

(1) lindex,按照索引下标獲得元素(從左到右,編号從0開始.)

(2) LLEN key

傳回清單key的長度,如果key不存在,則key被解釋為一個空清單,傳回0

(3) List的其它說明

​ List資料,可以從左或者右插入添加;

​ 如果值全移除,對應的鍵也就消失了。

Set(集合) - 介紹

Redis 的Set是string類型的無序集合。

底層是 HashTable資料結構,Set也是存放很多字元串元素,字元串元素是無序的,而且元素的值不能重複

舉例,存放多個郵件清單資訊:

email [email protected] [email protected]

key : email

[email protected] [email protected]就是二個元素

127.0.0.1:6379> sadd emails [email protected] [email protected]
(integer) 2
127.0.0.1:6379> SMEMBERS emails
1) "[email protected]"
2) "[email protected]"
127.0.0.1:6379> sadd emails [email protected] [email protected]
(integer) 2
127.0.0.1:6379> SMEMBERS emails
1) "[email protected]"
2) "[email protected]"
3) "[email protected]"
4) "[email protected]"
127.0.0.1:6379> sadd emails [email protected] 
(integer) 0
127.0.0.1:6379> SMEMBERS emails
1) "[email protected]"
2) "[email protected]"
3) "[email protected]"
4) "[email protected]"
           

Set(集合) - CRUD

舉例說明Redis的Set 的CRUD操作.

sadd

smembers[取出所有值]

sismember[判斷值是否是成員]

srem [删除指定值]

示範添加多個電子郵件資訊的案例

127.0.0.1:6379> SISMEMBER emails [email protected]
(integer) 1
127.0.0.1:6379> SISMEMBER emails [email protected]
(integer) 0
127.0.0.1:6379> srem emails [email protected]
(integer) 1
127.0.0.1:6379> SMEMBERS emails
1) "[email protected]"
2) "[email protected]"
3) "[email protected]"
           

Set練習

舉例,存放一個商品資訊:

包括商品名、價格、生産日期。

完成對應的crud操作

Golang操作Redis

安裝第三方開源Redis庫

1)使用第三方開源的redis庫: github.com/garyburd/redigo/redis

2)在使用Redis前,先安裝第三方Redis庫,在GOPATH路徑下執行安裝指令:

​ E:\gostudent>go get github.com/garyburd/redigo/redis

3)安裝成功後,可以看到如下包

go語言系列-redis

特别說明:在安裝Redis庫前,確定已經安裝并配置了Git, 因為是從github下載下傳安裝Redis庫的,需要使用到Git。

E:\gostudent>go get github.com/garyburd/redigo/redis
\# cd .; git clone -- https://github.com/garyburd/redigo E:\gostudent\src\github.com\garyburd\redigo
Cloning into 'E:\gostudent\src\github.com\garyburd\redigo'...
fatal: unable to access 'https://github.com/garyburd/redigo/': Failed to connect to github.com port 443: Timed out
package github.com/garyburd/redigo/redis: exit status 128
           

多執行幾次就好了 原因大家都懂

Set/Get接口

說明:通過Golang添加和擷取key-value 【比如name-tom~】

package main

import (
  "fmt"
  "github.com/garyburd/redigo/redis"  //引入redis包
)

func main() {
  //通過go向redis寫入資料和讀取資料
  //1. 連結到redis
  conn, err := redis.Dial("tcp", "127.0.0.1:6379")
  if err != nil {
   fmt.Println("redis.Dial err =", err)
   return
  }
  defer conn.Close() //關閉...

  //2. 通過go向redis寫入資料strinf [key-val]
  _, err = conn.Do("Set", "name","tomjerry 貓貓")
  if err != nil {
   fmt.Println("set err = ", err)
   return
  }
  
  //3. 通過go 向redis讀取資料string [key-val]
  r, err := redis.String(conn.Do("Get","name"))
  if err != nil {
   fmt.Println("set err = ", err)
   return
  }
  //因為傳回r是interface{}
  //因為name對應的值是string ,是以我們需要轉換
  //nameString := r.(string)
  fmt.Println("操作OK", r)
}
//操作OK tomjerry 貓貓
           

操作Hash

說明: 通過Golang對Redis操作Hash資料類型

對hash資料結構,field-val 是一個一個放入和讀取

代碼:

import (
  "fmt"
  "github.com/garyburd/redigo/redis"  //引入redis包
)

func main() {
  //通過go向redis寫入資料和讀取資料
  //1. 連結到redis
  conn, err := redis.Dial("tcp", "127.0.0.1:6379")
  if err != nil {
   fmt.Println("redis.Dial err =", err)
   return
  }
  defer conn.Close() //關閉...

  //2. 通過go向redis寫入資料string [key - val]
  _,err = conn.Do("HSet","user01","name","john")
  if err != nil {
   fmt.Println("hset err = ", err)
   return
  }
  _, err = conn.Do("HSet","user01","age",18)
  if err != nil {
   fmt.Println("hset err =", err)
   return
  }

  //3. 通過go向redis讀取資料
  r, err := redis.String(conn.Do("HGet","user01","name"))
  if err != nil {
   fmt.Println("hget err = ", err)
   return
  }

  r2, err := redis.Int(conn.Do("HGet","user01","age"))
  if err != nil{
   fmt.Println("hget err =", err)
   return
  }

  //因為傳回r是interface{}
  //因為name對應的值是string,是以需要轉換
  //nameString := r.(string)

  fmt.Printf("操作ok r1 = %v r2 = %v\n", r, r2)

}
//操作ok r1 = john r2 = 18

對hash資料結構,field-val是批量放入和讀取

import (
  "fmt"
  "github.com/garyburd/redigo/redis"  //引入redis包
)

func main() {
  //通過go向redis寫入資料和讀取資料
  //1. 連結到redis
  conn, err := redis.Dial("tcp", "127.0.0.1:6379")
  if err != nil {
   fmt.Println("redis.Dial err =", err)
   return
  }
  defer conn.Close() //關閉...

  //2. 通過go向redis寫入資料string [key - val]
  _,err = conn.Do("HMSet","user02","name","john","age",19)
  if err != nil {
   fmt.Println("HMSet err = ", err)
   return
  }

  //3. 通過go向redis讀取資料
  r, err := redis.Strings(conn.Do("HMGet","user02","name","age"))
  if err != nil {
   fmt.Println("HMGet err = ", err)
   return
  }
  for i, v := range r {
   fmt.Printf("r[%d] = %s\n", i, v)
  }
}
//r[0] = john
//r[1] = 19
           

批量Set/Get資料

說明:通過Golang對Redis操作,一次操作可以Set/Get多個key-val資料

核心代碼:

_, err = c.Do("MSet", "name",”zisefeizhu","address", "中國")
r, err := redis.Strings(c.Do("MGet", 'name", " address"))
for. ,V := range r {
	fmt.Println(v)
}
           

給資料設定有效時間

說明: 通過Golang對Redis操作,給key-value設定有效時間

//給name資料設定有效時間為10s

_,err = c.Do("expire", "name", 10)

操作List

說明: 通過Golang對Redis操作List 資料類型

_, err = c.Do("lpush", "heroList", "no1:宋江",30, "no2:盧俊義", 28)
r, err := redis.String(c.Do("rpop", "heroList"))
           

Redis連結池

說明:通過Golang對Redis操作,還可 以通過Redis連結池,流程如下:

​ 1) 事先初始化一定數量的連結,放入到連結池

​ 2) 當Go需要操作Redis時,*直接從Redis連結池取對外連結接*即可。

​ 3) 這樣可以節省臨時*擷取Redis連結*的時間,進而提高效率.

​ 4) 示意圖

go語言系列-redis

*連結池使用案例*

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

//定義一個全局的pool
var pool *redis.Pool

//當啟動程式時,就初始化連結池
func init()  {
  pool = &redis.Pool{
   Dial: func() (redis.Conn, error) {  //初始化連結的代碼,連結哪個ip的redis
     return redis.Dial("tcp","localhost:6379")
   },
   MaxIdle:     8,  //最大空閑連結數
   MaxActive:    0,  //表示和資料庫的最大連結數,0 表示沒有限制
   IdleTimeout:   100,  //最大空閑時間
  }
}

func main()  {
  //先從Pool取出一個連結
  conn := pool.Get()
  defer conn.Close()

  _, err := conn.Do("Set","name","湯姆貓~")
  if err != nil {
   fmt.Println("conn.Do err=", err)
   return
  }

  //取出
  r, err := redis.String(conn.Do("Get","name"))
  if err != nil {
   fmt.Println("conn.Do err =", err)
   return
  }

  fmt.Println("r =", r)

  //如果要從pool 取對外連結接,一定要保證連結池是沒有關閉
  // pool.Close()
  conn2 := pool.Get()

  _, err = conn2.Do("Set", "name2", "湯姆貓~2")
  if err != nil {
   fmt.Println("conn.Do err ~~=", err)
   return
  }

  //取出
  r2, err := redis.String(conn2.Do("Get","name2"))
  if err != nil {
   fmt.Println("conn.Do err =", err)
   return
  }

  fmt.Println("r =", r2)

  //fmt.Println("conn2 =", conn2)
}
//r = 湯姆貓~
//r = 湯姆貓~2

再來一例

var pool *redis.Pool

func init() {
  pool = &redis.Pool{
   MaxIdle:   8,
   MaxActive:  0,
   IdleTimeout: 100,
   Dial: func() (redis.Conn, error) {
     return redis.Dial("tcp", "localhost:6379")
   },
  }
}

func main() {
  conn := pool.Get()
  defer conn.Close()

  _, err1 := conn.Do("HMSet", "user1", "name", "beijing", "address", "beijing")
  if err1 != nil {
   fmt.Println("HMSet err=", err1)
   return
  }
  _, err3 := conn.Do("HMSet", "user2", "name", "wuhan", "address", "wuhan")
  if err3 != nil {
   fmt.Println("HMSet err=", err3)
   return
  }

  //向redis讀取資料,傳回的r是個空接口
  r, err2 := redis.Strings(conn.Do("HMGet", "user1", "name", "address"))
  if err2 != nil {
   fmt.Println("HMGet err=", err2)
   return
  }
  for i, v := range r {
   fmt.Printf("r[%d]=%v\n", i, v)
  }
}
//r[0]=beijing
//r[1]=beijing
           

過手如登山,一步一重天