十七、Redis

19.1 基本介绍

1、Redis是NoSQL数据库, 不是传统的关系型数据库

2、Redis:REmote Dlctionary Server(远程字典服务器),Redis性能非常高,单机能够达到15W qps,通常适合做缓存,也可做持久化

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

19.1.1 Redis的安装和基本能使用

Redis的下载地址:https://github.com/MSOpenTech/redis/releases 下载.zip的压缩包

​ 下载后如果不能双击运行redis-server.exe文件,则 windows +r -> cmd打开一个cmd窗口 ->进入Redis的安装目录 -> 运行 redis-server.exe redis.windows.conf -> 这样redis的服务端就起来了,不要关闭这个窗口 - > 再次打开一个新的cmd窗口进入到Redis的安装目录-> 运行 redis-cli.exe -h 127.0.0.1 - p 6379 这样Redis的客户端起来了

NZj59J.png

NZjx9H.png

19.1.2 Redis基本操作原理图:

NmGKT1.png

19.2 Redis的命令一览

地址:

19.3 Redis基本使用

说明:Redis安装好后,默认有16个数据库初始默认使用0号库,编号是0...15

1、添加key-val

set key1 hello

2、查看当前redis的所有 key

keys *

3、获取key对应的值

get key1

4、切换redis数据库

select 1 切换到1号数据库

5、如何查看当前数据库的key-val数量

dbsize

6、清空当前数据库的key-val和清空所有数据库的key-val

flushdb ---> 清空当前数据库

flushall ----> 清空16个数据库

NZzyjA.png

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类型是二进制安全的,除普通的E字符串外,也可以存放图片等数据。

redis中字符串value最大是512M

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

key:address

value:beijing

NepMz4.png

String(字符串) -CRUDE

举例说明Redis的String字符串的CRUD操作

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

NepwSe.png

String 使用注意事项

​ setex(set with expire)键秒值(以为单位),可以设置有限时间,定时器

Nep7T0.png

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

​ 如果某个给定 key 已经存在,那么 MSET 会用新值覆盖原来的旧值

mget[一次返回多个key的值]

​ 如果给定的 key 里面,有某个 key 不存在,那么这个 key 返回特殊值 nil

NeCpvQ.png

19.4.3 Hash (哈希 类似Golang里的Map)

​ Redis hash 是一个键值对集合。

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

​ Hash中的key不能重复。

举例,存放一个User信息

user1 name "smith" age 30 jb "golang"

NePfSO.png

Hash(哈希 类似golang里的map) - CRUD

举例说明Redis的Hash的CURD的基本操作

hset/hget/hgetall/hdel

NeFHRf.png

Hash-使用细节和注意事项

​ 再给user设置name和age时,前面是一步步设置,使用hmset 和 hmget可以一次性来设置多个 field的值和返回多个field的值

hlen 统计一个hasg有几个元素

Neiz8K.png

19.4.4 List(列表)

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

​ List本质是个链表,List的元素是有序的元素的值可以重复。

举例:存放多个地址信息

city 北京 天津 上海

NINOOI.PNG

List(列表) -CRUD

lpush/rpush/lrange/lpop/rpop/del

lrange解析:

NINOOI.PNG

List的演示

NINOOI.PNG

案例演示

NINOOI.PNG

List 使用细节和注意事项

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

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

3、List数据,可以从左或者右插入添加

4、如果值全部移除,对应的键也就消失了

19.4.5 Set(集合)

​ Redis的Set是string类型的无序集合。

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

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

NINOOI.PNG

Set 集合

sadd[添加]

smembers[取出所有值]

sismerber[判断值是否是成员]

srem[删除指定值]

19.5 Golang操作Redis

19.5.1 安装第三方开源Redis库

特别说明:

​ 在安装Redis库前,确保已经安装并配置了git,因为是从github上下载安装Redis库的,需要使用到redis,如果没有安装配置过git,请参考:

https://www.cnblogs.com/shuaishuaidefeizhu/p/12678804.html

