• Go-连接Redis-学习go-redis包


    Redis介绍

    Redis是一个开源的内存数据结构存储,常用作数据库、缓存和消息代理。目前它支持的数据结构有诸如string、hash、list、set、zset、bitmap、hyperloglog、geospatial index和stream。Redis内置了复制、Lua脚本、LRU清除、事务和不同级别的磁盘持久性,并通过Redis Sentinel提供高可用性,通过Redis Cluster自动分区。

    go-redis库

    安装

    区别于另一个比较常用的Go语言redis client库:redigo,我们这里采用https://github.com/go-redis/redis连接Redis数据库并进行操作,因为go-redis支持连接哨兵及集群模式的Redis。

    使用以下命令下载并安装:

    go get -u github.com/go-redis/redis
    

    连接

    普通连接
    // 声明一个全局的rdb变量
    var rdb *redis.Client
    
    // 初始化连接
    func initClient() (err error) {
            // 通过 redis.NewClient 函数即可创建一个 redis 客户端, 这个方法接收一个 redis.Options 对象参数, 通过这个参数, 我们可以配置 redis 相关的属性, 例如 redis 服务器地址, 数据库名, 数据库密码等。
    	rdb = redis.NewClient(&redis.Options{
    		Addr:     "localhost:6379",
    		Password: "", // no password set
    		DB:       0,  // use default DB
    	})
            // 通过 cient.Ping() 来检查是否成功连接到了 redis 服务器
    	_, err = rdb.Ping().Result()
    	if err != nil {
    		return err
    	}
    	return nil
    }
    
    连接Redis哨兵模式
    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
    }
    
    连接Redis集群
    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 的连接。
    默认情况下,连接池大小是10, 可以通过 redis.Options 的 PoolSize 属性, 我们设置了 redis 连接池的大小为5。

    func GetRedisClientPool() *Client{
        redisdb := NewClient(&Options{
            Addr: "127.0.0.1:6379",
            Password: "",
            DB: 0,
            PoolSize: 5,})
    
        pong, err := redisdb.Ping().Result()
        if err != nil {
            fmt.Println(pong, err)
        }
        return redisdb
    }
    
    // 连接池测试
    func connectPoolTest() {
        fmt.Println("-----------------------welcome to connect Pool Test-----------------------")
        client :=GetRedisClientPool()
        wg := sync.WaitGroup{}
        wg.Add(10)
    
        for i := 0; i < 10; i++ {
            go func() {
                defer wg.Done()
    
                for j := 0; j < 1000; j++ {
                    client.Set(fmt.Sprintf("name%d", j), fmt.Sprintf("xys%d", j), 0).Err()
                    client.Get(fmt.Sprintf("name%d", j)).Result()
                }
    
                fmt.Printf("PoolStats, TotalConns: %d, IdleConns: %d
    ", client.PoolStats().TotalConns, client.PoolStats().IdleConns);
            }()
        }
    
        wg.Wait()
    }
    

    基本使用

    String 操作
    • Set(key, value):给数据库中名称为key的string赋予值valueget(key):返回数据库中名称为key的string的value
    • GetSet(key, value):给名称为key的string赋予上一次的value
    • MGet(key1, key2,…, key N):返回库中多个string的value
    • SetNX(key, value):添加string,名称为key,值为value
    • SetXX(key, time, value):向库中添加string,设定过期时间time
    • MSet(key N, value N):批量设置多个string的值
    • MSetNX(key N, value N):如果所有名称为key i的string都不存在
    • Incr(key):名称为key的string增1操作
    • Incrby(key, integer):名称为key的string增加integer
    • Decr(key):名称为key的string减1操作
    • Decrby(key, integer):名称为key的string减少integer
    • Append(key, value):名称为key的string的值附加valuesubstr(key, start, end):返回名称为key的string的value的子串
       
    func redisExample() {
    	err := rdb.Set("score", 100, 0).Err()
    	if err != nil {
    		fmt.Printf("set score failed, err:%v
    ", err)
    		return
    	}
    
    	val, err := rdb.Get("score").Result()
    	if err != nil {
    		fmt.Printf("get score failed, err:%v
    ", err)
    		return
    	}
    	fmt.Println("score", val)
    
    	val2, err := rdb.Get("name").Result()
    	if err == redis.Nil {
    		fmt.Println("name does not exist")
    	} else if err != nil {
    		fmt.Printf("get name failed, err:%v
    ", err)
    		return
    	} else {
    		fmt.Println("name", val2)
    	}
    }
    
    func StringDemo() {
        fmt.Println("-----------------------welcome to StringDemo-----------------------")
        redisClient:=GetRedisClient()
        if redisClient ==nil{
            fmt.Errorf("StringDemo redisClient is nil")
            return
        }
    
        name := "张三"
        key :="name:zhangsan"
        redisClient.Set(key , name,1 * time.Second)
        val := redisClient.Get(key)
        if val == nil {
            fmt.Errorf("StringDemo get error")
        }
        fmt.Println("name", val)
    }
    
    List 操作
    • RPush(key, value):在名称为key的list尾添加一个值为value的元素
    • LPush(key, value):在名称为key的list头添加一个值为value的元素
    • LLen(key):返回名称为key的list的长度
    • LRange(key, start, end):返回名称为key的list中start至end之间的元素
    • LTrim(key, start, end):截取名称为key的list
    • LIndex(key, index):返回名称为key的list中index位置的元素
    • LSet(key, index, value):给名称为key的list中index位置的元素赋值
    • LRem(key, count, value):删除count个key的list中值为value的元素
    • LPop(key):返回并删除名称为key的list中的首元素
    • RPop(key):返回并删除名称为key的list中的尾元素
    • BLPop(key1, key2,… key N, timeout):lpop命令的block版本。
    • BRPop(key1, key2,… key N, timeout):rpop的block版本。
    • RPopLPush(srckey, dstkey):返回并删除名称为srckey的list的尾元素,并将该元素添加到名称为dstkey的list的头部
    func ListDemo(){
        fmt.Println("-----------------------welcome to ListDemo-----------------------")
        redisClient:=GetRedisClient()
        if redisClient == nil {
            fmt.Errorf("ListDemo redisClient is nil")
            return
        }
        articleKey := "article"
        result,err:=redisClient.RPush(articleKey, "a","b","c").Result() //
        if err!=nil {
            fmt.Println(err)
            return
        }
        fmt.Println("result:",result)
    
        result,err = redisClient.LPush(articleKey, "d").Result() //
        if err!=nil {
            fmt.Println(err)
            return
        }
        fmt.Println("result:",result)
    
        length, err := redisClient.LLen(articleKey).Result()
        if err != nil {
            fmt.Println("ListDemo LLen is nil")
        }
        fmt.Println("length: ", length) // 长度
    
        mapOut,err1:=redisClient.LRange(articleKey,0,100).Result()
        if err1!=nil {
            fmt.Println(err1)
            return
        }
        for inx, item := range mapOut {
            fmt.Printf("
     %s:%s", inx, item)
        }
    }
    
    Hash操作
    • HSet(key, field, value):向名称为key的hash中添加元素field
    • HGet(key, field):返回名称为key的hash中field对应的value
    • HMget(key, (fields)):返回名称为key的hash中field i对应的value
    • HMset(key, (fields)):向名称为key的hash中添加元素field
    • HIncrby(key, field, integer):将名称为key的hash中field的value增加integer
    • HExists(key, field):名称为key的hash中是否存在键为field的域
    • HDel(key, field):删除名称为key的hash中键为field的域
    • HLen(key):返回名称为key的hash中元素个数
    • HKeys(key):返回名称为key的hash中所有键
    • HVals(key):返回名称为key的hash中所有键对应的value
    • HGetall(key):返回名称为key的hash中所有的键(field)及其对应的value
    func HashDemo() {
        fmt.Println("-----------------------welcome to HashDemo-----------------------")
        redisClient := GetRedisClient()
        if redisClient == nil {
            fmt.Errorf("HashDemo redisClient is nil")
            return
        }
        article := Article{18, "测试文章内容22222", "测试文章内容22222测试文章内容22222测试文章内容22222", 10, 0}
        articleKey := "article:18"
     
        redisClient.HMSet(articleKey, ToStringDictionary(&article))
        mapOut := redisClient.HGetAll(articleKey).Val()
        for inx, item := range mapOut {
            fmt.Printf("
     %s:%s", inx, item)
        }
        fmt.Print("
    ")
     
        redisClient.HSet(articleKey, "Content", "测试文章内容")
        mapOut = redisClient.HGetAll(articleKey).Val()
        for inx, item := range mapOut {
            fmt.Printf("
     %s:%s", inx, item)
        }
        fmt.Print("
    ")
     
        view, err := redisClient.HIncrBy(articleKey, "Views", 1).Result()
        if err != nil {
            fmt.Printf("
     HIncrBy error=%s ", err)
        } else {
            fmt.Printf("
     HIncrBy Views=%d ", view)
        }
        fmt.Print("
    ")
     
        mapOut = redisClient.HGetAll(articleKey).Val()
        for inx, item := range mapOut {
            fmt.Printf("
     %s:%s", inx, item)
        }
        fmt.Print("
    ")
    }
    
    zset示例
    func redisExample2() {
    	zsetKey := "language_rank"
    	languages := []*redis.Z{
    		&redis.Z{Score: 90.0, Member: "Golang"},
    		&redis.Z{Score: 98.0, Member: "Java"},
    		&redis.Z{Score: 95.0, Member: "Python"},
    		&redis.Z{Score: 97.0, Member: "JavaScript"},
    		&redis.Z{Score: 99.0, Member: "C/C++"},
    	}
    	// ZADD
    	num, err := rdb.ZAdd(zsetKey, languages...).Result()
    	if err != nil {
    		fmt.Printf("zadd failed, err:%v
    ", err)
    		return
    	}
    	fmt.Printf("zadd %d succ.
    ", num)
    
    	// 把Golang的分数加10
    	newScore, err := rdb.ZIncrBy(zsetKey, 10.0, "Golang").Result()
    	if err != nil {
    		fmt.Printf("zincrby failed, err:%v
    ", err)
    		return
    	}
    	fmt.Printf("Golang's score is %f now.
    ", newScore)
    
    	// 取分数最高的3个
    	ret, err := rdb.ZRevRangeWithScores(zsetKey, 0, 2).Result()
    	if err != nil {
    		fmt.Printf("zrevrange failed, err:%v
    ", err)
    		return
    	}
    	for _, z := range ret {
    		fmt.Println(z.Member, z.Score)
    	}
    
    	// 取95~100分的
    	op := &redis.ZRangeBy{
    		Min: "95",
    		Max: "100",
    	}
    	ret, err = rdb.ZRangeByScoreWithScores(zsetKey, op).Result()
    	if err != nil {
    		fmt.Printf("zrangebyscore failed, err:%v
    ", err)
    		return
    	}
    	for _, z := range ret {
    		fmt.Println(z.Member, z.Score)
    	}
    }
    
    // 输出结果如下:
    $ ./06redis_demo 
    zadd 0 succ.
    Golang's score is 100.000000 now.
    Golang 100
    C/C++ 99
    Java 98
    JavaScript 97
    Java 98
    C/C++ 99
    Golang 100
    

    完整代码

    package main
    
    import (
        "fmt"
        . "github.com/go-redis/redis"
        . "redisDemo/models"
        "time"
        "sync"
    )
    
    func main() {
        fmt.Println("-----------------------welcome to redisdemo-----------------------")
        //StringDemo()
        //ListDemo()
        //HashDemo()
        connectPoolTest()
    }
    
    func StringDemo() {
        fmt.Println("-----------------------welcome to StringDemo-----------------------")
        redisClient:=GetRedisClient()
        if redisClient ==nil{
            fmt.Errorf("StringDemo redisClient is nil")
            return
        }
    
        name := "张三"
        key :="name:zhangsan"
        redisClient.Set(key , name,1 * time.Second)
        val := redisClient.Get(key)
        if val == nil {
            fmt.Errorf("StringDemo get error")
        }
        fmt.Println("name", val)
    }
    
    func ListDemo(){
        fmt.Println("-----------------------welcome to ListDemo-----------------------")
        redisClient:=GetRedisClient()
        if redisClient == nil {
            fmt.Errorf("ListDemo redisClient is nil")
            return
        }
        articleKey := "article"
        result,err:=redisClient.RPush(articleKey, "a","b","c").Result() //在名称为 key 的list尾添加一个值为value的元素
        if err!=nil {
            fmt.Println(err)
            return
        }
        fmt.Println("result:",result)
    
        result,err = redisClient.LPush(articleKey, "d").Result() //在名称为 key 的list头添加一个值为value的元素
        if err!=nil {
            fmt.Println(err)
            return
        }
        fmt.Println("result:",result)
    
        length, err := redisClient.LLen(articleKey).Result()
        if err != nil {
            fmt.Println("ListDemo LLen is nil")
        }
        fmt.Println("length: ", length) // 长度
    
        mapOut,err1:=redisClient.LRange(articleKey,0,100).Result()
        if err1!=nil {
            fmt.Println(err1)
            return
        }
        for inx, item := range mapOut {
            fmt.Printf("
     %s:%s", inx, item)
        }
    }
    
    func HashDemo() {
        fmt.Println("-----------------------welcome to HashDemo-----------------------")
        redisClient := GetRedisClient()
        if redisClient == nil {
            fmt.Errorf("HashDemo redisClient is nil")
            return
        }
        article := Article{18, "测试文章内容22222", "测试文章内容22222测试文章内容22222测试文章内容22222", 10, 0}
        articleKey := "article:18"
    
        redisClient.HMSet(articleKey, ToStringDictionary(&article))
        mapOut := redisClient.HGetAll(articleKey).Val()
        for inx, item := range mapOut {
            fmt.Printf("
     %s:%s", inx, item)
        }
        fmt.Print("
    ")
    
        redisClient.HSet(articleKey, "Content", "测试文章内容")
        mapOut = redisClient.HGetAll(articleKey).Val()
        for inx, item := range mapOut {
            fmt.Printf("
     %s:%s", inx, item)
        }
        fmt.Print("
    ")
    
        view, err := redisClient.HIncrBy(articleKey, "Views", 1).Result()
        if err != nil {
            fmt.Printf("
     HIncrBy error=%s ", err)
        } else {
            fmt.Printf("
     HIncrBy Views=%d ", view)
        }
        fmt.Print("
    ")
    
        mapOut = redisClient.HGetAll(articleKey).Val()
        for inx, item := range mapOut {
            fmt.Printf("
     %s:%s", inx, item)
        }
        fmt.Print("
    ")
    
    }
    
    func GetRedisClient() *Client {
        redisdb := NewClient(&Options{
            Addr:     "127.0.0.1:6379",
            Password: "", // no password set
            DB:       0,                 // use default DB
        })
    
        pong, err := redisdb.Ping().Result()
        if err != nil {
            fmt.Println(pong, err)
        }
        return redisdb
    }
    
    func GetRedisClientPool() *Client{
        redisdb := NewClient(&Options{
            Addr: "127.0.0.1:6379",
            Password: "",
            DB: 0,
            PoolSize: 5,})
    
        pong, err := redisdb.Ping().Result()
        if err != nil {
            fmt.Println(pong, err)
        }
        return redisdb
    }
    
    // 连接池测试
    func connectPoolTest() {
        fmt.Println("-----------------------welcome to connect Pool Test-----------------------")
        client :=GetRedisClientPool()
        wg := sync.WaitGroup{}
        wg.Add(10)
    
        for i := 0; i < 10; i++ {
            go func() {
                defer wg.Done()
    
                for j := 0; j < 1000; j++ {
                    client.Set(fmt.Sprintf("name%d", j), fmt.Sprintf("xys%d", j), 0).Err()
                    client.Get(fmt.Sprintf("name%d", j)).Result()
                }
    
                fmt.Printf("PoolStats, TotalConns: %d, IdleConns: %d
    ", client.PoolStats().TotalConns, client.PoolStats().IdleConns);
            }()
        }
        wg.Wait()
    }
    
  • 相关阅读:
    前端iframe跨域传值笔记
    css 将第1/n行文本超出部分替换成省略号
    第一章:1-08、计算机网络中的主干网和本地接入网各有何特点?
    第一章:1-07、 计算机网络可从哪几个方面进行分类?
    第一章:1-06、 试将TCP/IP和OSI的体系结构进行比较。讨论其异同之处?
    第一章:1-05、试讨论在广播式网络中对网络层的处理方法。讨论是否需要这一层?
    第一章:1-04、为什么说因特网是自由印刷术以来人类通信方面最大的变革?
    第一章:1-03、试从多个方面比较电路交换、报文交换和分组交换的主要优缺点。
    第一章:1-02、试简述分组交换的要点。
    第一章:1-01、计算机网络的发展可划分为几个阶段?每个阶段各有何特点?
  • 原文地址:https://www.cnblogs.com/Paul-watermelon/p/14211394.html
Copyright © 2020-2023  润新知