目录

前言

一、Redigo

1.redigo连接redis服务器

2.set、get操作

2.List操作

3.Hash表

4.set

5.zset

6.连接池

7.事务

8. pipeline

二、go-redis

1.go-redis连接redis服务器

2. get、set操作

3. List操作

4. Hash

5. Set

6. ZSet

7. pipeline

8. 事务

9. 哨兵模式

10. 集群

总结


前言

刚学完redis,在此记录如何使用redis。redis有许多go语言的客户端包,都能实现对redis的操作。例如redigo、go-redis。

一、Redigo

1.redigo连接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")
}

2.set、get操作

  • 设置值
    _, 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

2.List操作

  • lpush key element1 element2:向列表左侧插入若干个元素
    // 从左边放入元素
    _, err = client.Do("lpush", "NBAplayer", "Jordon", "Kobe", "Lebron")
    if err != nil {
        fmt.Println("push element failed")
        return
    }
  • lrange key start end:返回范围内的所有元素
    // 取出所有元素
    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

3.Hash表

  • hset key field value:添加或修改hash类型key的field的值
    // 单个插入
    _, err = client.Do("HSet", "DSB", "name", "SB")
    if err != nil {
        fmt.Println("hset failed")
        return
    }
  • hmset key field1 value1 field2 value2:批量添加多个hash类型key的field值
    _, err = client.Do("HmSet", "DSB", "age", "18", "addr", "usa")
    if err != nil {
        fmt.Println("hmset failed")
        return
    }
  • hget key field:获取一个hash类型的key的field的值
    // 单个获取
    res5, err := redis.String(client.Do("Hget", "DSB", "name"))
    if err != nil {
        fmt.Println("hget element failed")
        return
    }
    fmt.Println(res5)
  • hmget key field1 field2:批量获取hash类型key多个field的value值
    // 批量获取
    res6, err := redis.Strings(client.Do("HmGet", "DSB", "name", "age", "addr"))
    if err != nil {
        fmt.Println("hmget failed")
        return
    }
    fmt.Println(res6)

4.set

  • sadd key member1 member2:向set中添加若干个元素
    _, 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
    }
  • smembers key:返回set中所有元素s
    res, err := redis.Strings(client.Do("smembers", "qin")) 
    if err != nil {
        fmt.Println("smembers failed, err:", err)
        return
    }
    fmt.Println(res)
  • sinter key1 key2:求key1、key2的交集
    res, err := redis.Strings(client.Do("sinter", "qin", "yi"))
    if err != nil {
        fmt.Println("sinter failed, err:", err)
        return
    }
    fmt.Println(res)
  • sdiff key1 key2:求key1、key2的差集
    res, err = redis.Strings(client.Do("sdiff", "qin", "yi"))
    if err != nil {
        fmt.Println("sinter failed, err:", err)
        return
    }
    fmt.Println(res)
  • sunion key1 key2:求key1、key2的并集
    res, err = redis.Strings(client.Do("sunion", "qin", "yi"))
    if err != nil {
        fmt.Println("sinter failed, err:", err)
        return
    }
    fmt.Println(res)
  • sismember key member:判断元素是否存在于set中
    res, err := redis.Bool(client.Do("sismember", "qin", "20")) 
    if err != nil {
        fmt.Println("sismember failed, err:", err)
    }
    fmt.Println(res) 
  • scard key:返回set中元素的个数
    res, err := redis.Int(client.Do("scard", "qin")) 
    if err != nil {
        fmt.Println("scard failed, err:", err)
    }
    fmt.Println(res) 
  • srem key member1 member2:移除set中指定元素
    res, err := redis.Int(client.Do("srem", "qin", 18)) 
    if err != nil {
        fmt.Println("srem failed, err:", err)
    }
    fmt.Println(res)  