1、使用第三方开源的Redis库:https://github.com/garyburd/redigo

2、在使用Redis前,先安装第三方Redis库,在GOPATH 路径下执行安装指令: D:goproject> go get github.com/garyburd/redigo/redis

3、安装成功后,可以看到如下包

NINOOI.PNG

19.5.2 Set/Get接口

说明:通过Golang添加和获取key-value

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写入数据  string [key-value]
	_, err = conn.Do("Set", "name", "tomjerry猫猫")
	if err != nil {
		fmt.Println("set err=", err)
		return
	}

// 3、通过Go向Redis取出数据  string [key-value]
	r, err := redis.String(conn.Do("get", "name"))
	if err != nil {
		fmt.Println("get err=", err)
		return
	}
// 因为返回的 r  是interface{}
// 因为 name 对应的值是string,因此我们需要转换

	fmt.Println("操作OK
", r)
}

redis-cli 和 Go代码的运行结果

NINOOI.PNG

19.5.3 Golang操作Hash

对hash数据结构,是一个个放入和读取,代码如下:

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写入数据  string [key-value]
	_, err = conn.Do("HSet", "user01", "name", "jerrry")
	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取出数据  
	r1, err := redis.String(conn.Do("HGet", "user01", "name"))
	if err != nil {
		fmt.Println("Hget name err=", err)
		return
	}

	r2, err := redis.Int(conn.Do("HGet", "user01", "age"))
	if err != nil {
		fmt.Println("Hget age  err=", err)
		return
	}

// 因为返回的 r  是interface{}
// 因为 name 对应的值是string,因此我们需要转换

	fmt.Printf("操作OK r1=%v  r2=%v", r1, r2)
}

redis-cli 和 Go代码的运行结果

NmZfFH.png

19.5.4 批量 Set/Get数据

对hash数据结构,是批量放入和读取,代码如下:

核心代码:

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() //关闭

	_, err = conn.Do("HMSet", "user02", "name", "llllllll", "age", 22)
	if err != nil {
		fmt.Println("Hset err=", err)
		return
	}

	r3, err := redis.Strings(conn.Do("HMGet", "user02", "name", "age"))
	if err != nil {
		fmt.Println("Hget name err=", err)
		return
	}
	for i, v := range r3 {
		fmt.Printf("r[%d]=%s
", i, v)
	}
}

19.5.5 给数据设置有效时间

​ 通过Golang对Redis操作,给Key-val 设置有效时间,以秒为单位。

核心代码:

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

19.5.6 操作List

核心代码:

_, err = c.Do("lpush", "herolist", "no1:宋江", 30, "no2:林冲", 28)
r, err := redis.String(c.Do("rpop", "herolist"))

19.5.7 Golang操作连接池

​ 通过Golang对Redis操作,还可以通过Redis连接池,流程如下:

1、事先初始化一定数量的连接,放入到连接池

2、当Go需要操作Redis时,直接从Redis连接池取出连接即可

3、这样可以节省临时获取Redis连接的时间,从而提高效率。

4、示意图:

NZHfts.png

核心代码:

package main
import (
	"fmt"
	"github.com/garyburd/redigo/redis" //引入Redis包
)
var pool *redis.Pool
func init() {
	pool = &redis.Pool{
    	MaxIdle:8,  //最大空闲连接数
    	MaxActive:0, //表示和数据库最大连接数,0表示没有限制
    	IdleTimeout:100, //最大空闲时间
    	Dial:func()(redis.Conn,error){  //初始化连接的代码
        	return redis.Dial("tcp","localhost:6379")
    	},
	}
c := pool.Get()  //从连接池取出一个连接
pool.Close() //关闭连接池,一旦关闭连接池,就不能从连接池再取出连接。
}

案例:

package main
import (
	"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){  //初始化连接的代码
        	return 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.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()  //表示关闭连接池,则下面的汤姆猫2就取不出来,关闭这个注释则可以取出
	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)
}

结果:

MMIIII.PNG

原文地址:https://www.cnblogs.com/jiaxiaozia/p/13151565.html