欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

go语言系列-redis

程序员文章站 2022-07-09 19:31:41
Redis的使用 Redis 基本介绍 1. Redis是NoSQL数据库,不是传统的关系型数据库 官网: "https://redis.io/ 和" http://www.redis.cn/ 2. Redis:REmote DIctionary Server(远程字典服务器),Redis性能非常高 ......

redis的使用

redis 基本介绍

  1. redis是nosql数据库,不是传统的关系型数据库 官网: https://redis.io/ 和

  2. redis:remote dictionary server(远程字典服务器),redis性能非常高,单机能够达到15w qps,通常适合做缓存,也可以持久化。

  3. 是完全开源免费的,高性能的(key/value)分布式内存数据库,基于内存运行并支持持久化的nosql数据库,是最热门的nosq|数据库之一也称为数据结构服务器

redis的安装

链接:https://pan.baidu.com/s/1qtytkepsgza93kca76eatq

提取码:au10

下载后直接解压就有redis的服务器端程序(redis- server.exe)和客户端程序(redis-cli.exe),直接双击即可运行,并不需要安装。

redis 操作的基本原理图

go语言系列-redis

redis的安装和基本使用

redis的启动

go语言系列-redis
启动redis的服务器端程序(redis-server.exe),直接双击即可运行
go语言系列-redis

redis的操作指令一览

go语言系列-redis

redis的基本使用

说明:redis安装好后,默认有16个数据库,初始默认使用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 [fiushdb flushall]
    go语言系列-redis

redis的crud操作

redis的五大数据类型

redis的五大数据类型是: string(字符串)、hash (哈希)、list(列表)、set(集 合)和zset(sorted set:有序集合)

string(字符串) -介绍

string是redis最基本的类型,一个key对应一个value.

string类型是二进制安全的。除普通的字符串外,也可以存放图片等数据。

redis中字符串value最大是512m

举例,存放一个地址信息:

address 北京*

说明:

key : address

value:北京*

127.0.0.1:6379> set address beijing
ok
127.0.0.1:6379> get address
"beijing"

string(字符串)-crud

举例说明redis的string 字符串的crud操作.

set[如果存在就相当于修改,不存在就是添加]/get/del

127.0.0.1:6379> del address
(integer) 1
127.0.0.1:6379> get address
(nil)

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

setex(set with expire)键秒值

127.0.0.1:6379> setex mess01 10 hello,you
ok
127.0.0.1:6379> get mess01
"hello,you"
127.0.0.1:6379> get mess01
"hello,you"
127.0.0.1:6379> get mess01
(nil)

mset[同时设置一个或多个key-value 对]

mget[同时获取多个key-val]

127.0.0.1:6379> mset worker01 tom worker02 scott
ok
127.0.0.1:6379> get worker02
"scott"
127.0.0.1:6379> mget worker01 worker02
1) "tom"
2) "scott"

hash (哈希,类似golang里的map)-介绍

基本的介绍

redis hash是一个键值对集合。var user1 map[string]string

redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

举例,存放一个user信息:(user1)

userl name "smith" age 30 job "golang coder"

说明:

key : userl

name张三 和age 30 就是两对field-value
go语言系列-redis

hash (哈希,类似golang里的map) -crud

举例说明redis的hash 的crud的基本操作.

hset/hget/hgetall/hdel

演示添加user信息的案例(name,age )

127.0.0.1:6379> hgetall user1
1) "name"
2) "smith"
3) "age"
4) "30"
5) "job"
6) "golang coder"

hash-使用细节和注意事项

在给user设置name和age时,前面我们是一一步-一步设置,使用hmset和hmget 可以一次性来设置多个filed 的值和返回多个field 的值。

hlen 统计一个hash有几个元素

hexists key field 查看哈希表key中,给定域field是否存在

127.0.0.1:6379> hmset user2 name jerry age 110 job "java coder"
ok
127.0.0.1:6379> hmget user2 name age job
1) "jerry"
2) "110"
3) "java coder"
127.0.0.1:6379> hlen user2
(integer) 3
127.0.0.1:6379> hexists user2 name
(integer) 1
127.0.0.1:6379> hexists user2 name2
(integer) 0

hash练习

举例,存放一个student信息:

stu1 name张三age 30 score 80 address北京

说明:

通过相关指令,完成对student的crud操作

list(列表) - 介绍

列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

list本质是个链表,list的元素是有序的,元素的值可以重复.

举例 存放多个地址信息:

city 北京 天津 上海

说明:

key:city

北京 天津 上海 就是三个元素

入门案例

127.0.0.1:6379> lpush city berjing shanghai tianjing
(integer) 3
127.0.0.1:6379> lrange city 0 -1
1) "tianjing"
2) "shanghai"
3) "berjing"

list (列表) -crud

举例说明redis的list的crud操作。

lpush/rpush/lrange/lpop/rpop/del/

说明