5.zset

  • zadd key score member:添加若干个元素到zset,如果存在则覆盖
    _, 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
    }
  • zrem key member:删除zset中指定的元素
    _, err = client.Do("zrem", "RankOfNBAplayer", "JRSmith")
    if err != nil {
        fmt.Println("zrem failed, err:", err)
        return
    }

  • zscore key member:获取zset中指定元素的score值
    res, err := redis.Int(client.Do("zscore", "RankOfNBAplayer", "Jordon"))
    if err != nil {
        fmt.Println("zscore failed, err:", err)
        return
    }
    fmt.Println(res)

  • zrank key member:获取zset中指定元素的排名
    res, err := redis.Int(client.Do("zrank", "RankOfNBAplayer", "Jordon"))
    if err != nil {
        fmt.Println("zrank failed, err:", err)
        return
    }
    fmt.Println(res)

  • zcard key:获取zset中元素个数
    res, err := redis.Int(client.Do("zcard", "RankOfNBAplayer"))
    if err != nil {
        fmt.Println("zcard failed, err:", err)
        return
    }
    fmt.Println(res)

  • zcount key min max:统计score值在范围中的元素个数
    res, err := redis.Int(client.Do("zcount", "RankOfNBAplayer", 0, 3))
    if err != nil {
        fmt.Println("zcount failed, err:", err)
        return
    }
    fmt.Println(res)

  • zincrby key increment member:指定zset中指定元素的自增步长
    res, err := redis.Int(client.Do("zincrby", "RankOfNBAplayer", 10, "JRSmith"))
    if err != nil {
        fmt.Println("zincrby failed, err:", err)
        return
    }
    fmt.Println(res)

  • zrange key start end:获取范围内的元素
    res, err := redis.Strings(client.Do("zrange", "RankOfNBAplayer", 0, -1))
    if err != nil {
        fmt.Println("zincrby failed, err:", err)
        return
    }

  • zrangebyscore key min max:按照分数排序
    res, err := redis.Strings(client.Do("zrangebyscore", "RankOfNBAplayer", 0, 3))
    if err != nil {
        fmt.Println("zincrby failed, err:", err)
        return
    }
    fmt.Println(res)

6.连接池
 

// 创建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()
}

7.事务

    // 开启事务
    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)

8. pipeline

Send(),Flush(),Receive()支持管道化操作,Send()用于向连接的缓冲区写入命令,Flush()用于将缓冲区中的命令清空并写入服务端,Receive()按照先入先出的顺序依次读取服务端的响应。

二、go-redis

1.go-redis连接redis服务器

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
}

2. get、set操作

  • 设置值
    // 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])
	}

3. List操作

  • 从左边添加元素
    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)
  •  从list左边弹出一个元素
	res, err = rdb.LPop("NBAPlayer").Result()
	if err != nil {
		fmt.Println("pop failed", err)
		return
	}
	fmt.Println(res)

4. Hash

  • hset key field value:添加或修改hash类型key的field的值
	err = rdb.HSet("USA", "name", "dsb").Err()
	if err != nil {
		fmt.Println("Are you kidding? America Government is really sb")
		return
	}
  • hget key field:获取一个hash类型的key的field的值
	res, err = rdb.HGet("USA", "name").Result()
	if err != nil {
		fmt.Println("Are you kidding? America Government is really sb")
		return
	}
	fmt.Println(res)
  • hmset key field1 value1 field2 value2:批量添加多个hash类型key的field值
    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
	}
  • hmget key field1 field2:批量获取hash类型key多个field的value值
	res2 := rdb.HMGet("USA", "name2", "name").Val()
	fmt.Println(res2)

5. Set

  • sadd key member1 member2:向set中添加若干个元素
	err = rdb.SAdd("Chinese", "AiGuo", "JingYe", "ChengXin", "YouShan").Err()
	if err != nil {
		fmt.Println("Are you right? Chinese people are really great", err)
		return
	}
  • smembers key:返回set中所有元素s
	res3 := rdb.SMembers("Chinese").Val()
	fmt.Println(res3)
  • sismember key member:判断元素是否存在于set中
	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)
  • scard key:返回set中元素的个数
	count := rdb.SCard("Chinese").Val()
	fmt.Printf("The Chinese people have %d virtues\n", count)
    // virtues 品德

6. ZSet

  • zadd key score member:添加若干个元素到zset,如果存在则覆盖
	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")
  • zrem key member:删除zset中指定的元素
    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: ")
  • zrange key start end:获取范围内的元素
    val3 := rdb.ZRange(zsetKey, 0, -1).Val()
	fmt.Println(val3)
  • zincrby key increment member:指定zset中指定元素的自增步长
	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)
  • 选择分数在95-100之间的
	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)
	}
  •  取分数最高的3个
	res5, err := rdb.ZRevRangeWithScores(zsetKey, 0, 2).Result()
	if err != nil {
		fmt.Println("something wrong with zSetKey, err: ", err)
		return
	}
	fmt.Println(res5)

7. pipeline

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")
	}

8. 事务

 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

9. 哨兵模式

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
}

10. 集群

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,还是要根据情况选择使用。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