目录
刚学完redis,在此记录如何使用redis。redis有许多go语言的客户端包,都能实现对redis的操作。例如redigo、go-redis。
package main
import (
"fmt"
"github.com/garyburd/redigo/redis"
)
func main() {
client, err := redis.Dial("tcp", "localhost:6379")
defer client.Close()
if err != nil {
fmt.Println("redis connect failed,", err)
return
}
fmt.Println("redis connect success")
}
_, err = client.Do("Set", "abc", 100)
if err != nil {
fmt.Println("set string failed", err)
return
}
_, err = client.Do("Set", "36D", "good")
if err != nil {
fmt.Println("set string failed", err)
return
}
// redigo 通过redis.Int()函数来获取整型
res, err := redis.Int(client.Do("Get", "abc"))
if err != nil {
fmt.Println("get string failed,", err)
return
}
fmt.Println(res)
// redigo 通过redis.String()函数来获取字符串
res1, err := redis.String(client.Do("Get", "36D"))
if err != nil {
fmt.Println("get string failed,", err)
return
}
fmt.Println(res1)
res3, err := redis.Strings(client.Do("MGet", "36", "32"))
if err != nil {
fmt.Println("get string failed,", err)
return
}
fmt.Println(res3)
// 设置过期时间
_, err = client.Do("setex" , "a", 2, "10")
if err != nil {
fmt.Println("set string failed", err)
return
}
res2, err := redis.String(client.Do("Get", "a"))
if err != nil {
fmt.Println("get string failed,", err)
return
}
fmt.Println(res2)
time.Sleep(5 * time.Second)
fmt.Println("5秒后")
res2, err = redis.String(client.Do("Get", "a"))
if err != nil {
fmt.Println("get string failed,", err)
return
}
fmt.Println(res2)
输出如下:
10
5秒后
get string failed, redigo: nil returned
// 从左边放入元素
_, err = client.Do("lpush", "NBAplayer", "Jordon", "Kobe", "Lebron")
if err != nil {
fmt.Println("push element failed")
return
}
// 取出所有元素
res4, err := redis.Strings(client.Do("lrange", "NBAplayer", "0", "-1"))
if err != nil {
fmt.Println("get element failed")
return
}
for _, v := range res4{
fmt.Println(v)
}
输出结果:
Lebron
Kobe
Jordon
// 单个插入
_, err = client.Do("HSet", "DSB", "name", "SB")
if err != nil {
fmt.Println("hset failed")
return
}
_, err = client.Do("HmSet", "DSB", "age", "18", "addr", "usa")
if err != nil {
fmt.Println("hmset failed")
return
}
// 单个获取
res5, err := redis.String(client.Do("Hget", "DSB", "name"))
if err != nil {
fmt.Println("hget element failed")
return
}
fmt.Println(res5)
// 批量获取
res6, err := redis.Strings(client.Do("HmGet", "DSB", "name", "age", "addr"))
if err != nil {
fmt.Println("hmget failed")
return
}
fmt.Println(res6)
_, err = client.Do("sadd", "qin", "18", "male", "handsome")
if err != nil {
fmt.Println("sadd failed, err:", err)
return
}
_, err = client.Do("sadd", "yi", "19", "male", "handsome")
if err != nil {
fmt.Println("sadd failed, err:", err)
return
}
res, err := redis.Strings(client.Do("smembers", "qin"))
if err != nil {
fmt.Println("smembers failed, err:", err)
return
}
fmt.Println(res)
res, err := redis.Strings(client.Do("sinter", "qin", "yi"))
if err != nil {
fmt.Println("sinter failed, err:", err)
return
}
fmt.Println(res)
res, err = redis.Strings(client.Do("sdiff", "qin", "yi"))
if err != nil {
fmt.Println("sinter failed, err:", err)
return
}
fmt.Println(res)
res, err = redis.Strings(client.Do("sunion", "qin", "yi"))
if err != nil {
fmt.Println("sinter failed, err:", err)
return
}
fmt.Println(res)
res, err := redis.Bool(client.Do("sismember", "qin", "20"))
if err != nil {
fmt.Println("sismember failed, err:", err)
}
fmt.Println(res)
res, err := redis.Int(client.Do("scard", "qin"))
if err != nil {
fmt.Println("scard failed, err:", err)
}
fmt.Println(res)
res, err := redis.Int(client.Do("srem", "qin", 18))
if err != nil {
fmt.Println("srem failed, err:", err)
}
fmt.Println(res)
_, err = client.Do("zadd", "RankOfNBAplayer", 1, "Jordon", 2, "LeBron", 3, "kobe", 4, "YaoMing", 5, "JRSmith")
if err != nil {
fmt.Println("zadd failed, err:", err)
return
}
_, err = client.Do("zrem", "RankOfNBAplayer", "JRSmith")
if err != nil {
fmt.Println("zrem failed, err:", err)
return
}
res, err := redis.Int(client.Do("zscore", "RankOfNBAplayer", "Jordon"))
if err != nil {
fmt.Println("zscore failed, err:", err)
return
}
fmt.Println(res)
res, err := redis.Int(client.Do("zrank", "RankOfNBAplayer", "Jordon"))
if err != nil {
fmt.Println("zrank failed, err:", err)
return
}
fmt.Println(res)
res, err := redis.Int(client.Do("zcard", "RankOfNBAplayer"))
if err != nil {
fmt.Println("zcard failed, err:", err)
return
}
fmt.Println(res)
res, err := redis.Int(client.Do("zcount", "RankOfNBAplayer", 0, 3))
if err != nil {
fmt.Println("zcount failed, err:", err)
return
}
fmt.Println(res)
res, err := redis.Int(client.Do("zincrby", "RankOfNBAplayer", 10, "JRSmith"))
if err != nil {
fmt.Println("zincrby failed, err:", err)
return
}
fmt.Println(res)
res, err := redis.Strings(client.Do("zrange", "RankOfNBAplayer", 0, -1))
if err != nil {
fmt.Println("zincrby failed, err:", err)
return
}
res, err := redis.Strings(client.Do("zrangebyscore", "RankOfNBAplayer", 0, 3))
if err != nil {
fmt.Println("zincrby failed, err:", err)
return
}
fmt.Println(res)
// 创建redis连接池
var pool *redis.Pool
func init() {
pool = &redis.Pool{
MaxIdle: 16, // 连接数量
MaxActive: 0, // 最大连接数量,不确定用0
IdleTimeout: 300, //连接关闭时间
Dial: func() (redis.Conn, error) { //需要连接的数据库
return redis.Dial("tcp", "localhost:6379")
},
}
}
func main() {
// 从连接池中获取连接
client := pool.Get()
// 把连接放回连接池
defer client.Close()
_, err := client.Do("Set", "CSDN", "good")
if err != nil {
fmt.Println("set string failed, err:", err)
return
}
res, err := redis.String(client.Do("Get", "CSDN"))
if err != nil {
fmt.Println("set string failed, err:", err)
return
}
fmt.Println(res)
// 关闭连接池
pool.Close()
}
// 开启事务
client.Send("MULTI")
client.Send("set", "k1", "v1")
client.Send("set", "k2", "v2")
// 执行事务
res, err := client.Do("EXEC")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(res)
Send(),Flush(),Receive()支持管道化操作,Send()用于向连接的缓冲区写入命令,Flush()用于将缓冲区中的命令清空并写入服务端,Receive()按照先入先出的顺序依次读取服务端的响应。
package main
import (
"fmt"
"github.com/go-redis/redis"
)
var rdb *redis.Client
func initRedisClient() (err error) {
rdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
_, err = rdb.Ping().Result()
if err != nil {
return err
}
return nil
}
// Set
err = rdb.Set("goland", "so good", 0).Err()
if err != nil {
fmt.Println(err)
return
}
获取值
// Get
res, err := rdb.Get("goland").Result()
if err != nil {
fmt.Println(err)
return
}
fmt.Println(res)
批量设置
err = rdb.MSet("Go", "NO1", "C++", "NO1", "JAVA", "NO1", "PYTHON", "NO1").Err()
if err != nil {
fmt.Println("MSet failed, err: ", err)
return
}
res1, err := rdb.MGet("Go", "C++", "JAVA", "PYTHON").Result()
if err != nil {
fmt.Println(err)
return
}
for i, _ := range res1 {
fmt.Println(res1[i])
}
err = rdb.LPush("NBAPlayer", "kobe", "kawhi").Err()
if err != nil {
fmt.Println("Push failed", err)
return
}
获取list中所有元素
val := rdb.LRange("NBAPlayer", 0, -1).Val()
fmt.Println(val)
res, err = rdb.LPop("NBAPlayer").Result()
if err != nil {
fmt.Println("pop failed", err)
return
}
fmt.Println(res)
err = rdb.HSet("USA", "name", "dsb").Err()
if err != nil {
fmt.Println("Are you kidding? America Government is really sb")
return
}
res, err = rdb.HGet("USA", "name").Result()
if err != nil {
fmt.Println("Are you kidding? America Government is really sb")
return
}
fmt.Println(res)
usaMap := map[string]interface{}{"name": "dsb", "name2": "robber"}
err = rdb.HMSet("USA", usaMap).Err()
if err != nil {
fmt.Println("Are you kidding? America Government is really sb")
return
}
res2 := rdb.HMGet("USA", "name2", "name").Val()
fmt.Println(res2)
err = rdb.SAdd("Chinese", "AiGuo", "JingYe", "ChengXin", "YouShan").Err()
if err != nil {
fmt.Println("Are you right? Chinese people are really great", err)
return
}
res3 := rdb.SMembers("Chinese").Val()
fmt.Println(res3)
res4, err := rdb.SIsMember("Chinese", "AiGuo").Result() // 这里返回的是bool
if err != nil {
fmt.Println("You're mistaken")
return
}
fmt.Println("I can see that the Chinese are really AiGuo is", res4)
count := rdb.SCard("Chinese").Val()
fmt.Printf("The Chinese people have %d virtues\n", count)
// virtues 品德
zsetKey := "language"
languages := []redis.Z{
redis.Z{Score: 99, Member: "Go"},
redis.Z{Score: 97, Member: "C++"},
redis.Z{Score: 93, Member: "PYTHON"},
redis.Z{Score: 95, Member: "Java"},
redis.Z{Score: 98, Member: "C"},
}
count, err = rdb.ZAdd(zsetKey, languages...).Result()
if err != nil {
fmt.Println("fuck America Government, failed: ", err)
return
}
fmt.Println("zAdd succ")
count, err = rdb.ZRem(zsetKey, "C").Result()
if err != nil {
fmt.Println("fuck America Government, ZRem failed: ", err)
return
}
fmt.Println("fuck America Government, ZRem success: ")
val3 := rdb.ZRange(zsetKey, 0, -1).Val()
fmt.Println(val3)
score, err := rdb.ZIncrBy(zsetKey, 3, "C++").Result()
if err != nil {
fmt.Println("ZIncrBy failed, err: ", err)
return
}
fmt.Println("the new score is", score)
res6, err := rdb.ZRangeByScoreWithScores(zsetKey, redis.ZRangeBy{
Min: "95", Max: "100"}).Result()
if err != nil {
fmt.Println("something wrong with ZRangeByScoreWithScores, err: ", err)
return
}
for i, _ := range res6 {
fmt.Println(res6[i].Member, res6[i].Score)
}
res5, err := rdb.ZRevRangeWithScores(zsetKey, 0, 2).Result()
if err != nil {
fmt.Println("something wrong with zSetKey, err: ", err)
return
}
fmt.Println(res5)
pipeline本质上意味着客户端缓冲一堆命令并一次性将它们发送到服务器,这样做的好处是节省了每个命令的网络往返时间(RTT)。
pipeline := rdb.Pipeline()
pipeline.Set("key1", "val1", time.Hour)
pipeline.Set("key2", "val2", time.Hour)
pipeline.Set("key3", "val3", time.Hour)
pipeline.Set("key4", "val4", time.Hour)
pipeline.Set("key5", "val5", time.Hour)
_, err = pipeline.Exec()
if err != nil {
fmt.Println("set success")
}
multi/exec能够确保在multi/exec两个语句之间的命令之间没有其他客户端正在执行命令,TxPipeline内部会使用multi/exec包裹排队命令:
pipeline := rdb.TxPipeline()
pipeline.Set("key11", "val11", time.Hour)
pipeline.Set("key21", "val21", time.Hour)
pipeline.Set("key31", "val31", time.Hour)
pipeline.Set("key41", "val41", time.Hour)
pipeline.Set("key51", "val51", time.Hour)
_, err = pipeline.Exec()
上面代码相当于在一个RTT下执行了下面的redis命令:
MULTI
SET KEY11 VAL11
SET KEY21 VAL21
SET KEY31 VAL31
SET KEY41 VAL41
SET KEY51 VAL51
EXEC
func initClient()(err error){
rdb := redis.NewFailoverClient(&redis.FailoverOptions{
MasterName: "master",
SentinelAddrs: []string{"x.x.x.x:26379", "xx.xx.xx.xx:26379", "xxx.xxx.xxx.xxx:26379"},
})
_, err = rdb.Ping().Result()
if err != nil {
return err
}
return nil
}
func initClient()(err error){
rdb := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{":7000", ":7001", ":7002", ":7003", ":7004", ":7005"},
})
_, err = rdb.Ping().Result()
if err != nil {
return err
}
return nil
}
本文仅仅简单介绍了如何使用go语言操作redis,分别展示了两种客户端包如何实现对redis的访问和操作,并展示了redis的部分指令,而redis提供的指令远不止这些。写博客的过程中,个人还是感觉Redigo使用起来更加易懂,而go-redis支持连接哨兵和集群模式的redis,还是要根据情况选择使用。