go 使用go-redis 和redigo 連接redis


package main

import (
    "context"
    "fmt"
    "log"
    "math/rand"
    "net/http"
    "sync"
    "time"

    goredis "github.com/garyburd/redigo/redis"
    redis "github.com/go-redis/redis/v8"
)

var ctx = context.Background()
var redisdb *redis.Client
var once sync.Once
var pool *goredis.Pool

//使用單例模式創建redis client
func GetInstance(opt redis.Options) *redis.Client {
    once.Do(func() {
        redisdb = redis.NewClient(&opt)
    })
    return redisdb
}

//使用go-redins 獲取string
func GetByKey(w http.ResponseWriter, r *http.Request) {
    // nowtime := time.Now().UnixNano()
    // defer elapsed(w, nowtime)
    //循環使用redis 讀取數據
    val, err := redisdb.Get(ctx, "key").Result()
    if err != nil {
        panic(err)
    }
    //獲取過期時間
    // tm, err := redisdb.TTL(ctx, "key").Result()
    // log.Println(tm)
    fmt.Println("key", val)
}

//使用go-redis 設置string
func SetByKey(w http.ResponseWriter, r *http.Request) {
    //第三個參數為過期時間  time.Duration
    err := redisdb.Set(ctx, "key", "value", 100*time.Second).Err()
    if err != nil {
        panic(err)
    }
    //Incr 操作
    result, err := redisdb.Incr(ctx, "counter").Result()
    log.Println("Incr", result, err)
}

//使用go-redis 操作List
func OperationList(w http.ResponseWriter, r *http.Request) {

    err := redisdb.RPush(ctx, "list_test", "message1", "message2", "message3", "message4", "message5").Err()
    if err != nil {
        panic(err)
    }

    //設置
    log.Println(redisdb.LSet(ctx, "list_test", 2, "message set").Err())

    //remove
    ret, err := redisdb.LRem(ctx, "list_test", 3, "message1").Result()
    log.Println(ret, err)

    //獲取列表長度
    rLen, err := redisdb.LLen(ctx, "list_test").Result()
    log.Println(rLen, err)

    //遍歷
    lists, err := redisdb.LRange(ctx, "list_test", 0, rLen-1).Result()
    log.Println("LRange", lists, err)

    //blpop沒有時阻塞  -- 移出並獲取列表的第一個元素
    result, err := redisdb.BLPop(ctx, 1*time.Second, "list_test").Result()
    log.Println("result:", result, err, len(result))
    //brpop 沒有時阻塞 --移出並獲取列表的最后一個元素
    result, err = redisdb.BRPop(ctx, 1*time.Second, "list_test").Result()
    log.Println("result:", result, err, len(result))
}

//使用go-redis 操作hash
func OperationHash() {
    datas := map[string]interface{}{
        "name": "LI LEI",
        "sex":  1,
        "age":  28,
        "tel":  123445578,
    }

    //添加
    if err := redisdb.HMSet(ctx, "hash_test", datas).Err(); err != nil {
        log.Fatal(err)
    }

    //獲取
    rets, err := redisdb.HMGet(ctx, "hash_test", "name", "sex").Result()
    log.Println("rets:", rets, err)

    //成員
    retAll, err := redisdb.HGetAll(ctx, "hash_test").Result()
    log.Println("retAll", retAll, err)

    //存在
    bExist, err := redisdb.HExists(ctx, "hash_test", "tel").Result()
    log.Println(bExist, err)

    //只有在字段 field 不存在時,設置哈希表字段的值
    bRet, err := redisdb.HSetNX(ctx, "hash_test", "id", 100).Result()
    log.Println(bRet, err)

    //刪除
    log.Println(redisdb.HDel(ctx, "hash_test", "age").Result())
}

//使用go-redis 操作Set 集合
func OperationSet() {
    //添加
    ret, err := redisdb.SAdd(ctx, "set_test", "11", "22", "33", "44").Result()
    log.Println(ret, err)

    //數量
    count, err := redisdb.SCard(ctx, "set_test").Result()
    log.Println(count, err)

    //刪除
    ret, err = redisdb.SRem(ctx, "set_test", "11", "22").Result()
    log.Println(ret, err)

    //成員
    members, err := redisdb.SMembers(ctx, "set_test").Result()
    log.Println(members, err)

    bret, err := redisdb.SIsMember(ctx, "set_test", "33").Result()
    log.Println(bret, err)

    redisdb.SAdd(ctx, "set_a", "11", "22", "33", "44")
    redisdb.SAdd(ctx, "set_b", "11", "22", "33", "55", "66", "77")
    //差集
    diff, err := redisdb.SDiff(ctx, "set_a", "set_b").Result()
    log.Println(diff, err)

    //交集
    inter, err := redisdb.SInter(ctx, "set_a", "set_b").Result()
    log.Println(inter, err)

    //並集
    union, err := redisdb.SUnion(ctx, "set_a", "set_b").Result()
    log.Println(union, err)

    ret, err = redisdb.SDiffStore(ctx, "set_diff", "set_a", "set_b").Result()
    log.Println(ret, err)

    rets, err := redisdb.SMembers(ctx, "set_diff").Result()
    log.Println(rets, err)
}

