目录

GO操作Redis

摘要

Golang go-Redis

安装

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

初始化连接

单Redis节点

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package main

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

//创建一个全局的redis客户端实例Rdb
var Rdb *redis.Client

func initRdb()(err error){
	//这里这里不要用 := ,否则只是赋值给了临时变量
	Rdb = redis.NewClient(&redis.Options{
		Addr: "192.168.116.90:6379",
		// 留空为没设密码
		Password: "",
		// 默认的DB 为 0
		DB: 0,
		// 连接池大小
		PoolSize: 100,
	})
	//测试 redis 是否可以连接
	_,err = Rdb.Ping().Result()
	return err
}

func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	defer Rdb.Close()
}

Redis哨兵模式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
//创建一个全局的redis客户端实例Rdb
var Rdb *redis.Client

func initRdb()(err error){
	//这里这里不要用 := ,否则只是赋值给了临时变量
	Rdb = redis.NewFailoverClient(&redis.FailoverOptions{
		MasterName:    "master",
		SentinelAddrs: []string{"192.168.116.90:6379", "192.168.116.90:6380", "192.168.116.90:6381"},
	})
    // 测试 redis 是否可以连接
    _, err = Rdb.Ping().Result()
    return err
}
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	defer Rdb.Close()
}

Redis Cluster集群模式

集群模式的客户端实例与单节点是不一样的 *redis.ClusterClient

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
//创建一个全局的redis客户端实例Rdb
var Rdb *redis.ClusterClient

func initRdb()(err error){
	//这里这里不要用 := ,否则只是赋值给了临时变量
	Rdb = redis.NewClusterClient(&redis.ClusterOptions{
		Addrs: []string{"192.168.110.131:6379","192.168.110.131:6380","192.168.110.131:6381"},
	})
	//测试 redis 是否可以连接
	_,err = Rdb.Ping().Result()
	return err
}
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	defer Rdb.Close()
}

操作

字符串操作

Set 操作的函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
func redisSet(key string,value interface{},expr time.Duration){
	err := Rdb.Set(key,value,expr).Err()
	if err != nil{
		fmt.Printf("redisSet Failed Error %v\n",err)
		return
	}
	fmt.Printf("Redis Set key: [%s] value: [%v] Success\n",key,value)
}

func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	//expr参数代表过期时间,0为永不过期
	redisSet("RedisKey","value1",0)
}

输出:
Connection Redis Client Success!
Redis Set key: [RedisKey] value: [value1] Success

Get 操作的函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
func redisGet(key string)  {
	value ,err := Rdb.Get(key).Result()
	// 首先使用redis.Nil 判断key是否存在
	if err == redis.Nil{
		fmt.Printf("Key: [%s] is Null\n",key)
		//再判断 err != nil
	}else if err != nil {
		fmt.Printf("redisGet key failed error %v\n",err)
	}else{
		fmt.Printf("key: [%s] value:[%v]\n",key,value)
	}
}

func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	//不存在的key
	redisGet("redis")
	//存在的key值
	redisGet("RedisKey")
}
输出:
Connection Redis Client Success!
Key: [redis] is Null
key: [RedisKey] value:[value1]

TTL 获取过期时间

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	//插入键hello,并设置60秒过期
	redisSet("hello","world",60 * time.Second)
	time.Sleep(5 * time.Second)
	//获取过期时间
	tm,_ := Rdb.TTL("hello").Result()
	fmt.Println(tm)
}
输出:
Connection Redis Client Success!
Redis Set key: [hello] value: [world] Success
55s

SetNX 当键不存在的时候才赋值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	err := Rdb.Set("hello1","world1",0).Err()
	if err != nil{
		fmt.Println("set1 failed")
	}
	err = Rdb.SetNX("hello1","world2",0).Err()
	if err != nil{
		fmt.Println("setNx Failed")
	}
	redisGet("hello1")
}
输出
Connection Redis Client Success!
key: [hello1] value:[world1]

Incr 自增

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	//设置一个永不过期变量counter
	Rdb.SetNX("counter",0,0).Result()
	err := Rdb.Incr("counter").Err()
	if err != nil{
		fmt.Println("incr failed")
		return
	}
	redisGet("counter")
}
输出
C:\Users\xx\Desktop\git\sql>go run main.go
Connection Redis Client Success!
key: [counter] value:[1]

C:\Users\xx\Desktop\git\sql>go run main.go
Connection Redis Client Success!
key: [counter] value:[2]

列表

