Go第 19 章 :Redis 的使用

news/2024/12/1 15:26:42/

Go第 19 章 :Redis

19.1 Redis 基本介绍

请添加图片描述

19.1.1 Redis 的安装

请添加图片描述

19.1.2 Redis 操作的基本原理图

请添加图片描述

19.2 Redis 的安装和基本使用

19.2.1 Redis 的启动:

mac :src/redis-server
windows:
请添加图片描述

19.3 Redis 的操作指令一览

请添加图片描述

19.3.1 Redis 的基本使用:

说明: Redis 安装好后,默认有 16 个数据库,初始默认使用 0 号库, 编号是 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 [flushdb flushall]
请添加图片描述
请添加图片描述

19.4 Redis 的 Crud 操作

19.4.1 Redis 的五大数据类型:

Redis 的五大数据类型是: String(字符串) 、Hash (哈希)、List(列表)、Set(集合) 和 zset(sorted set:有序集合)

19.4.2 String(字符串) -介绍

string 是 redis 最基本的类型,一个 key 对应一个 value。 string 类型是二进制安全的。除普通的字符串外,也可以存放图片等数据
redis 中字符串 value 最大是 512M
请添加图片描述
请添加图片描述

19.4.3 String(字符串)-使用细节和注意事项

setex(set with expire)键秒值

请添加图片描述

mset[同时设置一个或多个 key-value 对]
mget[同时获取多个 key-val]

请添加图片描述

19.4.4 Hash (哈希,类似 golang 里的 Map)-介绍

请添加图片描述
请添加图片描述
请添加图片描述

19.4.5 Hash(哈希,类似 golang 里的 Map)-CRUD

举例说明 Redis 的 Hash 的 CRUD的基本操作.
hset/hget/hgetall/hdel
演示添加 user 信息的案例 (name,age )

请添加图片描述

19.4.6 Hash-使用细节和注意事项

请添加图片描述

19.4.7 课堂练习

请添加图片描述

19.4.8 List(列表)-介绍

列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列 表的头部(左边)或者尾部(右边)。
List 本质是个链表, List 的元素 是有序的,元素的值可以重复.
举例,存放多个地址信息: city 北京 天津 上海
说明 : key : city
北京 天津 上海 就是三个元素
请添加图片描述

19.4.9 List(列表)-CRUD

举例说明 Redis 的 List 的 CRUD操作。
lpush/rpush/lrange/lpop/rpop/del/
请添加图片描述
请添加图片描述
请添加图片描述

19.4.10 List-使用细节和注意事项

请添加图片描述

19.4.11 Set(集合) - 介绍

  • Redis 的 Set 是 string 类型的无序集合。
  • 底层是 HashTable 数据结构, Set 也是存放很多字符串元素,字符串元素是无序的,而且元素的值不能重复
  • 举例,存放多个邮件列表信息:
    email sgg@sohu.com tom@sohu.com
    说明 :
    key : email
    tn@sohu.com tom@sohu.com 就是二个元素

redis>sadd email xx xxx
请添加图片描述

19.4.12 Set(集合)- CRUD

  • 举例说明 Redis 的 Set 的 CRUD 操作.
    sadd
    smembers[取出所有值]
    sismember[判断值是否是成员]
    srem [删除指定值]
  • 演示添加多个电子邮件信息的案例

请添加图片描述

19.4.13 Set 课堂练习

举例,存放一个商品信息:
包括 商品名、价格、生产日期。
完成对应的 crud操作

19.5 Golang 操作 Redis

19.5.1 安装第三方开源 Redis 库

  1. 使用第三方开源的 redis 库: github.com/garyburd/redigo/redis 2) 在使用 Redis 前,先安装第三方 Redis 库,在 GOPATH 路径下执行安装指令:
    D:\goproject>go get github.com/garyburd/redigo/redis
  2. 安装成功后,可以看到如下包
    请添加图片描述

19.5.2 Set/Get 接口

说明: 通过 Golang 添加和获取 key-value 【比如 name-tom~ 】

package mainimport ("fmt""github.com/garyburd/redigo/redis"
)func main(){//通过go向reids写入数据和读取数据//1、连接到redisconn,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-vaql]_,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)
}

19.5.3 操作 Hash

说明: 通过 Golang 对 Redis操作 Hash 数据类型
对 hash 数据结构,field-val 是一个一个放入和读取 代码:

package mainimport ("fmt""github.com/garyburd/redigo/redis"
)func main01(){//通过go向reids写入数据和读取数据//1、连接到redisconn,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-vaql]_,err=conn.Do("HSet","user01","name","tomjerry猫猫")if err!=nil{fmt.Println("set err=",err)return}_,err=conn.Do("HSet","user01","age","18")if err!=nil{fmt.Println("set err=",err)return}//3、通过go读取redis读取数据string[key-val]r1,err:=redis.String(conn.Do("HGet","user01","name"))if err!=nil{fmt.Println("set err= ",err)return}r2,err:=redis.String(conn.Do("HGet","user01","age"))if err!=nil{fmt.Println("set err= ",err)return}//因为返回 r 是 interface{}//因为 name 对应的值是 string ,因此我们需要转换//nameString := string(r.[]byte)fmt.Println("操作 ok r1=", r1 ,"\n ","r2=",r2)
}

对 hash 数据结构,field-val 是批量放入和读取

package mainimport ("fmt""github.com/garyburd/redigo/redis"
)func main(){//通过go向reids写入数据和读取数据//1、连接到redisconn,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-vaql]_, err = conn.Do("HMSet", "user02", "name", "john", "age", 19)if err!=nil{fmt.Println("set err=",err)return}//3、通过go读取redis读取数据string[key-val]r,err:=redis.Strings(conn.Do("HMGet","user02","name","age"))if err!=nil{fmt.Println("Get err= ",err)return}//因为返回 r 是 interface{}//因为 name 对应的值是 string ,因此我们需要转换//nameString := string(r.[]byte)for i,v:=range r{fmt.Println(i,v)}}

19.5.4 批量 Set/Get 数据

说明: 通过 Golang 对 Redis操作,一次操作可以 Set / Get 多个 key-val 数据
核心代码:

19.5.5 给数据设置有效时间

说明: 通过 Golang 对 Redis操作,给 key-value 设置有效时间
核心代码:
//给 name 数据设置有效时间为 10s
_, err = c.Do(“expire”, “name”, 10)

举例

package mainimport ("fmt""github.com/garyburd/redigo/redis""reflect""time"
)func main(){//通过go向reids写入数据和读取数据//1、连接到redisconn,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-vaql]_,err=conn.Do("MSet","name","tomjerry猫猫","address","北京昌平区")if err!=nil{fmt.Println("set err=",err)return}//设置key过期时间_, err = conn.Do("expire", "name", 10) //10秒过期if err != nil {fmt.Println("set expire error: ", err)return}//3、通过go读取redis读取数据string[key-val]r,err:=redis.Strings(conn.Do("MGet","name","address"))if err!=nil{fmt.Println("set err= ",err)return}else{res_type:=reflect.TypeOf(r)fmt.Println("res_type= ", res_type)fmt.Println("MGET name: ", r)fmt.Println("len r: ", len(r))}//因为返回 r 是 interface{}//因为 name 对应的值是 string ,因此我们需要转换//nameString := string(r.[]byte)//for _,v:=range r{//	fmt.Println("操作 ok ", v)//}for i:=0;i<=12;i++{time.Sleep(time.Second)fmt.Printf("倒数:%d\n",i)}r,err=redis.Strings(conn.Do("MGet","name","address"))if err!=nil{fmt.Println("set err= ",err)return}for _,v:=range r{fmt.Println("操作 ok ", v)}}
res_type=  []string
MGET name:  [tomjerry猫猫 北京昌平区]
len r:  2
倒数:0
倒数:1
倒数:2
倒数:3
倒数:4
倒数:5
倒数:6
倒数:7
倒数:8
倒数:9
倒数:10
倒数:11
倒数:12
操作 ok  
操作 ok  北京昌平区

19.5.6 操作 List

说明: 通过 Golang 对 Redis操作 List 数据类型
核心代码:
_, err = c.Do(“lpush”, “heroList”, “no1:宋江”, 30, “no2:卢俊义”, 28) r, err := redis.String(c.Do(“rpop”, “heroList”))

package mainimport("fmt""github.com/garyburd/redigo/redis""reflect"
)
func main(){conn,err:=redis.Dial("tcp","127.0.0.1:6379")if err!=nil{fmt.Println("redis.Dial err=",err)return}defer conn.Close()read,err:= conn.Do("LPUSH","list1","ele1","ele2","ele3")if err!=nil{fmt.Println("do LPUSH err=",err)return}fmt.Println("read=",read)res,err:=redis.String(conn.Do("LPOP","list1"))if err != nil {fmt.Println("Do PoP err=", err)return}else{res_type:=reflect.TypeOf(res)fmt.Printf("res_type=%s\n",res_type)fmt.Printf("res :%s",res)}}

Pipelining(管道)

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

Send (commandName string, args ..interface{})error
Flush() error
Receive() (reply interface{},err error)
  • Send:发送命令至缓冲区
  • Flush:清空缓冲区,将命令一次性发送至服务器
  • Recevie: 依次读取服务器响应结果,当读取的命令未响应时,该操作会阻塞。
    示例:
package mainimport ("fmt""github.com/garyburd/redigo/redis"
)func main() {conn, err := redis.Dial("tcp", "127.0.0.1:6379")if err != nil {fmt.Println("redis.Dial err=", err)return}defer conn.Close()conn.Send("HSET", "student", "name", "wd", "age", "22")conn.Send("HEST", "Score", "100")conn.Send("HGET", "student", "age")conn.Flush()resl, err := conn.Receive()fmt.Printf("Recive resl:%v \n", resl)res2, err := conn.Receive()fmt.Printf("Recive resl:%v \n", res2)res3, err := conn.Receive()fmt.Printf("Recive resl:%v \n", res3)
}

发布/订阅

redis本身具有发布订阅的功能,其发布订阅功能通过命令SUBSCRIBE(订阅)/
PUBLISH(发布)实现,并且发布订阅模式可以是多对多模式还可支持正则表达式,发布者
可以向一个或多个频道发送消息,订阅者可订阅一个或者多个频道接受消息。
示意图:
发布者:
请添加图片描述
订阅者:
请添加图片描述
操作示例,示例中将使用两个goroutine分别担任发布者和订阅者角色进行演示:

package mainimport ("fmt""github.com/garyburd/redigo/redis""time"
)func Subs() { //订阅者conn, err := redis.Dial("tcp", "127.0.0.1:6379")if err != nil {fmt.Println("redis.dial err=", err)return}defer conn.Close()psc := redis.PubSubConn{conn}psc.Subscribe("channl1") //订阅channel1频道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 Push(message string) { //发布者conn, _ := redis.Dial("tcp", "127.0.0.1:6379")_, err1 := conn.Do("PUBLISH", "channel1", message)if err1 != nil {fmt.Println("PUBLISH err=", err1)return}
}func main() {go Subs()go Push("this is wd")time.Sleep(time.Second*3)
}

请添加图片描述
示例:

package mainimport ("fmt""github.com/garyburd/redigo/redis"
)func main() {conn,err:=redis.Dial("tcp","127.0.0.1:6379")if err != nil {fmt.Println(" redis.Dial err=", err)return}defer conn.Close()conn.Send("MUTL1")conn.Send("INCR","foo")conn.Send("INCR","bar")r,err:=conn.Do("EXEC")fmt.Println(r)
}

Ω

课堂作业

请添加图片描述

package mainimport ("fmt""github.com/garyburd/redigo/redis""reflect"
)type Monster struct{Name stringAge intSkill string
}func process(name string, age int, skill string){//1、链接ridesconn:=pool.Get()defer conn.Close()_, err:=conn.Do("HMSet","Monster","name",name,"age",age,"skill",skill)if err != nil {fmt.Println(" do err=", err)return}res,err:=redis.Strings(conn.Do("HMGet","Monster","name","age","skill"))if err != nil {fmt.Println("res Do err=", err)return}else{res_type:=reflect.TypeOf(res)fmt.Println("res_type=",res_type)fmt.Println("res=",res)}for _,v:=range res{fmt.Println(v)}
}var pool *redis.Poolfunc init(){pool = &redis.Pool{MaxIdle: 8,MaxActive: 8,IdleTimeout: 100,Dial:func()(redis.Conn,error){return redis.Dial("tcp","127.0.0.1:6379")},}
}func main(){var monster Monsterfmt.Println("请输入monster的name:")fmt.Scanln(&monster.Name)fmt.Println("请输入monster的age:")fmt.Scanln(&monster.Age)fmt.Println("请输入monster的Skill:")fmt.Scanln(&monster.Skill)process(monster.Name,monster.Age,monster.Skill)
}

请添加图片描述
请添加图片描述

19.5.7 Redis 链接池

请添加图片描述
请添加图片描述
5) 链接池使用的案例

package mainimport ("fmt""github.com/garyburd/redigo/redis"
)//定义一个全局的pool
var pool *redis.Pool//当启动程序时,就初始化连接池
func init() {pool = &redis.Pool{MaxIdle:     8, //最大空闲链接数MaxActive:   0, //表示和数据库的最大链接数,0表示没有限制IdleTimeout: 100,Dial: func() (redis.Conn, error) { // 初始化链接的代码, 链接哪个 ip 的 redisreturn redis.Dial("tcp", "localhost:6379")},}
}func main() {//先从pool取出一个链接conn := pool.Get()defer conn.Close()_, err := conn.Do("Set", "name", "汤姆猫~~")if err != nil {fmt.Println("conn.Do1 Set err=", err)return}//取出r, err := redis.String(conn.Do("Get", "name"))if err != nil {fmt.Println("Do Get1 err=", err)return}fmt.Println("r=", r)//如果我们要从pool取出链接,一定保证连接池是没有关闭的//pool.Close()conn2 := pool.Get()_, err = conn2.Do("Get", "name2", "汤姆猫~~2")if err != nil {fmt.Println("conn.Do2 Set err=", err)return}r2, err := redis.String(conn2.Do("Get2", "name"))if err != nil {fmt.Println("Do Get2 err=", err)return}fmt.Println("r=",r2)//fmt.Println("conn2=", conn2)}

在这里插入图片描述
请添加图片描述
请添加图片描述


http://www.ppmy.cn/news/22421.html

相关文章

基础IO(下)

基础IO&#xff08;下&#xff09;模拟实现封装C标准库为shell添加重定向功能区分stdout和stderr文件系统磁盘的物理结构磁盘的存储结构磁盘的逻辑结构文件系统的管理理解创建文件/删除文件/查看文件查看文件的更多属性软硬链接软链接硬链接链接指令硬链接数软硬链接的区别删除…

java处理,调用外系统的 WebAPI(https请求)时,相关知识整理

目录 ■整理内容 1.外系统连接时&#xff0c;注意点 2.https证书相关问题---java---证书产生的错误---不被信任的证书 3.https证书相关问题---CURL---通过参数-可以忽略-证书信任问题 4.证书添加---在调用方-添加被调用方(WebAPI https)的证书 5.之前的一个作业&#xff…

「抄底 Android 内存优化 9」 —手撕 LeakCanary 核心原理

核心内容在文章最后面的总结部分 1 自动安装原理 在2.0版本开始&#xff0c;LeakCanary 已经不需要手动初始化了&#xff0c;只需要引入以来即可: // leakCanarydebugImplementation com.squareup.leakcanary:leakcanary-android:2.4那么他是如何进行初始化的呢&#xff1f;答…

DVWA-XSS(Stored)注入-Low-Medium-Hight

Low 1、进来这里可以看到&#xff0c;好像是有两个入口&#xff0c;先随便填个数据试试水&#xff0c;勒特 payload: <script>alert(1)</script> 2、直接提交&#xff0c;简单拿下。 Medium 1、继续尝试刚才的入口&#xff0c;勒特。 payload: <script>ale…

OpenWrt之IPTV单线复用详细教程

文章目录前言OpenWrt版本1. 让路由与光猫互通2. 设置Vlan3. 配置接口4. 配置路由表5. 播放测试后话前言 前段时间开始, 电信就开始整理单播源传播的乱象, 就限制了非内网无法打开直播源, 于是只能搞搞内网融合了, 让我的RTSP源重新焕发生机 OpenWrt版本 22.02 1. 让路由与光猫…

【Linux】冯诺依曼体系与操作系统(OS)概念

文章目录冯诺依曼体系结构为什么是这样的结构局部性原理操作系统(Operator System)设计OS的目的定位如何理解管理 (精髓:先描述再组织)总结系统调用和库函数概念冯诺依曼体系结构 我们常见的计算机,如笔记本.我们不常见的计算机,如服务器,大部分都遵守冯诺依曼体系 为什么是这…

海量多源遥感数据智能分析展望

前言随着空间对地观测技术在全球范围内的迅速发展&#xff0c;遥感数据的空间分辨率、时间分辨率乃至光谱分辨率日益提升&#xff0c;高分辨率遥感数据量呈井喷式增长。未来10年中全球每天获取的观测数据将超过10PB&#xff0c;标志着遥感大数据时代已然来临。然而&#xff0c;…

从 HTTP/1.1 到 HTTP/3

从 HTTP/1.1 到 HTTP/3&#xff0c;解决了一些旧协议的问题&#xff0c;引入了好用的新功能。 HTTP/1.1 HTTP/1.1 通过在传输层和应用层之间增加 SSL/TSL 解决数据不安全的问题&#xff0c;但它本身还有一些其它的不足。 同一时间&#xff0c;一个连接只能对应一个请求&…