//使用go-redis 操作sort Set 有序集合
func OperationSortSet() {
    addArgs := make([]*redis.Z, 100)
    for i := 1; i < 100; i++ {
        addArgs = append(addArgs, &redis.Z{Score: float64(i), Member: fmt.Sprintf("a_%d", i)})
    }
    //log.Println(addArgs)

    Shuffle := func(slice []*redis.Z) {
        r := rand.New(rand.NewSource(time.Now().Unix()))
        for len(slice) > 0 {
            n := len(slice)
            randIndex := r.Intn(n)
            slice[n-1], slice[randIndex] = slice[randIndex], slice[n-1]
            slice = slice[:n-1]
        }
    }

    //隨機打亂
    Shuffle(addArgs)

    //添加
    ret, err := redisdb.ZAddNX(ctx, "sortset_test", addArgs...).Result()
    log.Println(ret, err)

    //獲取指定成員score
    score, err := redisdb.ZScore(ctx, "sortset_test", "a_10").Result()
    log.Println(score, err)

    //獲取制定成員的索引
    index, err := redisdb.ZRank(ctx, "sortset_test", "a_50").Result()
    log.Println(index, err)

    count, err := redisdb.SCard(ctx, "sortset_test").Result()
    log.Println(count, err)

    //返回有序集合指定區間內的成員
    rets, err := redisdb.ZRange(ctx, "sortset_test", 10, 20).Result()
    log.Println(rets, err)

    //返回有序集合指定區間內的成員分數從高到低
    rets, err = redisdb.ZRevRange(ctx, "sortset_test", 10, 20).Result()
    log.Println(rets, err)

    //指定分數區間的成員列表  30 < score < 50
    rets, err = redisdb.ZRangeByScore(ctx, "sortset_test", &redis.ZRangeBy{Min: "(30", Max: "(50", Offset: 1, Count: 10}).Result()
    log.Println(rets, err)
}

//用來做基數統計的算法,HyperLogLog 的優點是,在輸入元素的數量或者體積非常非常大時,計算基數所需的空間總是固定 的、並且是很小的。
//每個 HyperLogLog 鍵只需要花費 12 KB 內存,就可以計算接近 2^64 個不同元素的基 數
func OperationHyperLogLog() {
    for i := 0; i < 10000; i++ {
        redisdb.PFAdd(ctx, "pf_test_1", fmt.Sprintf("pfkey%d", i))
    }
    ret, err := redisdb.PFCount(ctx, "pf_test_1").Result()
    log.Println(ret, err)

    for i := 0; i < 10000; i++ {
        redisdb.PFAdd(ctx, "pf_test_2", fmt.Sprintf("pfkey%d", i))
    }
    ret, err = redisdb.PFCount(ctx, "pf_test_2").Result()
    log.Println(ret, err)

    redisdb.PFMerge(ctx, "pf_test", "pf_test_2", "pf_test_1")
    ret, err = redisdb.PFCount(ctx, "pf_test").Result()
    log.Println(ret, err)

}

//發布訂閱
func PubSub() {
    //發布訂閱
    pubsub := redisdb.Subscribe(ctx, "subkey")
    _, err := pubsub.Receive(ctx)
    if err != nil {
        log.Fatal("pubsub.Receive")
    }
    ch := pubsub.Channel()
    time.AfterFunc(1*time.Second, func() {
        log.Println("Publish")

        err = redisdb.Publish(ctx, "subkey", "test publish 1").Err()
        if err != nil {
            log.Fatal("redisdb.Publish", err)
        }

        redisdb.Publish(ctx, "subkey", "test publish 2")
    })
    for msg := range ch {
        log.Println("recv channel:", msg.Channel, msg.Pattern, msg.Payload)
    }
}