LPush | RPush 添加

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	//从右入栈
	Rdb.RPush("list_test","message").Err()
	Rdb.RPush("list_test","message1").Err()
	//从左入栈
	Rdb.LPush("list_test","message2").Err()
	//查看所有元素 lrange key start end 获取指定范围的元素0(n),谨慎使用
	v,_ :=  Rdb.LRange("list_test",0,-1).Result()
	fmt.Println(v)
}

LSet 更新某个索引的值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	Rdb.LSet("list_test",2,"message set")
	//查看所有元素 lrange key start end 获取指定范围的元素0(n),谨慎使用
	v,_ :=  Rdb.LRange("list_test",0,-1).Result()
	fmt.Println(v)
}

LLen 获取列表长度

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	//查看所有元素 lrange key start end 获取指定范围的元素0(n),谨慎使用
	v,_ :=  Rdb.LRange("list_test",0,-1).Result()
	fmt.Println(v)
	//获取长度
	len,_ := Rdb.LLen("list_test").Result()
	fmt.Println(len)
}

LPop | RPop 出栈 pop 操作,没有阻塞

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	//从左出栈
	Rdb.LPop("list_test").Err()
	//从右出栈
	Rdb.RPop("list_test").Err()
	//查看所有元素 lrange key start end 获取指定范围的元素0(n),谨慎使用
	v,_ :=  Rdb.LRange("list_test",0,-1).Result()
	fmt.Println(v)
	//获取长度
	len,_ := Rdb.LLen("list_test").Result()
	fmt.Println(len)
}

LIndex 获取指定索引的元素值

1
2
3
4
5
6
7
8
9
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	v,_ :=  Rdb.LIndex("list_test",0).Result()
	fmt.Println(v)
}

LInsert 在指定元素的前面或者后面添加新的元素 LInsert [key before | after item newitem]

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	v,_ :=  Rdb.LRange("list_test",0,-1).Result()
	fmt.Println(v)
	//指定在message元素之前添加元素hello
	Rdb.LInsert("list_test","before","message","hello")
	//指定在message元素之后添加元素hello1
	Rdb.LInsert("list_test","after","message","hello1")
	v,_ =  Rdb.LRange("list_test",0,-1).Result()
	fmt.Println(v)
}

输出
Connection Redis Client Success!
[message]
[hello message hello1]

lrem key count value 删除指定个数值为value的元素

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
count = 0 删除所有值为value的元素
count > 0 :从左到右删除count个值为value的元素
count < 0 :从右到左删除count个值为value的元素
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	v,_ :=  Rdb.LRange("list_test",0,-1).Result()
	fmt.Println(v)
	Rdb.LRem("list_test",0,"message")
	v,_ =  Rdb.LRange("list_test",0,-1).Result()
	fmt.Println(v)
}
输出:
Connection Redis Client Success!
[hello message hello1]
[hello hello1]

ltrim key start end 保留指定范围的元素

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	v,_ :=  Rdb.LRange("list_test",0,-1).Result()
	fmt.Println(v)
	//只保留索引为0-4的键值,注意收尾都包括,也就是索引0和索引4都包括在内
	Rdb.LTrim("list_test",0,4)
	v,_ =  Rdb.LRange("list_test",0,-1).Result()
	fmt.Println(v)
}
输出:
Connection Redis Client Success!
[hello 0 4 3 2 1]
[hello 0 4 3 2]

Hash

HMSet 添加

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	datas := map[string]interface{}{
		"name": "xxx",
		"sex": 1,
		"age": 22,
		"tel": "123456789111",
	}
	Rdb.HMSet("hash_test",datas)
}

HMGet 获取对应键內指定字段的值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()

	ret,_ := Rdb.HMGet("hash_test","name","sex","age","tel").Result()
	fmt.Println(ret)
}
输出:
Connection Redis Client Success!
[xxx 1 22 123456789111]

HSet 设置对应键內某个字段的值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.HMGet("hash_test","name","sex","age","tel").Result()
	fmt.Println(ret)
	Rdb.HSet("hash_test","age",33)
	ret,_ = Rdb.HMGet("hash_test","name","sex","age","tel").Result()
	fmt.Println(ret)
}
输出:
Connection Redis Client Success!
[xxx 1 22 123456789111]
[xxx 1 33 123456789111]

HGet 获取对应键某个字段的值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret, _ := Rdb.HGet("hash_test","name").Result()
	fmt.Println(ret)
}
输出:
Connection Redis Client Success!
xxx

