2 Go 数据库IO(二):Redis操作
2019-07-08 本文已影响0人
GoFuncChan
一、Redis概述
Redis是一个内存数据结构存储系统。它主要有以下特点:
- 与其他数据库不同,它的数据主要存储在内存中,当然为了数据安全它也有磁盘存储备份。由于内存存储,所以它性能非常高。
- 与其他K-V缓存系统不同,它提供多种数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) ,甚至提供Sub/Pub机制,你可以以此构建简单的消息队列。
Redis中文网提供了完整的Redis命令文档,你可以进入学习相关的常用命令。
二、Go 使用Redis
Go中对redis的支持一般都使用第三方包,这里我们使用redigo,其github star 6k,有较高的使用或支持率,维护比较稳定,不用担心有大坑。
安装:
go get -u github.com/gomodule/redigo/redis
1.redigo的简单使用
import (
"fmt"
"github.com/garyburd/redigo/redis"
"strconv"
"time"
)
func BaseRedis() {
//go 连接Redis操作,类似拨号连接tcp,其端口号默认6379
conn, err := redis.Dial("tcp", "localhost:6379")
ErrorHandler(err, "redis.Dial")
defer conn.Close()
//执行一项操作时如果知道值返回类型可用以下写法
//一般Set类的设置值操作成功都返回"OK"
//Get类操作返回Int、String、Strings、Bool、Bytes、ByteSlices,Int等等,可先输出调试再用特定类型接收
//Set结果的原始类型string,值为OK
reply1, err := redis.String(conn.Do("Set", "name", "fun"))
ErrorHandler(err, "conn.Do:Set")
//Get结果的原始类型[]uint8,值为fun
reply2, err := redis.String(conn.Do("Get", "name"))
ErrorHandler(err, "conn.Do:Get")
//setex结果的原始类型string,值为OK
reply3, err := conn.Do("setex", "myname", "60", "bill")
ErrorHandler(err, "conn.Do:setex")
reply4, err := conn.Do("persist", "myname")
ErrorHandler(err, "conn.Do:persist")
reply5, err := conn.Do("mset", "age", "60", "gender", "male")
ErrorHandler(err, "conn.Do:mset")
reply6, err := conn.Do("hmset", "bangzhu", "name", "jobs", "age", 10000)
ErrorHandler(err, "conn.Do:hmset")
reply7, err := conn.Do("hgetall", "bangzhu")
ErrorHandler(err, "conn.Do:hgetall")
reply8, err := conn.Do("rpush", "mydearlist", 11, 22, 33)
ErrorHandler(err, "conn.Do:rpush")
reply9, err := conn.Do("lrange", "fucklist", 0, -1)
ErrorHandler(err, "conn.Do:lrange")
reply10, err := conn.Do("sadd", "mydearset", 1, 2, 3)
ErrorHandler(err, "conn.Do:sadd")
reply11, err := conn.Do("smembers", "mydearset")
ErrorHandler(err, "conn.Do:smembers")
reply12, err := conn.Do("zadd", "mz", 10, "bill", 9, "bangzhu", 8, "zuckberg")
ErrorHandler(err, "conn.Do:zadd")
reply13, err := conn.Do("zrange", "mz", 0, -1)
ErrorHandler(err, "conn.Do:zrange")
//输出执行结果
fmt.Printf("Set结果的原始类型%T,值为%v\n", reply1, reply1)
fmt.Printf("Get结果的原始类型%T,值为%v\n", reply2, reply2)
fmt.Printf("Setex结果的原始类型%T,值为%v\n", reply3, reply3)
fmt.Printf("persist结果的原始类型%T,值为%v\n", reply4, reply4)
fmt.Printf("mset结果的原始类型%T,值为%v\n", reply5, reply5)
fmt.Printf("hmset结果的原始类型%T,值为%v\n", reply6, reply6)
fmt.Printf("hgetall结果的原始类型%T,值为%s\n", reply7, reply7)
fmt.Printf("rpush结果的原始类型%T,值为%v\n", reply8, reply8)
fmt.Printf("lrange结果的原始类型%T,值为%v\n", reply9, reply9)
fmt.Printf("sadd结果的原始类型%T,值为%v\n", reply10, reply10)
fmt.Printf("smembers结果的原始类型%T,值为%s\n", reply11, reply11)
fmt.Printf("zadd结果的原始类型%T,值为%v\n", reply12, reply12)
fmt.Printf("zrange结果的原始类型%T,值为%s\n", reply13, reply13)
//输出执行结果
//Set结果的原始类型string,值为OK
//Get结果的原始类型string,值为fun
//Setex结果的原始类型string,值为OK
//persist结果的原始类型int64,值为1
//mset结果的原始类型string,值为OK
//hmset结果的原始类型string,值为OK
//hgetall结果的原始类型[]interface {},值为[name jobs age 10000]
//rpush结果的原始类型int64,值为21
//lrange结果的原始类型[]interface {},值为[]
//sadd结果的原始类型int64,值为0
//smembers结果的原始类型[]interface {},值为[1 2 3]
//zadd结果的原始类型int64,值为0
//zrange结果的原始类型[]interface {},值为[zuckberg bangzhu bill]
//zrange结果的原始类型[]interface {},值为[zuckberg bangzhu bill]
}
redigo内置连接池的实现:以下示例演示开启一个连接池最高活动连接数为50,最大闲置连接数为20。开启100个协程从连接池获取连接并执行命令。
//go redis 连接池
func BaseRedisPoll() {
//配置并获得一个连接池对象的指针
poolPtr := &redis.Pool{
//最大活动链接数。0为无限
MaxActive: 50,
//最大闲置链接数,0为无限
MaxIdle: 20,
//闲置链接超时时间
IdleTimeout: time.Second * 100,
Dial: func() (redis.Conn, error) {
conn, e := redis.Dial("tcp", "localhost:6379")
return conn, e
}}
defer poolPtr.Close()
for i := 1; i <= 100; i++ {
//并发100写入redis
go func(pool *redis.Pool, n int) {
//从连接池中获取一个连接
conn := poolPtr.Get()
//协程执行完成后释放连接
defer conn.Close()
key := "name" + strconv.Itoa(n)
fmt.Println(key)
_, err := redis.String(conn.Do("Set", key, n))
ErrorHandler(err, "conn.Do")
//fmt.Println(res)
}(poolPtr, i)
}
//为了让协程有足够时间执行,保持主协程存活,
//Tips:主协程死亡后协程也不存在!
time.Sleep(3 * time.Second)
fmt.Println("并发连接池执行完成!")
}
至此Redis的基本使用到此结束,更多使用方式会在实战篇展开。Redis常被用作数据层之上的缓存层,搭建redis缓存层可缓解数据库IO阻塞,从而加大系统地访问性能。另一个使用场景Redis也可以被设计成简单的Sub/Pub消息队列,以达到业务异步IO的功能。