//執行自定義redis命令
func CMD() {
    log.Println("ExampleClient_CMD")
    defer log.Println("ExampleClient_CMD Complete!")

    //執行自定義redis命令
    Get := func(rdb *redis.Client, key string) *redis.StringCmd {
        cmd := redis.NewStringCmd(ctx, "get", key)
        redisdb.Process(ctx, cmd)
        return cmd
    }

    v, err := Get(redisdb, "NewStringCmd").Result()
    log.Println("NewStringCmd", v, err)

    cmd := redisdb.Do(ctx, "get", "redisdb.do").String()
    log.Println("redisdb.Do", cmd)
}

//SCAN 命令
func Scan() {
    log.Println("ExampleClient_Scan")
    defer log.Println("ExampleClient_Scan")

    //scan
    for i := 1; i < 1000; i++ {
        redisdb.Set(ctx, fmt.Sprintf("skey_%d", i), i, 0)
    }

    cusor := uint64(0)
    for {
        keys, retCusor, err := redisdb.Scan(ctx, cusor, "skey_*", int64(100)).Result()
        log.Println(keys, cusor, err)
        cusor = retCusor
        if cusor == 0 {
            break
        }
    }
}

//執行事務,事務之中又包含以上的原子操作
func Tx() {
    pipe := redisdb.TxPipeline()
    incr := pipe.Incr(ctx, "tx_pipeline_counter")
    pipe.Expire(ctx, "tx_pipeline_counter", time.Hour)

    // Execute
    //
    //     MULTI
    //     INCR pipeline_counter
    //     EXPIRE pipeline_counts 3600
    //     EXEC
    //
    // using one rdb-server roundtrip.
    _, err := pipe.Exec(ctx)
    fmt.Println(incr.Val(), err)
}

//腳本
func Script() {
    IncrByXX := redis.NewScript(`
        if redis.call("GET", KEYS[1]) ~= false then
            return redis.call("INCRBY", KEYS[1], ARGV[1])
        end
        return false
    `)

    n, err := IncrByXX.Run(ctx, redisdb, []string{"xx_counter"}, 2).Result()
    fmt.Println(n, err)

    err = redisdb.Set(ctx, "xx_counter", "40", 0).Err()
    if err != nil {
        panic(err)
    }

    n, err = IncrByXX.Run(ctx, redisdb, []string{"xx_counter"}, 2).Result()
    fmt.Println(n, err)
}

/*-------------------------------------------------------------------------分割線--------------------------------------------------------------------*/

//使用redigo獲取一個string類型
func GetByKey2(w http.ResponseWriter, r *http.Request) {
    // nowtime := time.Now().UnixNano()
    // defer elapsed(w, nowtime)
    // //循環使用redis 讀取數據
    // conn, err := goredis.Dial("tcp", "192.168.3.10:6000")
    // if err != nil {
    //     fmt.Println("connect redis error :", err)
    //     return
    // }
    //從線程池中取
    conn := pool.Get()
    defer conn.Close()
    name, err := goredis.String(conn.Do("GET", "name"))
    if err != nil {
        fmt.Println("redis get error:", err)
    } else {
        fmt.Printf("Got name: %s \n", name)
    }
    fmt.Println("key", name)
}

//使用redigo 設置一個string
func SetByKey2(w http.ResponseWriter, r *http.Request) {
    //第三個參數為過期時間  time.Duration
    conn := pool.Get()
    _, err := conn.Do("SET", "name", "wd")
    if err != nil {
        fmt.Println("redis set error:", err)
    }
}

// 使用defer 關鍵字統計程序耗時時長(微秒)
func elapsed(w http.ResponseWriter, beforeTime int64) {
    t := time.Now().UnixNano() - beforeTime
    fmt.Fprintln(w, t)
}

func main() {
    pool = &goredis.Pool{
        MaxIdle:     100, //最大空閑
        MaxActive:   800, //0表示沒有限制 ,最大連接數
        Wait:        true,
        IdleTimeout: 300,
        Dial: func() (goredis.Conn, error) {
            return goredis.Dial("tcp", "192.168.3.10:6000")
        },
    }
    redisdb = GetInstance(redis.Options{
        Addr:     "192.168.3.10:6000", //集群模式一定要配置主節點的值  否則會報MOVED 4998
        Password: "",                  // no password set
        DB:       0,                   // use default DB
        // MinIdleConns: 500,                 //在啟動階段創建指定數量的Idle連接,並長期維持idle狀態的連接數不少於指定數量;
        // PoolSize:     100,
    })
    http.HandleFunc("/GetByKey", GetByKey)
    http.HandleFunc("/GetByKey2", GetByKey2)
    err := http.ListenAndServe(":9090", nil)
    if err != nil {
        fmt.Printf("http server failed, err:%v\n", err)
        return
    }
}
  •  不清楚是寫法有問題還是什么問題go-redis 的性能要比redigo的性能好很多。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM