zoukankan      html  css  js  c++  java
  • go操作redis的一些练习

    使用go-redis

    github.com/go-redis/redis

    初始化连接

    // 初始化连接
    // 声明一个全局的rdb变量
    var rdb *redis.Client
    
    // 初始化连接
    func initClient() (err error) {
        // 注意这里不用 :=   必须给全局变量赋值!
        rdb = redis.NewClient(&redis.Options{
            Addr:     "localhost:6388",
            Password: "", // no password set
            DB:       1,  // use DB 1
        })
    
        _, err = rdb.Ping().Result()
        if err != nil {
            return err
        }
        return nil
    }
    View Code

    基本的set/get示例

    // 基本的 set/get 示例
    func setGetDemo(rdb *redis.Client) error {
        // set
        err := rdb.Set("age1", 100, 0).Err()
        if err != nil {
            return err
        }
    
        // get
        if val, err := rdb.Get("age1").Result(); err != nil {
            return err
        } else {
            fmt.Printf("age1>>> %v  %T 
    ", val, val) // 100  string
        }
    
        // get 一个不存在的key的情况
        if val, err := rdb.Get("xxx").Result(); err == redis.Nil {
            fmt.Printf("没有这个key! %s 
    ", "xxx")
        } else if err != nil {
            return err
        } else {
            fmt.Println("xxx>>> ", val)
        }
    
        return nil
    }
    View Code

    zset(有序集合)示例

    // zset(有序集合)示例
    func zsetDemo(rdb *redis.Client) error {
        zsetKey := "scoreRank"
    
        scoreLst := []redis.Z{
            {Score: 100.0, Member: "Math"},
            {Score: 90.0, Member: "Chinese"},
            {Score: 80.0, Member: "English"},
        }
        // 1 ZAdd 打散传参数
        if num, err := rdb.ZAdd(zsetKey, scoreLst...).Result(); err != nil {
            return err
        } else {
            fmt.Printf("zadd %d succ... 
    ", num)
        }
        // 2 给English的分数加30
        if newScore, err := rdb.ZIncrBy(zsetKey, 30, "English").Result(); err != nil {
            return err
        } else {
            fmt.Printf("English's score is %f Now! 
    ", newScore)
        }
        // 3 获取分数最高的3个 注意是闭区间!!!
        if ret, err := rdb.ZRevRangeWithScores(zsetKey, 0, 2).Result(); err != nil {
            return err
        } else {
            fmt.Println("分数最高的3个:")
            for _, val := range ret {
                fmt.Printf("%s : %f 
    ", val.Member, val.Score)
            }
        }
        // 获取 Score在 95~110 范围的 (还是闭区间)!
        op := redis.ZRangeBy{
            Min: "95",
            Max: "110",
        }
        if ret, err := rdb.ZRangeByScoreWithScores(zsetKey, op).Result(); err != nil {
            return err
        } else {
            fmt.Println("95~110范围的:")
            for _, val := range ret {
                fmt.Printf("%s : %f 
    ", val.Member, val.Score)
                /*
                    95~110范围的:
                    Math : 100.000000
                    English : 110.000000
                */
            }
        }
        return nil
    }
    View Code

    pipeline操作

    // pipeline的操作
    func pipelineDemo(rdb *redis.Client) error {
        // 1 Pipeline示例 ———— 批量set三个key
        pipe := rdb.Pipeline()
        statusCmd1 := pipe.Set("name1", "whw", 0)
        statusCmd2 := pipe.Set("name2", "naruto", 0)
        statusCmd3 := pipe.Set("name3", "sasuke", 0)
    
        fmt.Println("statusCmd1>>> ", statusCmd1)
        fmt.Println("statusCmd2>>> ", statusCmd2)
        fmt.Println("statusCmd3>>> ", statusCmd3)
        // Exec() !!!
        _, err := pipe.Exec()
        if err != nil {
            return err
        }
    
        // 2 PipeLined示例 —— 给 pipelined_counter 自增1并且设置超时时间为3600秒!
        var incr *redis.IntCmd
        _, err = rdb.Pipelined(func(pipe redis.Pipeliner) error {
            incr = pipe.Incr("pipelined_counter")
            pipe.Expire("pipelined_counter", time.Hour)
            return nil
        })
        fmt.Println(incr.Val(), err)
        return nil
    }
    View Code

    事务的操作

    // 事务的操作
    func affairDemo(rdb *redis.Client) error {
        // TxPipeline
        pipe := rdb.TxPipeline()
    
        incr := pipe.Incr("tx_pipeline_counter")
        pipe.Expire("tx_pipeline_counter", time.Hour)
    
        _, err := pipe.Exec()
        fmt.Println(incr.Val(), err)
    
        // TxPipelined
        var incr1 *redis.IntCmd
        _, err = rdb.TxPipelined(func(pipe redis.Pipeliner) error {
            incr1 = pipe.Incr("tx_pipelined_counter")
            pipe.Expire("tx_pipelined_counter", time.Hour)
            return nil
        })
        fmt.Println(incr.Val(), err)
        return nil
    }
    View Code

    完整的代码 ***

    package main
    
    import (
        "fmt"
        "github.com/go-redis/redis"
        "time"
    )
    
    // 初始化连接
    // 声明一个全局的rdb变量
    var rdb *redis.Client
    
    // 初始化连接
    func initClient() (err error) {
        // 注意这里不用 :=   必须给全局变量赋值!
        rdb = redis.NewClient(&redis.Options{
            Addr:     "localhost:6388",
            Password: "", // no password set
            DB:       1,  // use DB 1
        })
    
        _, err = rdb.Ping().Result()
        if err != nil {
            return err
        }
        return nil
    }
    
    // 基本的 set/get 示例
    func setGetDemo(rdb *redis.Client) error {
        // set
        err := rdb.Set("age1", 100, 0).Err()
        if err != nil {
            return err
        }
    
        // get
        if val, err := rdb.Get("age1").Result(); err != nil {
            return err
        } else {
            fmt.Printf("age1>>> %v  %T 
    ", val, val) // 100  string
        }
    
        // get 一个不存在的key的情况
        if val, err := rdb.Get("xxx").Result(); err == redis.Nil {
            fmt.Printf("没有这个key! %s 
    ", "xxx")
        } else if err != nil {
            return err
        } else {
            fmt.Println("xxx>>> ", val)
        }
    
        return nil
    }
    
    // zset(有序集合)示例
    func zsetDemo(rdb *redis.Client) error {
        zsetKey := "scoreRank"
    
        scoreLst := []redis.Z{
            {Score: 100.0, Member: "Math"},
            {Score: 90.0, Member: "Chinese"},
            {Score: 80.0, Member: "English"},
        }
        // 1 ZAdd 打散传参数
        if num, err := rdb.ZAdd(zsetKey, scoreLst...).Result(); err != nil {
            return err
        } else {
            fmt.Printf("zadd %d succ... 
    ", num)
        }
        // 2 给English的分数加30
        if newScore, err := rdb.ZIncrBy(zsetKey, 30, "English").Result(); err != nil {
            return err
        } else {
            fmt.Printf("English's score is %f Now! 
    ", newScore)
        }
        // 3 获取分数最高的3个 注意是闭区间!!!
        if ret, err := rdb.ZRevRangeWithScores(zsetKey, 0, 2).Result(); err != nil {
            return err
        } else {
            fmt.Println("分数最高的3个:")
            for _, val := range ret {
                fmt.Printf("%s : %f 
    ", val.Member, val.Score)
            }
        }
        // 获取 Score在 95~110 范围的 (还是闭区间)!
        op := redis.ZRangeBy{
            Min: "95",
            Max: "110",
        }
        if ret, err := rdb.ZRangeByScoreWithScores(zsetKey, op).Result(); err != nil {
            return err
        } else {
            fmt.Println("95~110范围的:")
            for _, val := range ret {
                fmt.Printf("%s : %f 
    ", val.Member, val.Score)
                /*
                    95~110范围的:
                    Math : 100.000000
                    English : 110.000000
                */
            }
        }
        return nil
    }
    
    // pipeline的操作
    func pipelineDemo(rdb *redis.Client) error {
        // 1 Pipeline示例 ———— 批量set三个key
        pipe := rdb.Pipeline()
        statusCmd1 := pipe.Set("name1", "whw", 0)
        statusCmd2 := pipe.Set("name2", "naruto", 0)
        statusCmd3 := pipe.Set("name3", "sasuke", 0)
    
        fmt.Println("statusCmd1>>> ", statusCmd1)
        fmt.Println("statusCmd2>>> ", statusCmd2)
        fmt.Println("statusCmd3>>> ", statusCmd3)
        // Exec() !!!
        _, err := pipe.Exec()
        if err != nil {
            return err
        }
    
        // 2 PipeLined示例 —— 给 pipelined_counter 自增1并且设置超时时间为3600秒!
        var incr *redis.IntCmd
        _, err = rdb.Pipelined(func(pipe redis.Pipeliner) error {
            incr = pipe.Incr("pipelined_counter")
            pipe.Expire("pipelined_counter", time.Hour)
            return nil
        })
        fmt.Println(incr.Val(), err)
        return nil
    }
    
    
    // 事务的操作
    func affairDemo(rdb *redis.Client) error {
        // TxPipeline
        pipe := rdb.TxPipeline()
    
        incr := pipe.Incr("tx_pipeline_counter")
        pipe.Expire("tx_pipeline_counter", time.Hour)
    
        _, err := pipe.Exec()
        fmt.Println(incr.Val(), err)
    
        // TxPipelined
        var incr1 *redis.IntCmd
        _, err = rdb.TxPipelined(func(pipe redis.Pipeliner) error {
            incr1 = pipe.Incr("tx_pipelined_counter")
            pipe.Expire("tx_pipelined_counter", time.Hour)
            return nil
        })
        fmt.Println(incr.Val(), err)
        return nil
    }
    
    
    func main() {
        // 初始化连接
        err := initClient()
        if err != nil {
            panic(fmt.Sprintf("初始化连接失败:%s 
    ", err.Error()))
        }
        fmt.Println("初始化连接成功......")
    
        // set/get 练习
        err = setGetDemo(rdb)
        if err != nil {
            panic(fmt.Sprintf("set/get发生错误:%s 
    ", err.Error()))
        }
    
        // zset 练习
        err = zsetDemo(rdb)
        if err != nil {
            panic(fmt.Sprintf("zset发生错误:%s 
    ", err.Error()))
        }
    
        // pipeline 练习
        err = pipelineDemo(rdb)
        if err != nil {
            panic(fmt.Sprintf("pipeline发生错误:%s 
    ", err.Error()))
        }
    
        // 事务练习
        err = affairDemo(rdb)
        if err != nil{
            panic(fmt.Sprintf("事务操作发生错误:%s 
    ", err.Error()))
        }
    
    }
    View Code

    使用GET和SET命令以事务方式递增Key的值的示例

    const routineCount = 100
    
    increment := func(key string) error {
        txf := func(tx *redis.Tx) error {
            // 获得当前值或零值
            n, err := tx.Get(key).Int()
            if err != nil && err != redis.Nil {
                return err
            }
    
            // 实际操作(乐观锁定中的本地操作)
            n++
    
            // 仅在监视的Key保持不变的情况下运行
            _, err = tx.Pipelined(func(pipe redis.Pipeliner) error {
                // pipe 处理错误情况
                pipe.Set(key, n, 0)
                return nil
            })
            return err
        }
    
        for retries := routineCount; retries > 0; retries-- {
            err := rdb.Watch(txf, key)
            if err != redis.TxFailedErr {
                return err
            }
            // 乐观锁丢失
        }
        return errors.New("increment reached maximum number of retries")
    }
    
    var wg sync.WaitGroup
    wg.Add(routineCount)
    for i := 0; i < routineCount; i++ {
        go func() {
            defer wg.Done()
    
            if err := increment("counter3"); err != nil {
                fmt.Println("increment error:", err)
            }
        }()
    }
    wg.Wait()
    
    n, err := rdb.Get("counter3").Int()
    fmt.Println("ended with", n, err)
    View Code

    参考博客

    https://www.liwenzhou.com/posts/Go/go_redis/

  • 相关阅读:
    php判断token有效期
    ecshop数据库操作
    CSS3选择器 :nth-child(n) 如何理解
    socket_wirte、socket_read、socket_send、socket_recv
    Mysql按指定顺序排序的两种写法
    Photoshop图片优化文件大小
    Wordpress中的自定义栏目是什么玩意,有什么用?
    Windows使用压缩包安装Mysql5.7.17服务
    Discuz论坛搬家后出现 Unknown column 'app1' in 'where clause' 原因及解决办法
    .PHP后缀大写导致Linux下Composer找不到类
  • 原文地址:https://www.cnblogs.com/paulwhw/p/14144632.html
Copyright © 2011-2022 走看看