redis-----08-----redigo管道以及事务-管道

1 Redis 管道

在这里插入图片描述
正常的情况下,redis是请求响应模式,一条请求后那么正常就会返回一个响应,例如上图。但是只存在这种情况是无法满足我们开发的需求的。所以redis给我们提供了管道。

redis的管道(pipeline )相关特点:

  • 1)redis的管道pipeline配合事务,可以实现原子操作,保证一次执行多条命令。注意:管道本身不具有原子操作,只是单纯提高传输性能,而原子操作还是由事务和lua脚本实现。
  • 2)它一次可以发送多次请求,然后返回多个响应,这个响应的顺序会依照你请求的顺序进行返回。
  • 3)管道作用:一次可以发送多条请求,并可以一次返回多个响应,例如下图,所以节省大量的网络耗时,减少与redis的交互,主要体现在TCP三次握手与四次挥手。如果将多个请求拆开,势必会效率大打折扣。
  • 4)redis pipeline 是一个由客户端提供的,而不是服务端提供的。
    在这里插入图片描述

下面我们来看一下redigo提供了哪些接口给我们。

type Conn interface { 
	// Close closes the connection. 
	Close() error 
	
	// Err returns a non-nil value when the connection is not usable. 
	Err() error 
	
	// Do sends a command to the server and returns the received reply. 
	Do(commandName string, args ...interface{}) (reply interface{}, err error)
	
	// Do = Send + Flush + Receive 
	
	// Send writes the command to the client's output buffer. 
	Send(commandName string, args ...interface{}) error 
	
	// Flush flushes the output buffer to the Redis server. 
	Flush() error 
	
	// Receive receives a single reply from the Redis server 
	Receive() (reply interface{}, err error) 
}

重点讲解Do和Send、Flush、Receive的关系。

  • 1)Do等价于执行了一次Send、Flush、Receive。
  • 2)Send函数代表往redigo的缓冲区发送消息,相当于写到缓冲区,此时并未发送到redis服务器。
  • 3)Flush函数代表真正的将redigo的缓冲区的内容往redis服务器发送。
  • 4)Receive函数代表从redis服务器中接收返回的信息。

2 管道作用

redis的主要作用上面也说过,就是节省大量的网络耗时,减少与redis的交互,主要体现在TCP三次握手与四次挥手。

3 管道使用技巧

// 1. 批量发送,批量接收。
c.Send(cmd1, ...) 
c.Send(cmd2, ...) 
c.Send(cmd3, ...) 
c.Flush() 	// 将上面的三个命令发送出去 
c.Receive() // cmd1 的返回值 
c.Receive() // cmd2 的返回值 
c.Receive() // cmd3 的返回值 

// 2. 如果不需要关注返回值。
c.Send(cmd1, ...) 
c.Send(cmd2, ...) 
c.Send(cmd3, ...) 
c.Do("") 
// 简单分析Do(""):
// Do=Send、Flush、Receive。而此时传空字符串,那么此时的Send相当于没命令即没意义,
// 那么此时的Do("")等价于连续执行了c.Flush()与c.Receive(),并不关心返回值。

// 3. 如果只关注最后一个命令的返回值。
// 一般这种情况前两条是写,第三条语句是读。
c.Send(cmd1, ...) 
c.Send(cmd2, ...) 
c.Do(cmd3, ...)

但是注意,上面每次调用函数后,都应该去判断返回值,养成良好的习惯,不是说忽略了redis的返回值就不判断错误。
例如忽略返回值但判断错误情况:

ifi( _, err := c.Do("")); err != nil{
	// 错误处理
} 

4 管道代码例子

package main

import (
	"fmt"
	"math/rand"
	"time"

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

func main() {
	//c, err := redis.Dial("tcp", fmt.Sprintf("%s:%d", "127.0.0.1", 6379))
	c, err := redis.Dial("tcp", "192.168.1.9:6379", redis.DialPassword("123456"))
	if err != nil {
		panic(err)
	}
	defer (func() {
		fmt.Println("connection close")
		c.Close()
	})()

	// 1. 批量发送,批量接收。
	if false {
		c.Send("del", "set", "list", "zset")
		c.Send("sadd", "set", "tyy", "hc", "lqq")
		c.Send("lpush", "list", 10001, 10002, 10003)
		c.Send("smembers", "set")
		c.Send("lrange", "list", 0, -1)
		c.Flush()
		c.Receive() // 忽略del的返回值。
		c.Receive() // 忽略sadd的返回值。
		c.Receive() // 忽略lpush的返回值。

		mbrs, err := redis.Strings(c.Receive()) // 接收smembers返回值。
		if err != redis.ErrNil {
			fmt.Println(mbrs)
		}
		lsts, err := redis.Ints(c.Receive()) // 接收lrange返回值。
		if err != redis.ErrNil {
			fmt.Println(lsts)
		}
	}

	// 2. 如果不需要关注返回值。
	if false {
		c.Send("del", "set", "list", "zset")
		c.Send("sadd", "set", "tyy", "hc", "lqq")
		c.Send("lpush", "list", 10001, 10002, 10003)
		c.Do("")
	}

	// 3. 如果只关注最后一个命令的返回值。
	if false {
		rand.Seed(time.Now().UnixNano())
		c.Send("del", "set", "list", "zset")
		c.Send("sadd", "set", "tyy", "hc", "lqq")
		{
			args := redis.Args{}.Add("zset")
			args = args.Add(rand.Intn(100)).Add("tyy")
			args = args.Add(rand.Intn(100)).Add("hc")
			args = args.Add(rand.Intn(100)).Add("lqq")
			c.Send("zadd", args...)
		}

		// 只关注最后一个命令的返回值。
		{
			args := redis.Args{}.Add("zset")
			args = args.Add(0).Add(-1).Add("withscores")
			vals, err := redis.Values(c.Do("zrange", args...))
			if err != nil {
				panic(err)
			}
			var rets []struct {
				Name  string
				Score int
			}
			if err = redis.ScanSlice(vals, &rets); err != nil {
				panic(err)
			}
			fmt.Println(rets)
		}
	}

}

测试方法:将上面的3个if添加中的false逐个改成true即可测得下面结果。
分别对应上面的结果:

  • 1)
    在这里插入图片描述

  • 2)此时因为程序不关心返回值,所以此时执行完程序结果只会打印connection close,所以我们可以去xshell命令行使用redis-cli查看结果。
    在这里插入图片描述

  • 3)这个结果可能大家都不一样,因为score是使用rand.Intn(100)随机生成的,所以排序可能会不一样。
    在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值