刘沙河 刘沙河
首页
  • Go语言基础

    • 数据类型
    • 反射
    • Go指针
  • Go语言进阶

    • go泛型
    • go条件编译
    • cgo教程
    • Go协程调度原理及GPM模型
    • Go内存管理
    • Go垃圾回收机制
    • Go语言内存对齐
  • Go语言实现原理

    • channel 实现原理
    • slice 实现原理
    • map 实现原理
    • sync.Mutex 实现原理
    • 乐观锁CAS 实现原理
    • singlefight 实现原理
  • gin框架

    • gin中间件原理
    • gin路由原理
  • gorm

    • GORM介绍和使用
    • GORM_CURD操作指南
  • go测试

    • benchmark基准测试
    • pprof 性能分析
  • python进阶

    • Numpy&Pandas
    • celery分布式任务队列
  • Django

    • Django 常见命令
    • middleware中间件
    • Django缓存系统
    • Django信号系统
    • Django REST Framework
  • Flask

    • Flask基础知识总结
    • Flask-SQLAlchemy
  • 爬虫

    • aiohttp
    • scrapy框架
  • Mysql

    • Mysql存储引擎和索引
    • MySQL主从复制
    • Mysql读写分离
    • 数据库分库分表
    • Mysql锁
    • Mysql事务和MVCC原理
    • 分库分表带来的读扩散问题
  • Redis

    • redis基础和数据类型
    • redis主从架构
    • redis哨兵架构
    • redis集群模式
    • 如何保证缓存和数据库双写一致
    • redis底层数据结构
    • redis分布式锁
  • Elasticsearch

    • es基本概念
    • es基础语法
    • es倒排索引
  • etcd

    • Go操作etcd
    • Raft原理
    • etcd分布式锁
  • kafka

    • 消息队列MQ总结
    • kafka 概述及原理
    • kafka 消费问题记录
    • 零拷贝技术
    • kafka分区规范
  • RabbitMQ

    • rabbitMQ基础
    • Go操作rabbitmq
  • RocketMQ

    • 可靠消息队列 rocketMQ
  • Http&Https

    • http&https
    • TCP和UDP
    • Ping 原理
  • RPC

    • RPC初识
    • grpc初识和实现
  • gRPC

    • grpc 初识
    • grpc 上下文 metadata
    • grpc 健康检查
    • grpc keepalive
    • grpc 命名解析
    • grpc 中间件&拦截器
    • grpc 负载均衡
    • grpc 身份认证
    • grpc 超时重试
    • grpc 链路追踪
    • grpc-gw将gRPC转RESTfu api
    • grpc-gw自定义选项
  • protobuf

    • protobuf 进阶
    • protobuf 编码原理
  • Docker

    • Docker基础
    • Docker常用命令
    • Dockerfile
    • Docker-Compose
    • Docker多阶段构建
    • Docker Config 教程
    • Docker Swarm 教程
    • Docker Stack 教程
    • Docker Buildx 教程
  • k8s

    • k8s 基础概念
    • k8s 集群架构
    • k8s 工作负载
    • Pod 网络
    • Service 网络
    • 外部接入网络
    • 一张图搞懂k8s各种pod
    • k8s 存储抽象
    • mac快速启动k8s
    • 自制申威架构k8s-reloader
  • go-kit

    • go-kit初识
    • go-kit启动http服务
    • go-kit集成gin启动服务
    • go-kit集成grpc和protobuf
    • go-kit中间件
    • go-kit服务注册发现与负载均衡
    • go-kit限流和熔断
    • go-kit链路追踪
    • go-kit集成Prometheus
  • 设计模式

    • 初识设计模式
    • 创建型模式
    • 结构型模式
    • 行为模式
  • 数据结构

    • 时间轮
    • 堆、双向链表、环形队列
    • 队列:优先队列
    • 队列:延迟队列
  • 算法

    • 递归算法
    • 枚举算法
    • 动态规划
    • 回溯算法
    • 分治算法
    • 贪心算法
    • LRU和LFU
    • 一致性哈希

花开半夏,半夏花开
首页
  • Go语言基础

    • 数据类型
    • 反射
    • Go指针
  • Go语言进阶

    • go泛型
    • go条件编译
    • cgo教程
    • Go协程调度原理及GPM模型
    • Go内存管理
    • Go垃圾回收机制
    • Go语言内存对齐
  • Go语言实现原理

    • channel 实现原理
    • slice 实现原理
    • map 实现原理
    • sync.Mutex 实现原理
    • 乐观锁CAS 实现原理
    • singlefight 实现原理
  • gin框架

    • gin中间件原理
    • gin路由原理
  • gorm

    • GORM介绍和使用
    • GORM_CURD操作指南
  • go测试

    • benchmark基准测试
    • pprof 性能分析
  • python进阶

    • Numpy&Pandas
    • celery分布式任务队列
  • Django

    • Django 常见命令
    • middleware中间件
    • Django缓存系统
    • Django信号系统
    • Django REST Framework
  • Flask

    • Flask基础知识总结
    • Flask-SQLAlchemy
  • 爬虫

    • aiohttp
    • scrapy框架
  • Mysql

    • Mysql存储引擎和索引
    • MySQL主从复制
    • Mysql读写分离
    • 数据库分库分表
    • Mysql锁
    • Mysql事务和MVCC原理
    • 分库分表带来的读扩散问题
  • Redis

    • redis基础和数据类型
    • redis主从架构
    • redis哨兵架构
    • redis集群模式
    • 如何保证缓存和数据库双写一致
    • redis底层数据结构
    • redis分布式锁
  • Elasticsearch

    • es基本概念
    • es基础语法
    • es倒排索引
  • etcd

    • Go操作etcd
    • Raft原理
    • etcd分布式锁
  • kafka

    • 消息队列MQ总结
    • kafka 概述及原理
    • kafka 消费问题记录
    • 零拷贝技术
    • kafka分区规范
  • RabbitMQ

    • rabbitMQ基础
    • Go操作rabbitmq
  • RocketMQ

    • 可靠消息队列 rocketMQ
  • Http&Https

    • http&https
    • TCP和UDP
    • Ping 原理
  • RPC

    • RPC初识
    • grpc初识和实现
  • gRPC

    • grpc 初识
    • grpc 上下文 metadata
    • grpc 健康检查
    • grpc keepalive
    • grpc 命名解析
    • grpc 中间件&拦截器
    • grpc 负载均衡
    • grpc 身份认证
    • grpc 超时重试
    • grpc 链路追踪
    • grpc-gw将gRPC转RESTfu api
    • grpc-gw自定义选项
  • protobuf

    • protobuf 进阶
    • protobuf 编码原理
  • Docker

    • Docker基础
    • Docker常用命令
    • Dockerfile
    • Docker-Compose
    • Docker多阶段构建
    • Docker Config 教程
    • Docker Swarm 教程
    • Docker Stack 教程
    • Docker Buildx 教程
  • k8s

    • k8s 基础概念
    • k8s 集群架构
    • k8s 工作负载
    • Pod 网络
    • Service 网络
    • 外部接入网络
    • 一张图搞懂k8s各种pod
    • k8s 存储抽象
    • mac快速启动k8s
    • 自制申威架构k8s-reloader
  • go-kit

    • go-kit初识
    • go-kit启动http服务
    • go-kit集成gin启动服务
    • go-kit集成grpc和protobuf
    • go-kit中间件
    • go-kit服务注册发现与负载均衡
    • go-kit限流和熔断
    • go-kit链路追踪
    • go-kit集成Prometheus
  • 设计模式

    • 初识设计模式
    • 创建型模式
    • 结构型模式
    • 行为模式
  • 数据结构

    • 时间轮
    • 堆、双向链表、环形队列
    • 队列:优先队列
    • 队列:延迟队列
  • 算法

    • 递归算法
    • 枚举算法
    • 动态规划
    • 回溯算法
    • 分治算法
    • 贪心算法
    • LRU和LFU
    • 一致性哈希
  • go语言基础

  • go语言进阶

  • go语言实现原理

  • gin框架

    • gin框架
    • gin进阶
    • gin中使用jwt
    • go+redis
      • gin-swagger生成API文档
      • gin中间件原理
      • gin路由原理
    • gorm

    • go测试

    • Go语言
    • gin框架
    bigox
    2022-06-16
    目录

    go+redis

    go语言操作redis有个包,一个是 go-redis,另一个是redigo,官方推荐第二种,但是个人比较喜欢用第一种。

    # 连接数据库

    package main
    
    import (
        "fmt"
        "log"
        "math/rand"
        "sync"
        "time"
    
        "github.com/go-redis/redis"
    )
    
    var redisdb *redis.Client
    var wg sync.WaitGroup
    
    func main() {
        wg.Add(1)
        go testRedisBase()
        wg.Wait()
    }
    
    func testRedisBase() {
        defer wg.Done()
    
        //连接服务器
        redisdb = redis.NewClient(&redis.Options{
            Addr:     "localhost:6379", // use default Addr
            Password: "",               // no password set
            DB:       0,                // use default DB
        })
    
        //心跳
        pong, err := redisdb.Ping().Result()
        log.Println(pong, err) // Output: PONG <nil>
    
        ExampleClient_String()
        ExampleClient_List()
        ExampleClient_Hash()
        ExampleClient_Set()
        ExampleClient_SortSet()
        ExampleClient_HyperLogLog()
        ExampleClient_CMD()
        ExampleClient_Scan()
        ExampleClient_Tx()
        ExampleClient_Script()
        ExampleClient_PubSub()
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47

    # 操作String格式

    func ExampleClient_String() {
        log.Println("ExampleClient_String")
        defer log.Println("ExampleClient_String")
    
        //kv读写
        err := redisdb.Set("key", "value", 1*time.Second).Err()
        log.Println(err)
    
        //获取过期时间
        tm, err := redisdb.TTL("key").Result()
        log.Println(tm)
    
        val, err := redisdb.Get("key").Result()
        log.Println(val, err)
    
        val2, err := redisdb.Get("missing_key").Result()
        if err == redis.Nil {
            log.Println("missing_key does not exist")
        } else if err != nil {
            log.Println("missing_key", val2, err)
        }
    
        //不存在才设置 过期时间 nx ex
        value, err := redisdb.SetNX("counter", 0, 1*time.Second).Result()
        log.Println("setnx", value, err)
    
        //Incr
        result, err := redisdb.Incr("counter").Result()
        log.Println("Incr", result, err)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30

    # 操作 List 格式

    func ExampleClient_List() {
        log.Println("ExampleClient_List")
        defer log.Println("ExampleClient_List")
    
        //添加
        log.Println(redisdb.RPush("list_test", "message1").Err())
        log.Println(redisdb.RPush("list_test", "message2").Err())
    
        //设置
        log.Println(redisdb.LSet("list_test", 2, "message set").Err())
    
        //remove
        ret, err := redisdb.LRem("list_test", 3, "message1").Result()
        log.Println(ret, err)
    
        rLen, err := redisdb.LLen("list_test").Result()
        log.Println(rLen, err)
    
        //遍历
        lists, err := redisdb.LRange("list_test", 0, rLen-1).Result()
        log.Println("LRange", lists, err)
    
        //pop没有时阻塞
        result, err := redisdb.BLPop(1*time.Second, "list_test").Result()
        log.Println("result:", result, err, len(result))
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26

    # 操作 Hash 格式

    func ExampleClient_Hash() {
        log.Println("ExampleClient_Hash")
        defer log.Println("ExampleClient_Hash")
    
        datas := map[string]interface{}{
            "name": "LI LEI",
            "sex":  1,
            "age":  28,
            "tel":  123445578,
        }
    
        //添加
        if err := redisdb.HMSet("hash_test", datas).Err(); err != nil {
            log.Fatal(err)
        }
    
        //获取
        rets, err := redisdb.HMGet("hash_test", "name", "sex").Result()
        log.Println("rets:", rets, err)
    
        //成员
        retAll, err := redisdb.HGetAll("hash_test").Result()
        log.Println("retAll", retAll, err)
    
        //存在
        bExist, err := redisdb.HExists("hash_test", "tel").Result()
        log.Println(bExist, err)
    
        bRet, err := redisdb.HSetNX("hash_test", "id", 100).Result()
        log.Println(bRet, err)
    
        //删除
        log.Println(redisdb.HDel("hash_test", "age").Result())
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34

    # 操作 Set 格式(无序无重复)

    func ExampleClient_Set() {
        log.Println("ExampleClient_Set")
        defer log.Println("ExampleClient_Set")
    
        //添加
        ret, err := redisdb.SAdd("set_test", "11", "22", "33", "44").Result()
        log.Println(ret, err)
    
        //数量
        count, err := redisdb.SCard("set_test").Result()
        log.Println(count, err)
    
        //删除
        ret, err = redisdb.SRem("set_test", "11", "22").Result()
        log.Println(ret, err)
    
        //成员
        members, err := redisdb.SMembers("set_test").Result()
        log.Println(members, err)
        //查看是否是成员
        bret, err := redisdb.SIsMember("set_test", "33").Result()
        log.Println(bret, err)
    
        redisdb.SAdd("set_a", "11", "22", "33", "44")
        redisdb.SAdd("set_b", "11", "22", "33", "55", "66", "77")
        //差集
        diff, err := redisdb.SDiff("set_a", "set_b").Result()
        log.Println(diff, err)
    
        //交集
        inter, err := redisdb.SInter("set_a", "set_b").Result()
        log.Println(inter, err)
    
        //并集
        union, err := redisdb.SUnion("set_a", "set_b").Result()
        log.Println(union, err)
    
        ret, err = redisdb.SDiffStore("set_diff", "set_a", "set_b").Result()
        log.Println(ret, err)
    
        rets, err := redisdb.SMembers("set_diff").Result()
        log.Println(rets, err)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43

    # 操作 zset 格式

    func ExampleClient_SortSet() {
        log.Println("ExampleClient_SortSet")
        defer log.Println("ExampleClient_SortSet")
    
        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("sortset_test", addArgs...).Result()
        log.Println(ret, err)
    
        //获取指定成员score
        score, err := redisdb.ZScore("sortset_test", "a_10").Result()
        log.Println(score, err)
    
        //获取制定成员的索引
        index, err := redisdb.ZRank("sortset_test", "a_50").Result()
        log.Println(index, err)
    
        count, err := redisdb.SCard("sortset_test").Result()
        log.Println(count, err)
    
        //返回有序集合指定区间内的成员
        rets, err := redisdb.ZRange("sortset_test", 10, 20).Result()
        log.Println(rets, err)
    
        //返回有序集合指定区间内的成员分数从高到低
        rets, err = redisdb.ZRevRange("sortset_test", 10, 20).Result()
        log.Println(rets, err)
    
        //指定分数区间的成员列表
        rets, err = redisdb.ZRangeByScore("sortset_test", redis.ZRangeBy{Min: "(30", Max: "(50", Offset: 1, Count: 10}).Result()
        log.Println(rets, err)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50

    # zset 使用2

    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 := redisdb.ZAdd(zsetKey, languages...).Result()
        if err != nil {
            fmt.Printf("zadd failed, err:%v\n", err)
            return
        }
        fmt.Printf("zadd %d succ.\n", num)
     
        // 把Golang的分数加10
        newScore, err := redisdb.ZIncrBy(zsetKey, 10.0, "Golang").Result()
        if err != nil {
            fmt.Printf("zincrby failed, err:%v\n", err)
            return
        }
        fmt.Printf("Golang's score is %f now.\n", newScore)
     
        // 取分数最高的3个
        ret, err := redisdb.ZRevRangeWithScores(zsetKey, 0, 2).Result()
        if err != nil {
            fmt.Printf("zrevrange failed, err:%v\n", err)
            return
        }
        for _, z := range ret {
            fmt.Println(z.Member, z.Score)
        }
     
        // 取95~100分的
        op := &redis.ZRangeBy{
            Min: "95",
            Max: "100",
        }
        ret, err = redisdb.ZRangeByScoreWithScores(zsetKey, op).Result()
        if err != nil {
            fmt.Printf("zrangebyscore failed, err:%v\n", err)
            return
        }
        for _, z := range ret {
            fmt.Println(z.Member, z.Score)
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49

    # 其他操作

    
    //用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
    //每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数
    func ExampleClient_HyperLogLog() {
        log.Println("ExampleClient_HyperLogLog")
        defer log.Println("ExampleClient_HyperLogLog")
    
        for i := 0; i < 10000; i++ {
            redisdb.PFAdd("pf_test_1", fmt.Sprintf("pfkey%d", i))
        }
        ret, err := redisdb.PFCount("pf_test_1").Result()
        log.Println(ret, err)
    
        for i := 0; i < 10000; i++ {
            redisdb.PFAdd("pf_test_2", fmt.Sprintf("pfkey%d", i))
        }
        ret, err = redisdb.PFCount("pf_test_2").Result()
        log.Println(ret, err)
    
        redisdb.PFMerge("pf_test", "pf_test_2", "pf_test_1")
        ret, err = redisdb.PFCount("pf_test").Result()
        log.Println(ret, err)
    }
    
    func ExampleClient_PubSub() {
        log.Println("ExampleClient_PubSub")
        defer log.Println("ExampleClient_PubSub")
        //发布订阅
        pubsub := redisdb.Subscribe("subkey")
        _, err := pubsub.Receive()
        if err != nil {
            log.Fatal("pubsub.Receive")
        }
        ch := pubsub.Channel()
        time.AfterFunc(1*time.Second, func() {
            log.Println("Publish")
    
            err = redisdb.Publish("subkey", "test publish 1").Err()
            if err != nil {
                log.Fatal("redisdb.Publish", err)
            }
    
            redisdb.Publish("subkey", "test publish 2")
        })
        for msg := range ch {
            log.Println("recv channel:", msg.Channel, msg.Pattern, msg.Payload)
        }
    }
    
    func ExampleClient_CMD() {
        log.Println("ExampleClient_CMD")
        defer log.Println("ExampleClient_CMD")
    
        //执行自定义redis命令
        Get := func(rdb *redis.Client, key string) *redis.StringCmd {
            cmd := redis.NewStringCmd("get", key)
            redisdb.Process(cmd)
            return cmd
        }
    
        v, err := Get(redisdb, "NewStringCmd").Result()
        log.Println("NewStringCmd", v, err)
    
        v, err = redisdb.Do("get", "redisdb.do").String()
        log.Println("redisdb.Do", v, err)
    }
    
    func ExampleClient_Scan() {
        log.Println("ExampleClient_Scan")
        defer log.Println("ExampleClient_Scan")
    
        //scan
        for i := 1; i < 1000; i++ {
            redisdb.Set(fmt.Sprintf("skey_%d", i), i, 0)
        }
    
        cusor := uint64(0)
        for {
            keys, retCusor, err := redisdb.Scan(cusor, "skey_*", int64(100)).Result()
            log.Println(keys, cusor, err)
            cusor = retCusor
            if cusor == 0 {
                break
            }
        }
    }
    
    func ExampleClient_Tx() {
        pipe := redisdb.TxPipeline()
        incr := pipe.Incr("tx_pipeline_counter")
        pipe.Expire("tx_pipeline_counter", time.Hour)
    
        // Execute
        //
        //     MULTI
        //     INCR pipeline_counter
        //     EXPIRE pipeline_counts 3600
        //     EXEC
        //
        // using one rdb-server roundtrip.
        _, err := pipe.Exec()
        fmt.Println(incr.Val(), err)
    }
    
    func ExampleClient_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(redisdb, []string{"xx_counter"}, 2).Result()
        fmt.Println(n, err)
    
        err = redisdb.Set("xx_counter", "40", 0).Err()
        if err != nil {
            panic(err)
        }
    
        n, err = IncrByXX.Run(redisdb, []string{"xx_counter"}, 2).Result()
        fmt.Println(n, err)
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    #Go#
    上次更新: 2023/04/16, 18:35:33
    gin中使用jwt
    gin-swagger生成API文档

    ← gin中使用jwt gin-swagger生成API文档→

    最近更新
    01
    go与http代理
    05-24
    02
    自制申威架构k8s-reloader
    12-06
    03
    Docker Buildx 教程
    12-01
    更多文章>
    Theme by Vdoing | Copyright © 2020-2024 小刘扎扎 | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式