HSetNX 用于设置键內不存在key的值,如果key存在,不会设置成功

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.HMGet("hash_test","name","sex","age","tel").Result()
	fmt.Println(ret)
	Rdb.HSetNX("hash_test","age",44)
	ret,_ = Rdb.HMGet("hash_test","name","sex","age","tel").Result()
	fmt.Println(ret)
}
输出:
Connection Redis Client Success!
[xxx 1 33 123456789111]
[xxx 1 33 123456789111]

HGetAll 获取指定key对应的hash对象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func main()  {
   if err := initRdb();err != nil{
      panic(err)
   }
   fmt.Println("Connection Redis Client Success!")
   defer Rdb.Close()
   ret, _ := Rdb.HGetAll("hash_test").Result()
   fmt.Println(ret)
}
输出:
Connection Redis Client Success!
map[age:33 name:xxx sex:1 tel:123456789111]

HDel 删除指定键对应的hash对象的某个字段

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret, _ := Rdb.HGetAll("hash_test").Result()
	fmt.Println(ret)
	Rdb.HDel("hash_test","sex")
	ret, _ = Rdb.HGetAll("hash_test").Result()
	fmt.Println(ret)
}
输出:
Connection Redis Client Success!
map[age:33 name:xxx sex:1 tel:123456789111]
map[age:33 name:xxx tel:123456789111]

HExists 判断指定键对应的hash对象是否有某个字段

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.HExists("hash_test","name").Result()
	fmt.Println(ret)
	ret,_ = Rdb.HExists("hash_test","name1").Result()
	fmt.Println(ret)
}
输出:
Connection Redis Client Success!
true
false

HLen 获取指定键对应hash对象的字段个数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.HLen("hash_test").Result()
	fmt.Println(ret)
}
输出:
Connection Redis Client Success!
3

HVals 获取指定键对应的hash对象所有的value值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.HVals("hash_test").Result()
	fmt.Println(ret)
}
输出:
Connection Redis Client Success!
[xxx 33 123456789111]

HKeys 获取指定键对应的hash对象所有的key值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.HKeys("hash_test").Result()
	fmt.Println(ret)
}
输出:
Connection Redis Client Success!
[name age tel]

HIncrBy key field increValue 增加某个key的value值,increValue表示增加多少,这个值可以为负数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.HGetAll("hash_test").Result()
	fmt.Println(ret)
	Rdb.HIncrBy("hash_test","age",10)
	ret,_ = Rdb.HGetAll("hash_test").Result()
	fmt.Println(ret)
	Rdb.HIncrBy("hash_test","age",-20)
	ret,_ = Rdb.HGetAll("hash_test").Result()
	fmt.Println(ret)
}
输出:
Connection Redis Client Success!
map[age:43 name:xxx tel:123456789111]
map[age:53 name:xxx tel:123456789111]
map[age:33 name:xxx tel:123456789111]

set集合

SAdd 添加

1
2
3
4
5
6
7
8
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	Rdb.SAdd("set_test",11,22,33,44).Result()
}

SRem 删除集合中对应的元素

1
2
3
4
5
6
7
8
9
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	Rdb.SRem("set_test",22,44)
}

SMembers 获取集合中所有的元素

1
2
3
4
5
6
7
8
9
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.SMembers("set_test").Result()
	fmt.Println(ret)
}

SIsMember 判断集合内是否有指定元素

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.SIsMember("set_test",22).Result()
	fmt.Println(ret)
	ret,_ = Rdb.SIsMember("set_test",33).Result()
	fmt.Println(ret)
}

SRandMember 随机获取集合内的一个元素

1
2
3
4
5
6
7
8
9
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.SRandMember("set_test").Result()
	fmt.Println(ret)
}

SRandMemberN 随机获取集群内的n个元素

1
2
3
4
5
6
7
8
9
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.SRandMemberN("set_test",2).Result()
	fmt.Println(ret)
}

SPop从集合中随机弹出元素(会破坏结构)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.SMembers("set_test").Result()
	fmt.Println(ret)
	Rdb.SPop("set_test")
	ret,_ = Rdb.SMembers("set_test").Result()
	fmt.Println(ret)
}
输出
[11 22 33 44]
[11 33 44]

SCard 获取集合内元素的个数

1
2
3
4
5
6
7
8
9
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.SCard("set_test").Result()
	fmt.Println(ret)
}

