redis pipe处理大数据操作

       假设我们现在有一个需求,需要往redis中添加1000完条数据。注意这1000万数据是没有重复的,因此我们只需要把这1000万数据添加到redis中的一个集合中。

命令行添加方式如下:

SADD  [集合名称]  成员1,成员2,...

例如

SADD FRUIT apple banana pear

      这样添加的效率低,时间都耗费了网络传输和命令传输的往返时间上,如果添加的数据量不多还好,如果添加的数据达到百万甚至千万级,这样在添加的过程中耗费了大量的时间。那么redis是如何在很短的时间内加载已生成的大量数据的呢?在2.6或更高版本的Redis中,该redis-cli实用程序支持一种称为管道模式的新模式,该模式是为了执行大量插入而设计的。

使用管道模式运行的命令如下所示:

cat data.txt | redis-cli --pipe

这将产生类似于此的输出:

All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 1000000

redis-cli实用程序还将确保仅将从Redis实例接收的错误重定向到标准输出。

使用redis协议

       Redis协议生成和解析非常简单,并 在此处记录。但是,为了生成大规模插入目标的协议,您不需要了解协议的每个细节,而只需要按以下方式表示每个命令:

*3\r\n            命令起始,定义共3个输入参数
$3\r\n            下一个参数字节长度
SET\r\n           命令参数
$3\r\n             下一个参数字节长度
key\r\n           变量参数
$5\r\n            下一个参数字节长度
value\r\n        值参数
 
注意:此处的\r\n为换行符,不是输入的字符。在这里我耗了很长的时间。。。。英文不好没办法。

下面是一个例子

*3
$4
SADD
$18
USER_UID_LIST_TEST
$6
111111

假设我们又一个文本中都是存着上述格式的文本,我们可以通过命令行这样执行:

cat user_uid.txt | redis-cli -h 127.0.0.1 --pipe

go 语言实现

对于redis-pipe,go-redis库实现了该功能,代码如下

package main

import (
	"fmt"
	"github.com/go-redis/redis"
)

func main() {
	/*	client := redis.NewClusterClient(&redis.ClusterOptions{
			Addrs:         []string{"127.0.0.1:6379"},
			ReadOnly:      true,
			RouteRandomly: true,
		})
	*/
	client := redis.NewClient(&redis.Options{
		Addr:     "127.0.0.1:6379",
		Password: "",
	})
	pipe := client.Pipeline()
	pipe.SAdd("USER_UID_LIST_TEST", "123")
	pipe.SAdd("USER_UID_LIST_TEST", "456")

	cmders, err := pipe.Exec()
	if err != nil {
		fmt.Println("err", err)
	}

	for _, cmder := range cmders {
		//cmd := cmder.(*redis.StringStringMapCmd)
		cmd := cmder.(*redis.IntCmd)
		res, err := cmd.Result()
		if err != nil {
			fmt.Println("err", err)
		}
		fmt.Println("res", res)
	}
}

 

你可能感兴趣的:(数据库)