list画图帮助理解(可以把list想象成一根管道)
go语言系列-redis
herolist的演示

127.0.0.1:6379> lpush herolist aaa bbb ccc
(integer) 3
127.0.0.1:6379> lrange herolist 0 -1
1) "ccc"
2) "bbb"
3) "aaa"
127.0.0.1:6379> rpush herolist ddd eee
(integer) 5
127.0.0.1:6379> lrange herolist 0 -1
1) "ccc"
2) "bbb"
3) "aaa"
4) "ddd"
5) "eee"
127.0.0.1:6379>  rpop herolist
"eee"
127.0.0.1:6379> lrange herolist 0 -1
1) "ccc"
2) "bbb"
3) "aaa"
4) "ddd"
127.0.0.1:6379> del herolist
(integer) 1
127.0.0.1:6379> lrange herolist 0 -1
(empty list or set)

list-使用细节和注意事项

(1) lindex,按照索引下标获得元素(从左到右,编号从0开始.)

(2) llen key

返回列表key的长度,如果key不存在,则key被解释为一个空列表,返回0

(3) list的其它说明

​ list数据,可以从左或者右插入添加;

​ 如果值全移除,对应的键也就消失了。

set(集合) - 介绍

redis 的set是string类型的无序集合。

底层是 hashtable数据结构,set也是存放很多字符串元素,字符串元素是无序的,而且元素的值不能重复

举例,存放多个邮件列表信息:

email sgg@sohu.com tom@sohu.com

说明:

key : email

tn@sohu.com tom@sohu.com就是二个元素

127.0.0.1:6379> sadd emails tom@sohu.com jack@qq.com
(integer) 2
127.0.0.1:6379> smembers emails
1) "jack@qq.com"
2) "tom@sohu.com"
127.0.0.1:6379> sadd emails kk@yy.com yy@sohu.com
(integer) 2
127.0.0.1:6379> smembers emails
1) "kk@yy.com"
2) "jack@qq.com"
3) "tom@sohu.com"
4) "yy@sohu.com"
127.0.0.1:6379> sadd emails tom@sohu.com 
(integer) 0
127.0.0.1:6379> smembers emails
1) "kk@yy.com"
2) "jack@qq.com"
3) "tom@sohu.com"
4) "yy@sohu.com"

set(集合) - crud

举例说明redis的set 的crud操作.

sadd

smembers[取出所有值]

sismember[判断值是否是成员]

srem [删除指定值]

演示添加多个电子邮件信息的案例

127.0.0.1:6379> sismember emails tom@sohu.com
(integer) 1
127.0.0.1:6379> sismember emails tom~@sohu.com
(integer) 0
127.0.0.1:6379> srem emails tom@sohu.com
(integer) 1
127.0.0.1:6379> smembers emails
1) "jack@qq.com"
2) "yy@sohu.com"
3) "kk@yy.com"

set练习

举例,存放一个商品信息:

包括商品名、价格、生产日期。

完成对应的crud操作

golang操作redis

安装第三方开源redis库

1)使用第三方开源的redis库: github.com/garyburd/redigo/redis

2)在使用redis前,先安装第三方redis库,在gopath路径下执行安装指令:

​ e:\gostudent>go get github.com/garyburd/redigo/redis

3)安装成功后,可以看到如下包
go语言系列-redis
特别说明:在安装redis库前,确保已经安装并配置了git, 因为是从github下载安装redis库的,需要使用到git。

e:\gostudent>go get github.com/garyburd/redigo/redis
\# cd .; git clone -- https://github.com/garyburd/redigo e:\gostudent\src\github.com\garyburd\redigo
cloning into 'e:\gostudent\src\github.com\garyburd\redigo'...
fatal: unable to access 'https://github.com/garyburd/redigo/': failed to connect to github.com port 443: timed out
package github.com/garyburd/redigo/redis: exit status 128

多执行几次就好了 原因大家都懂

set/get接口

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

package main

import (
  "fmt"
  "github.com/garyburd/redigo/redis"  //引入redis包
)

func main() {
  //通过go向redis写入数据和读取数据
  //1. 链接到redis
  conn, 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写入数据strinf [key-val]
  _, 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)
}
//操作ok tomjerry 猫猫

操作hash

说明: 通过golang对redis操作hash数据类型

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

代码:

import (
  "fmt"
  "github.com/garyburd/redigo/redis"  //引入redis包
)

func main() {
  //通过go向redis写入数据和读取数据
  //1. 链接到redis
  conn, 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 - val]
  _,err = conn.do("hset","user01","name","john")
  if err != nil {
   fmt.println("hset err = ", err)
   return
  }
  _, err = conn.do("hset","user01","age",18)
  if err != nil {
   fmt.println("hset err =", err)
   return
  }

  //3. 通过go向redis读取数据
  r, err := redis.string(conn.do("hget","user01","name"))
  if err != nil {
   fmt.println("hget err = ", err)
   return
  }

  r2, err := redis.int(conn.do("hget","user01","age"))
  if err != nil{
   fmt.println("hget err =", err)
   return
  }

  //因为返回r是interface{}
  //因为name对应的值是string,因此需要转换
  //namestring := r.(string)

  fmt.printf("操作ok r1 = %v r2 = %v\n", r, r2)

}
//操作ok r1 = john r2 = 18

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

import (
  "fmt"
  "github.com/garyburd/redigo/redis"  //引入redis包
)

func main() {
  //通过go向redis写入数据和读取数据
  //1. 链接到redis
  conn, 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 - val]
  _,err = conn.do("hmset","user02","name","john","age",19)
  if err != nil {
   fmt.println("hmset err = ", err)
   return
  }

  //3. 通过go向redis读取数据
  r, err := redis.strings(conn.do("hmget","user02","name","age"))
  if err != nil {
   fmt.println("hmget err = ", err)
   return
  }
  for i, v := range r {
   fmt.printf("r[%d] = %s\n", i, v)
  }
}
//r[0] = john
//r[1] = 19

批量set/get数据

说明:通过golang对redis操作,一次操作可以set/get多个key-val数据

核心代码:

_, err = c.do("mset", "name",”zisefeizhu","address", "中国")
r, err := redis.strings(c.do("mget", 'name", " address"))
for. ,v := range r {
	fmt.println(v)
}

给数据设置有效时间

说明: 通过golang对redis操作,给key-value设置有效时间

核心代码:

//给name数据设置有效时间为10s

_,err = c.do("expire", "name", 10)

操作list

说明: 通过golang对redis操作list 数据类型

核心代码:

_, err = c.do("lpush", "herolist", "no1:宋江",30, "no2:卢俊义", 28)
r, err := redis.string(c.do("rpop", "herolist"))

redis链接池

说明:通过golang对redis操作,还可 以通过redis链接池,流程如下:

​ 1) 事先初始化一定数量的链接,放入到链接池

​ 2) 当go需要操作redis时,*直接从redis链接池取出链接*即可。

​ 3) 这样可以节省临时*获取redis链接*的时间,从而提高效率.

​ 4) 示意图
go语言系列-redis
*链接池使用案例*

import (
  "fmt"
  "github.com/garyburd/redigo/redis"
)

//定义一个全局的pool
var pool *redis.pool

//当启动程序时,就初始化链接池
func init()  {
  pool = &redis.pool{
   dial: func() (redis.conn, error) {  //初始化链接的代码,链接哪个ip的redis
     return redis.dial("tcp","localhost:6379")
   },
   maxidle:     8,  //最大空闲链接数
   maxactive:    0,  //表示和数据库的最大链接数,0 表示没有限制
   idletimeout:   100,  //最大空闲时间
  }
}

func main()  {
  //先从pool取出一个链接
  conn := pool.get()
  defer conn.close()

  _, err := conn.do("set","name","汤姆猫~")
  if err != nil {
   fmt.println("conn.do err=", err)
   return
  }

  //取出
  r, err := redis.string(conn.do("get","name"))
  if err != nil {
   fmt.println("conn.do err =", err)
   return
  }

  fmt.println("r =", r)

  //如果要从pool 取出链接,一定要保证链接池是没有关闭
  // pool.close()
  conn2 := pool.get()

  _, err = conn2.do("set", "name2", "汤姆猫~2")
  if err != nil {
   fmt.println("conn.do err ~~=", err)
   return
  }

  //取出
  r2, err := redis.string(conn2.do("get","name2"))
  if err != nil {
   fmt.println("conn.do err =", err)
   return
  }

  fmt.println("r =", r2)

  //fmt.println("conn2 =", conn2)
}
//r = 汤姆猫~
//r = 汤姆猫~2

再来一例

var pool *redis.pool

func init() {
  pool = &redis.pool{
   maxidle:   8,
   maxactive:  0,
   idletimeout: 100,
   dial: func() (redis.conn, error) {
     return redis.dial("tcp", "localhost:6379")
   },
  }
}

func main() {
  conn := pool.get()
  defer conn.close()

  _, err1 := conn.do("hmset", "user1", "name", "beijing", "address", "beijing")
  if err1 != nil {
   fmt.println("hmset err=", err1)
   return
  }
  _, err3 := conn.do("hmset", "user2", "name", "wuhan", "address", "wuhan")
  if err3 != nil {
   fmt.println("hmset err=", err3)
   return
  }

  //向redis读取数据,返回的r是个空接口
  r, err2 := redis.strings(conn.do("hmget", "user1", "name", "address"))
  if err2 != nil {
   fmt.println("hmget err=", err2)
   return
  }
  for i, v := range r {
   fmt.printf("r[%d]=%v\n", i, v)
  }
}
//r[0]=beijing
//r[1]=beijing