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的客户端起来了
19.1.2 Redis基本操作原理图:
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个数据库
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
String(字符串) -CRUDE
举例说明Redis的String字符串的CRUD操作
set[如果存在就相当于修改,不存在就是添加]/get/del
String 使用注意事项
setex(set with expire)键秒值(以秒为单位),可以设置有限时间,定时器
mset[同时设置一个或多个 key-vale 对]
如果某个给定 key
已经存在,那么 MSET 会用新值覆盖原来的旧值
mget[一次返回多个key的值]
如果给定的 key
里面,有某个 key
不存在,那么这个 key
返回特殊值 nil
19.4.3 Hash (哈希 类似Golang里的Map)
Redis hash 是一个键值对集合。
Redis hash 是一个的、string类型的filed和value的映射表,hash特别适合用于存储对象。
Hash中的key不能重复。
举例,存放一个User信息
user1 name "smith" age 30 jb "golang"
Hash(哈希 类似golang里的map) - CRUD
举例说明Redis的Hash的CURD的基本操作
hset/hget/hgetall/hdel
Hash-使用细节和注意事项
再给user设置name和age时,前面是一步步设置,使用hmset 和 hmget可以一次性来设置多个 field的值和返回多个field的值
hlen 统计一个hasg有几个元素
19.4.4 List(列表)
列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到表的头部(左边)、或者尾部(右边)
List本质是个链表,List的元素是有序的,元素的值可以重复。
举例:存放多个地址信息
city 北京 天津 上海
List(列表) -CRUD
lpush/rpush/lrange/lpop/rpop/del
lrange解析:
List的演示
案例演示
List 使用细节和注意事项
1、lindex、按照索引下标获得元素(从左到右,编号从0开始)
2、LLEN key 返回列表key的长度,如果key不存在,则key被解释为一个空列表,返回0
3、List数据,可以从左或者右插入添加
4、如果值全部移除,对应的键也就消失了
19.4.5 Set(集合)
Redis的Set是string类型的无序集合。
底层是HashTable数据结构,Set也是存放很多字符串元素,字符串元素是无序的,而且元素的值不能重复
举例,存放多个电子邮件列表信息
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、安装成功后,可以看到如下包
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代码的运行结果
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代码的运行结果
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、示意图:
核心代码:
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)
}
结果: