Golang操作Redis | 基础到生产环境实践

连接Redis基础

我们先从Go语言连接Redis开始。安装官方推荐的go-redis库:

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

基本连接示例:

import (
    "context"
    "github.com/redis/go-redis/v9"
)

func main() {
    rdb := redis.NewClient(&redis.Options{
        Addr:     "localhost:6379", // Redis地址
        Password: "",               // 密码
        DB:       0,                // 数据库编号
        PoolSize: 20,               // 连接池大小
    })

    ctx := context.Background()
    pong, err := rdb.Ping(ctx).Result()
    if err != nil {
        panic(err)
    }
    fmt.Println(pong) // 输出PONG表示连接成功
}

连接参数说明:

  • Addr: 支持多种格式:host:portredis://user:password@host:port
  • TLSConfig: 配置TLS加密连接
  • ReadTimeout: 读超时默认3秒
  • WriteTimeout: 写超时默认3秒

数据操作实战

字符串操作

// 设置值(带过期时间)
err := rdb.Set(ctx, "article:123", "Redis入门指南", time.Hour).Err()

// 获取值
val, err := rdb.Get(ctx, "article:123").Result()

// 原子递增
count := rdb.Incr(ctx, "page_view").Val()

// 批量操作
rdb.MSet(ctx, "key1", "value1", "key2", "value2")
values := rdb.MGet(ctx, "key1", "key2").Val()

哈希操作

// 设置哈希字段
rdb.HSet(ctx, "user:1001", 
    "name", "张三",
    "email", "zhangsan@example.com",
    "created_at", time.Now().Unix(),
)

// 获取单个字段
name := rdb.HGet(ctx, "user:1001", "name").Val()

// 获取全部字段
userData := rdb.HGetAll(ctx, "user:1001").Val()

// 原子操作
rdb.HIncrBy(ctx, "product:2001", "stock", -1)

列表操作

// 从左侧插入
rdb.LPush(ctx, "task_queue", "task1")

// 从右侧获取
task := rdb.RPop(ctx, "task_queue").Val()

// 范围查询
tasks := rdb.LRange(ctx, "task_queue", 0, 10).Val()

高级特性应用

事务处理

Redis事务通过MULTI/EXEC实现:

// Watch实现乐观锁
err := rdb.Watch(ctx, func(tx *redis.Tx) error {
    // 获取当前值
    n, err := tx.Get(ctx, "counter").Int()
    if err != nil && err != redis.Nil {
        return err
    }

    // 事务操作
    _, err = tx.TxPipelined(ctx, func(pipe redis.Pipeliner) error {
        pipe.Set(ctx, "counter", n+1, 0)
        return nil
    })
    return err
}, "counter")

管道批处理

pipe := rdb.Pipeline()
pipe.Get(ctx, "key1")
pipe.HGetAll(ctx, "user:1001")
pipe.ZRange(ctx, "leaderboard", 0, 10)
cmds, err := pipe.Exec(ctx)

发布订阅

pubsub := rdb.Subscribe(ctx, "news")
defer pubsub.Close()

// 接收消息
go func() {
    for msg := range pubsub.Channel() {
        fmt.Printf("收到消息: %s\n", msg.Payload)
    }
}()

// 发布消息
rdb.Publish(ctx, "news", "重大更新!")

性能优化实践

连接池配置

client := redis.NewClient(&redis.Options{
    PoolSize:     50,                // 最大连接数
    MinIdleConns: 10,                // 最小空闲连接
    MaxRetries:   3,                 // 最大重试次数
    ReadTimeout:  500 * time.Millisecond,
    WriteTimeout: 500 * time.Millisecond,
    IdleTimeout:  5 * time.Minute,
})

内存优化技巧

  1. 使用HSCAN代替HGETALL处理大哈希
  2. 对长字符串启用压缩(snappy/gzip)
  3. 设置合理的过期时间
  4. 使用SSCAN分批次获取大数据集
iter := rdb.SScan(ctx, "large_set", 0, "", 100).Iterator()
for iter.Next(ctx) {
    fmt.Println(iter.Val())
}

生产环境最佳实践

健康检查方案

// 定期检查Redis状态
go func() {
    ticker := time.NewTicker(30 * time.Second)
    for {
        select {
        case <-ticker.C:
            latency := rdb.Ping(ctx).Val()
            metrics.RecordRedisLatency(latency)
            
            info := rdb.Info(ctx).Val()
            monitor.ParseInfo(info)
        }
    }
}()

错误处理规范

value, err := rdb.Get(ctx, "key").Result()
switch {
case err == redis.Nil:
    log.Println("键不存在")
case err != nil:
    log.Printf("Redis错误: %v", err)
default:
    log.Printf("获取到值: %s", value)
}

安全加固措施

  1. 启用ACL访问控制
  2. 使用TLS加密传输
  3. 限制危险命令
client := redis.NewClient(&redis.Options{
    TLSConfig: &tls.Config{
        MinVersion: tls.VersionTLS12,
    },
})
正文到此结束
评论插件初始化中...
Loading...