Go语言 Redis的使用

介绍

REmote DIctionary Server(Redis) 是一个由 Salvatore Sanfilippo 写的 key-value 存储系统。

Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。

它通常被称为数据结构服务器,因为值(value)可以是 字符串 (String), 哈希 (Hash), 列表 (list), 集合 (sets) 和 有序集合 (sorted sets)等类型。

Redis 优势:

  • 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
  • 丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
  • 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
  • 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

Mac 安装 Redis

首先安装homebrew ,使用 brew install redis 安装即可。

  • 如果需要后台运行 redis 服务,使用命令 brew services start redis
  • 如果不需要后台服务,则使用命令 redis-server /usr/local/etc/redis.conf

要运行命令,可以直接到 /usr/local/bin 目录下,有

  • redis-server 服务器运行命令
  • redis-cli 运行客户端

可以直接运行 redis-server 打开服务。然后另外开一个终端,运行 redis-cli 运行服务端,在服务端中输入 quit 可以退出。

go 操作 Redis

go 操作 redis 的客户端包有多个比如 redigo、go-redis,github上 Star 最多的莫属 redigo。

github地址:https://github.com/gomodule/redigo

文档:https://godoc.org/github.com/garyburd/redigo/redis

连接

Conn 接口是与 Redis 协作的主要接口,可以使用 Dial, DialWithTimeout 或者 NewConn 函数来创建连接,当任务完成时,应用程序必须调用 Close 函数来完成操作。

	c, err := redis.Dial("tcp", "localhost:6379")
	if err != nil {
		fmt.Println("Connect to redis error", err)
		return
	}else {
		fmt.Println("连接成功")
	}
	defer c.Close()

命令操作

可以通过使用 Conn 接口中的 do 方法执行 redis 命令,redis 命令链接:http://doc.redisfans.com/

get、set 操作:

	// 写入数据,永不过期
	_, err = c.Do("SET", "username", "nick")
	if err != nil {
		fmt.Println("redis set failed:", err)
	}
	// 写入数据,10s后过期
	_, err = c.Do("SET", "password", "123456", "EX", "10")
	if err != nil {
		fmt.Println("redis set failed:", err)
	}
	// 读取数据
	username, err := redis.String(c.Do("GET", "username"))
	if err != nil {
		fmt.Println("redis get failed:", err)
	} else {
		fmt.Printf("Got username %v \n", username)
	}
	// 读取数据
	passwd, err := redis.String(c.Do("GET", "password"))
	if err != nil {
		fmt.Println("redis get failed:", err)
	} else {
		fmt.Printf("Got password %v \n", passwd)
	}

批量获取mget、批量设置mset

	// 批量读写
	_, err = c.Do("MSET", "name", "nill","passwd", "123456")
	if err != nil {
		fmt.Println("redis mset error:", err)
	}
	res, err := redis.Strings(c.Do("MGET", "name","passwd"))
	if err != nil {
		fmt.Println("redis get error:", err)
	} else {
		res_type := reflect.TypeOf(res)
		fmt.Printf("res type : %s \n", res_type)
		fmt.Printf("MGET name: %s \n", res)
		fmt.Println(len(res))
	}

列表操作:

	// 列表操作
	c.Do("lpush", "redlist", "qqq")
	c.Do("lpush", "redlist", "www")
	c.Do("lpush", "redlist", "eee")
	values, _ := redis.Values(c.Do("lrange", "redlist", "0", "2"))
	for _, v := range values {
		fmt.Println(string(v.([]byte)))
	}

hash操作:

	// hash 操作
	_, err = c.Do("HSET", "student","name", "nill","passwd","123456")
	if err != nil {
		fmt.Println("redis mset error:", err)
	}
	resi, err := redis.Int64(c.Do("HGET", "student","passwd"))
	if err != nil {
		fmt.Println("redis HGET error:", err)
	} else {
		res_type := reflect.TypeOf(resi)
		fmt.Printf("res type : %s \n", res_type)
		fmt.Printf("res  : %d \n", resi)
	}

管道 Pipelining

管道操作可以理解为并发操作,并通过 Send(),Flush(),Receive() 三个方法实现。客户端可以使用 send() 方法一次性向服务器发送一个或多个命令,命令发送完毕时,使用 flush() 方法将缓冲区的命令输入一次性发送到服务器,客户端再使用 Receive() 方法依次按照先进先出的顺序读取所有命令操作结果。

c.Send("SET", "foo", "bar")//Send向连接的输出缓冲中写入命令
c.Send("GET", "foo")//
c.Flush()//Flush将连接的输出缓冲清空并写入服务器端
//Recevie按照FIFO顺序依次读取服务器的响应
c.Receive() // reply from SET
v, err = c.Receive() // reply from GET

Send:发送命令至缓冲区
Flush:清空缓冲区,将命令一次性发送至服务器
Recevie:依次读取服务器响应结果,当读取的命令未响应时,该操作会阻塞。

发布/订阅

redis 本身具有发布订阅的功能,其发布订阅功能通过命令 SUBSCRIBE(订阅)/PUBLISH(发布) 实现,并且发布订阅模式可以是多对多模式还可支持正则表达式,发布者可以向一个或多个频道发送消息,订阅者可订阅一个或者多个频道接受消息。

func subscribe() {
	c, err := redis.Dial("tcp", "127.0.0.1:6379")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer c.Close()

	psc := redis.PubSubConn{c}
	psc.Subscribe("redChatRoom")
	for {
		 switch v := psc.Receive().(type) {
		 case redis.Message:
				fmt.Printf("%s: message: %s\n", v.Channel, v.Data)
		 case redis.Subscription:
				fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
		 case error:
			fmt.Println(v)
			return
		}

 	}
}

func main() {
	c, err := redis.Dial("tcp", "localhost:6379")
	if err != nil {
		fmt.Println("Connect to redis error", err)
		return
	}else {
		fmt.Println("连接成功")
	}
	defer c.Close()
	
	go subscribe()
	go subscribe()
	
	for {
		 var s string
		 fmt.Scanln(&s)
		 _, err := c.Do("PUBLISH", "redChatRoom", s)
		 if err != nil {
			  fmt.Println("pub err: ", err)
			 return
		  }
	 }
}

参考文章

https://www.jianshu.com/p/3bdfda703552
https://www.cnblogs.com/wdliu/p/9330278.html

猜你喜欢

转载自blog.csdn.net/bingfeilongxin/article/details/88239546