SInter 获取所有集合的交集

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.SMembers("set_test").Result()
	fmt.Println(ret)
	Rdb.SAdd("set_test1",22,44,55,77)
	ret,_ = Rdb.SInter("set_test","set_test1").Result()
	fmt.Println(ret)
}
输出:
Connection Redis Client Success!
[11 33 44]
[44]

SDiff 获取所有集合的差集

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.SMembers("set_test").Result()
	fmt.Println(ret)
	ret,_ = Rdb.SMembers("set_test1").Result()
	fmt.Println(ret)
	ret,_ = Rdb.SDiff("set_test","set_test1").Result()
	fmt.Println(ret)
}
输出:
Connection Redis Client Success!
[11 33 44]
[22 44 55 77]
[11 33]

SUnion 获取所有集合的并集

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	ret,_ := Rdb.SMembers("set_test").Result()
	fmt.Println(ret)
	ret,_ = Rdb.SMembers("set_test1").Result()
	fmt.Println(ret)
	ret,_ = Rdb.SUnion("set_test","set_test1").Result()
	fmt.Println(ret)
}
输出
Connection Redis Client Success!
[11 33 44]
[22 44 55 77]
[11 22 33 44 55 77]

Redis Pipeline

Pipeline管道技术,指的是客户端允许将多个请求一次发给服务器,过程中而不需要等待请求的回复,在最后再一并读取结果即可

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	pipe := Rdb.Pipeline()
	pipe.Set("key1","value1",0)
	pipe.Set("key2","value2",0)
	pipe.Set("key3","value3",0)
	pipe.Set("key4","value4",0)
	pipe.Get("key1")
	cmder,err := pipe.Exec()
	if err != nil{
		fmt.Printf("pipeline exec failed err %v\n",err)
		return
	}
	for _,cmd := range cmder{
		fmt.Printf("Pipe Exec: [%v]\n",cmd)
	}
}
输出:
Connection Redis Client Success!
Pipe Exec: [set key1 value1: OK]
Pipe Exec: [set key2 value2: OK]
Pipe Exec: [set key3 value3: OK]
Pipe Exec: [set key4 value4: OK]
Pipe Exec: [get key1: value1]

Redis事务操作

TXPipeline

  • Redis是单线程,因此单个命令始终是原子的,但是来自不同客户端的两个命令可以依次执行,但是Multi/exec能够确保在Multi/exec两个语句之间的命令没有其他客户端正在执行命令。基于这样的场景下我们需要使用TxPipeline来解决
  • TxPipeline类似于Pipeline的方式,不过TxPipeline内部会使用Multi/exec封装排列的命令
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	pipe := Rdb.TxPipeline()
	pipe.Set("key1","value1",0)
	pipe.Set("key2","value2",0)
	pipe.Set("key3","value3",0)
	pipe.Set("key4","value4",0)
	pipe.Get("key1")
	cmder,err := pipe.Exec()
	if err != nil{
		fmt.Printf("pipeline exec failed err %v\n",err)
		return
	}
	for _,cmd := range cmder{
		fmt.Printf("Pipe Exec: [%v]\n",cmd)
	}
}
输出
Connection Redis Client Success!
Pipe Exec: [set key1 value1: OK]
Pipe Exec: [set key2 value2: OK]
Pipe Exec: [set key3 value3: OK]
Pipe Exec: [set key4 value4: OK]
Pipe Exec: [get key1: value1]

WATCH

  • 某些场景下,我们除了要使用Multi/Exec命令之外,还需要配合WATCH命令使用
  • 如: 在使用 WATCH 命令监视某个键之后, 直到执行 Exec 命令的这段时间内, 如果有其他用户抢先对被监视的键进行了替换、更新、删除等操作, 那么当用户尝试执行Exec 的时候, 事务将返回一个错误, 用户可以根据这个错误选择重试事务或者放弃事务。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func main()  {
	if err := initRdb();err != nil{
		panic(err)
	}
	fmt.Println("Connection Redis Client Success!")
	defer Rdb.Close()
	key := "watch_count"
	err := Rdb.Watch(func(tx *redis.Tx) error {
		n,err := tx.Get(key).Int()
		if err != nil && err != redis.Nil{
			return err
		}
		_,err = tx.Pipelined(func(pipe redis.Pipeliner) error{
			pipe.Set(key,n+1,0)
			return nil
		})
		return err
	},key)
	if err != nil{
		fmt.Printf("WATCH failed error %v\n",err)
		return
	}
	fmt.Printf("Watch get watch_count: %v\n",Rdb.Get(key).Val())
}