zoukankan      html  css  js  c++  java
  • 使用Goland操作Redis详解

    String 操作

    redis 的 String 操作有:

    set(key, value):给数据库中名称为key的string赋予值value
    get(key):返回数据库中名称为key的string的value
    getset(key, value):给名称为key的string赋予上一次的value
    mget(key1, key2,…, key N):返回库中多个string的value
    setnx(key, value):添加string,名称为key,值为value
    setex(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的值附加value
    substr(key, start, end):返回名称为key的string的value的子串

    在 go-redis 中, 我们可以直接找到对应的操作方法, 直接上代码:

    // String 操作
    func stringOperation(client *redis.Client) {
        // 第三个参数是过期时间, 如果是0, 则表示没有过期时间.
        err := client.Set("name", "xys", 0).Err()
        if err != nil {
            panic(err)
        }
    
        val, err := client.Get("name").Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("name", val)
    
    
        // 这里设置过期时间.
        err = client.Set("age", "20", 1 * time.Second).Err()
        if err != nil {
            panic(err)
        }
    
        client.Incr("age") // 自增
        client.Incr("age") // 自增
        client.Decr("age") // 自减
    
        val, err = client.Get("age").Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("age", val) // age 的值为21
    
        // 因为 key "age" 的过期时间是一秒钟, 因此当一秒后, 此 key 会自动被删除了.
        time.Sleep(1 * time.Second)
        val, err = client.Get("age").Result()
        if err != nil {
            // 因为 key "age" 已经过期了, 因此会有一个 redis: nil 的错误.
            fmt.Printf("error: %v
    ", err)
        }
        fmt.Println("age", val)
    }

    list 操作

    redis 的 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的头部

    同样地, 在 go-redis 中也可以找到对应的方法, 下面是一个简单的示例:

    // list 操作
    func listOperation(client *redis.Client) {
        client.RPush("fruit", "apple") //在名称为 fruit 的list尾添加一个值为value的元素
        client.LPush("fruit", "banana") //在名称为 fruit 的list头添加一个值为value的 元素
        length, err := client.LLen("fruit").Result() //返回名称为 fruit 的list的长度
        if err != nil {
            panic(err)
        }
        fmt.Println("length: ", length) // 长度为2
    
        value, err := client.LPop("fruit").Result() //返回并删除名称为 fruit 的list中的首元素
        if err != nil {
            panic(err)
        }
        fmt.Println("fruit: ", value)
    
        value, err = client.RPop("fruit").Result() // 返回并删除名称为 fruit 的list中的尾元素
        if err != nil {
            panic(err)
        }
        fmt.Println("fruit: ", value)
    }

    set 操作

    redis 的 set 操作:

    sadd(key, member):向名称为key的set中添加元素member
    srem(key, member) :删除名称为key的set中的元素member
    spop(key) :随机返回并删除名称为key的set中一个元素
    smove(srckey, dstkey, member) :移到集合元素
    scard(key) :返回名称为key的set的基数
    sismember(key, member) :member是否是名称为key的set的元素
    sinter(key1, key2,…key N) :求交集
    sinterstore(dstkey, (keys)) :求交集并将交集保存到dstkey的集合
    sunion(key1, (keys)) :求并集
    sunionstore(dstkey, (keys)) :求并集并将并集保存到dstkey的集合
    sdiff(key1, (keys)) :求差集
    sdiffstore(dstkey, (keys)) :求差集并将差集保存到dstkey的集合
    smembers(key) :返回名称为key的set的所有元素
    srandmember(key) :随机返回名称为key的set的一个元素

    接下来是 go-redis 的 set 操作:

    // set 操作
    func setOperation(client *redis.Client) {
        client.SAdd("blacklist", "Obama") // 向 blacklist 中添加元素
        client.SAdd("blacklist", "Hillary") // 再次添加
        client.SAdd("blacklist", "the Elder") // 添加新元素
    
        client.SAdd("whitelist", "the Elder") // 向 whitelist 添加元素
    
        // 判断元素是否在集合中
        isMember, err := client.SIsMember("blacklist", "Bush").Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("Is Bush in blacklist: ", isMember)
    
    
        // 求交集, 即既在黑名单中, 又在白名单中的元素
        names, err := client.SInter("blacklist", "whitelist").Result()
        if err != nil {
            panic(err)
        }
        // 获取到的元素是 "the Elder"
        fmt.Println("Inter result: ", names)
    
    
        // 获取指定集合的所有元素
        all, err := client.SMembers("blacklist").Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("All member: ", all)
    }

    hash 操作

    redis 的 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

    go-redis 中的 hash 操作:

    // hash 操作
    func hashOperation(client *redis.Client) {
        client.HSet("user_xys", "name", "xys"); // 向名称为 user_xys 的 hash 中添加元素 name
        client.HSet("user_xys", "age", "18"); // 向名称为 user_xys 的 hash 中添加元素 age
    
        // 批量地向名称为 user_test 的 hash 中添加元素 name 和 age
        client.HMSet("user_test", map[string]string{"name": "test", "age":"20"})
        // 批量获取名为 user_test 的 hash 中的指定字段的值.
        fields, err := client.HMGet("user_test", "name", "age").Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("fields in user_test: ", fields)
    
    
        // 获取名为 user_xys 的 hash 中的字段个数
        length, err := client.HLen("user_xys").Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("field count in user_xys: ", length) // 字段个数为2
    
        // 删除名为 user_test 的 age 字段
        client.HDel("user_test", "age")
        age, err := client.HGet("user_test", "age").Result()
        if err != nil {
            fmt.Printf("Get user_test age error: %v
    ", err)
        } else {
            fmt.Println("user_test age is: ", age) // 字段个数为2
        }
    }

    关于连接池

    redis.v4 包实现了 redis 的连接池管理, 因此我们就不需要自己手动管理 redis 的连接了.
    默认情况下, redis.v4 的 redis 连接池大小是10, 不过我们可以在初始化 redis 客户端时自行设置连接池的大小, 例如:

    client := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379",
        Password: "",
        DB:       0,
        PoolSize: 5,
    })

    通过 redis.Options 的 PoolSize 属性, 我们设置了 redis 连接池的大小为5.
    那么接下来我们来看一下这个设置有什么效果吧:

    // redis.v4 的连接池管理
    func connectPool(client *redis.Client) {
        wg := sync.WaitGroup{}
        wg.Add(10)
    
        for i := 0; i < 10; i++ {
            go func() {
                defer wg.Done()
    
                for j := 0; j < 100; 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, FreeConns: %d
    ", client.PoolStats().TotalConns, client.PoolStats().FreeConns);
            }()
        }
    
        wg.Wait()
    }

    上面的例子启动了10个 routine 来不断向 redis 读写数据, 然后我们通过 client.PoolStats() 获取连接池的信息. 运行这个例子, 输出如下:

    PoolStats, TotalConns: 5, FreeConns: 1
    PoolStats, TotalConns: 5, FreeConns: 1
    PoolStats, TotalConns: 5, FreeConns: 1
    PoolStats, TotalConns: 5, FreeConns: 1
    PoolStats, TotalConns: 5, FreeConns: 1
    PoolStats, TotalConns: 5, FreeConns: 2
    PoolStats, TotalConns: 5, FreeConns: 2
    PoolStats, TotalConns: 5, FreeConns: 3
    PoolStats, TotalConns: 5, FreeConns: 4
    PoolStats, TotalConns: 5, FreeConns: 5

    通过输出可以看到, 此时最大的连接池数量确实是 5 了, 并且一开始时, 因为 coroutine 的数量大于5, 会造成 redis 连接不足的情况(反映在 FreeConns 上就是前几次的输出 FreeConns 一直是1), 当某个 coroutine 结束后, 会释放此 redis 连接, 因此 FreeConns 会增加.

    完整示例

    //
    // author xiongyongshun
    // project go_redis
    // version 1.0
    // created 16/10/6 03:49
    //
    package main
    
    import (
        "fmt"
        "gopkg.in/redis.v4"
        "time"
        "sync"
    )
    
    func main() {
        client := createClient()
        defer client.Close()
    
        stringOperation(client)
        listOperation(client)
        setOperation(client)
        hashOperation(client)
    
        connectPool(client)
    
    }
    
    // 创建 redis 客户端
    func createClient() *redis.Client {
        client := redis.NewClient(&redis.Options{
            Addr:     "localhost:6379",
            Password: "",
            DB:       0,
            PoolSize: 5,
        })
    
        pong, err := client.Ping().Result()
        fmt.Println(pong, err)
    
        return client
    }
    
    
    // String 操作
    func stringOperation(client *redis.Client) {
        // 第三个参数是过期时间, 如果是0, 则表示没有过期时间.
        err := client.Set("name", "xys", 0).Err()
        if err != nil {
            panic(err)
        }
    
        val, err := client.Get("name").Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("name", val)
    
    
        // 这里设置过期时间.
        err = client.Set("age", "20", 1 * time.Second).Err()
        if err != nil {
            panic(err)
        }
    
        client.Incr("age") // 自增
        client.Incr("age") // 自增
        client.Decr("age") // 自减
    
        val, err = client.Get("age").Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("age", val) // age 的值为21
    
        // 因为 key "age" 的过期时间是一秒钟, 因此当一秒后, 此 key 会自动被删除了.
        time.Sleep(1 * time.Second)
        val, err = client.Get("age").Result()
        if err != nil {
            // 因为 key "age" 已经过期了, 因此会有一个 redis: nil 的错误.
            fmt.Printf("error: %v
    ", err)
        }
        fmt.Println("age", val)
    }
    
    // list 操作
    func listOperation(client *redis.Client) {
        client.RPush("fruit", "apple") //在名称为 fruit 的list尾添加一个值为value的元素
        client.LPush("fruit", "banana") //在名称为 fruit 的list头添加一个值为value的 元素
        length, err := client.LLen("fruit").Result() //返回名称为 fruit 的list的长度
        if err != nil {
            panic(err)
        }
        fmt.Println("length: ", length) // 长度为2
    
        value, err := client.LPop("fruit").Result() //返回并删除名称为 fruit 的list中的首元素
        if err != nil {
            panic(err)
        }
        fmt.Println("fruit: ", value)
    
        value, err = client.RPop("fruit").Result() // 返回并删除名称为 fruit 的list中的尾元素
        if err != nil {
            panic(err)
        }
        fmt.Println("fruit: ", value)
    }
    
    // set 操作
    func setOperation(client *redis.Client) {
        client.SAdd("blacklist", "Obama") // 向 blacklist 中添加元素
        client.SAdd("blacklist", "Hillary") // 再次添加
        client.SAdd("blacklist", "the Elder") // 添加新元素
    
        client.SAdd("whitelist", "the Elder") // 向 whitelist 添加元素
    
        // 判断元素是否在集合中
        isMember, err := client.SIsMember("blacklist", "Bush").Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("Is Bush in blacklist: ", isMember)
    
    
        // 求交集, 即既在黑名单中, 又在白名单中的元素
        names, err := client.SInter("blacklist", "whitelist").Result()
        if err != nil {
            panic(err)
        }
        // 获取到的元素是 "the Elder"
        fmt.Println("Inter result: ", names)
    
    
        // 获取指定集合的所有元素
        all, err := client.SMembers("blacklist").Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("All member: ", all)
    }
    
    
    // hash 操作
    func hashOperation(client *redis.Client) {
        client.HSet("user_xys", "name", "xys"); // 向名称为 user_xys 的 hash 中添加元素 name
        client.HSet("user_xys", "age", "18"); // 向名称为 user_xys 的 hash 中添加元素 age
    
        // 批量地向名称为 user_test 的 hash 中添加元素 name 和 age
        client.HMSet("user_test", map[string]string{"name": "test", "age":"20"})
        // 批量获取名为 user_test 的 hash 中的指定字段的值.
        fields, err := client.HMGet("user_test", "name", "age").Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("fields in user_test: ", fields)
    
    
        // 获取名为 user_xys 的 hash 中的字段个数
        length, err := client.HLen("user_xys").Result()
        if err != nil {
            panic(err)
        }
        fmt.Println("field count in user_xys: ", length) // 字段个数为2
    
        // 删除名为 user_test 的 age 字段
        client.HDel("user_test", "age")
        age, err := client.HGet("user_test", "age").Result()
        if err != nil {
            fmt.Printf("Get user_test age error: %v
    ", err)
        } else {
            fmt.Println("user_test age is: ", age) // 字段个数为2
        }
    }
    
    // redis.v4 的连接池管理
    func connectPool(client *redis.Client) {
        wg := sync.WaitGroup{}
        wg.Add(10)
    
        for i := 0; i < 10; i++ {
            go func() {
                defer wg.Done()
    
                for j := 0; j < 100; 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, FreeConns: %d
    ", client.PoolStats().TotalConns, client.PoolStats().FreeConns);
            }()
        }
    
        wg.Wait()
    }
     

    本文来自:Segmentfault

    感谢作者:永顺

  • 相关阅读:
    三个心态做人做学问 沧海
    成功走职场要找准自己的"快捷键" 沧海
    免费离线下载 拂晓风起
    Hibernate 获取某个表全部记录时 奇怪现象 (重复出现某个记录) 拂晓风起
    无法读取mdb 如果连接不了ACCESS mdb文件,就尝试安装MDAC 拂晓风起
    Netbeans 使用 Hibernate 逆向工程 生成hbm和pojo 拂晓风起
    如何点击单选框 radio 后面的文字,选中单选框 拂晓风起
    Java 连接access 使用access文件 不用配置 拂晓风起
    mysql下如何执行sql脚本 拂晓风起
    Hibernate配置access Hibernate 连接 access 拂晓风起
  • 原文地址:https://www.cnblogs.com/Flower-Z/p/10448739.html
Copyright © 2011-2022 走看看