redis详解

一、Redis 详细介绍

Redis(Remote Dictionary Server)是一款开源的高性能键值对(Key-Value)内存数据库,以 “快” 为核心特点,同时支持持久化、多种数据结构和分布式部署,广泛用于缓存、会话存储、分布式锁等场景。

1. 核心特性

  • 内存存储:数据主要存于内存,读写速度极快(单机 QPS 可达 10 万 +),延迟通常在微秒级。
  • 多数据结构:支持 String(字符串)、Hash(哈希)、List(列表)、Set(集合)、Sorted Set(有序集合)等,满足复杂业务需求。
  • 持久化:通过 RDB(快照)和 AOF(日志)机制将内存数据持久化到磁盘,避免重启后数据丢失。
  • 高可用:支持主从复制、哨兵(Sentinel)和集群(Cluster)模式,解决单点故障问题。
  • 原子操作:内置丰富的原子命令(如INCRHSETNX),适合计数器、分布式锁等场景。

2. 核心数据结构及应用场景

数据结构 特点 典型场景
String 简单键值对,可存储文本、数字、二进制 缓存用户 Token、计数器(如文章阅读量)
Hash 键值对集合,适合存储对象多属性 缓存用户信息(用户名、ID、角色)
List 有序字符串列表,支持两端操作 消息队列、最新评论列表
Set 无序不重复集合,支持交集 / 并集运算 标签系统、好友关系(共同好友)
Sorted Set 有序集合(按分数排序),支持范围查询 排行榜(如销量 Top10)、延时任务

3. 典型应用场景

  • 缓存:存储高频访问数据(如商品详情),减少数据库压力;
  • 会话存储:分布式系统中共享用户登录态(Session);
  • 分布式锁:通过SETNX命令实现跨服务互斥操作(如秒杀库存扣减);
  • 计数器:实时统计(如在线人数、接口调用次数);
  • 消息队列:基于 List 的LPUSH/RPOP实现简单消息队列。

二、GoFrame 框架中操作 Redis 的核心语句

GoFrame 提供 gredis 组件封装了 Redis 操作,支持连接池、集群、TLS 等特性,API 设计简洁,与框架生态无缝集成。

1. 初始化 Redis 客户端

首先需要配置 Redis 连接信息(支持通过配置文件或代码硬编码),并创建客户端实例。

示例:通过代码配置初始化

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
package main

import (
"context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/database/gredis"
)

func main() {
ctx := gctx.New()

// 1. 配置 Redis 连接(地址、密码、数据库编号等)
config := &gredis.Config{
Address: "127.0.0.1:6379", // Redis 地址
Password: "your-redis-pass", // 密码(无密码可省略)
Db: 0, // 数据库编号(默认0)
PoolSize: 10, // 连接池大小
}

// 2. 创建 Redis 客户端
redisClient, err := gredis.New(config)
if err != nil {
g.Log().Fatal(ctx, "创建Redis客户端失败:", err)
}

// 测试连接
_, err = redisClient.Ping(ctx)
if err != nil {
g.Log().Fatal(ctx, "Redis连接失败:", err)
}
g.Log().Info(ctx, "Redis连接成功")
}

示例:通过配置文件初始化(推荐)
config.yaml 中配置:

1
2
3
4
5
6
redis:
default:
address: "127.0.0.1:6379"
password: "your-redis-pass"
db: 0
poolSize: 10

代码中直接通过 g.Redis() 获取默认客户端:

1
redisClient := g.Redis() // 自动读取配置文件中的redis.default配置

2. 常用数据结构操作示例

以下是 gredis 对 Redis 核心数据结构的操作示例,均基于 redisClient 实例。

(1)String 类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 设置键值对(过期时间10秒)
_, err := redisClient.SetEx(ctx, "user:name:100", "张三", 10)
if err != nil {
g.Log().Error(ctx, "SetEx失败:", err)
}

// 获取值
name, err := redisClient.Get(ctx, "user:name:100")
if err != nil {
g.Log().Error(ctx, "Get失败:", err)
}
fmt.Println("用户名:", name.String()) // 输出:张三

// 自增(计数器)
_, err = redisClient.Incr(ctx, "user:login:count") // 每次登录+1
(2)Hash 类型(适合存储对象)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 存储用户信息(Hash键:user:info:100,字段包括id、name、age)
_, err = redisClient.HSet(ctx, "user:info:100", g.Map{
"id": 100,
"name": "张三",
"age": 25,
})

// 获取单个字段
age, err := redisClient.HGet(ctx, "user:info:100", "age")
fmt.Println("年龄:", age.Int()) // 输出:25

// 获取所有字段
userInfo, err := redisClient.HGetAll(ctx, "user:info:100")
fmt.Println("用户信息:", userInfo.Map()) // 输出:map[id:100 name:张三 age:25]
(3)List 类型(消息队列示例)
1
2
3
4
5
6
7
8
// 向列表左侧添加元素(生产者)
_, err = redisClient.LPush(ctx, "message:queue", "消息1", "消息2")

// 从列表右侧获取并移除元素(消费者,阻塞等待10秒)
message, err := redisClient.BRPop(ctx, 10, "message:queue")
if err == nil {
fmt.Println("消费消息:", message) // 输出:消息1(按插入顺序)
}
(4)Set 类型(去重集合)
1
2
3
4
5
6
// 添加元素
_, err = redisClient.SAdd(ctx, "user:tags:100", "体育", "音乐", "体育") // 自动去重

// 获取所有元素
tags, err := redisClient.SMembers(ctx, "user:tags:100")
fmt.Println("用户标签:", tags.Slice()) // 输出:[体育 音乐]
(5)Sorted Set 类型(排行榜示例)
1
2
3
4
5
6
7
8
9
10
11
12
// 添加元素(分数+值,分数代表销量)
_, err = redisClient.ZAdd(ctx, "goods:sales:rank",
gredis.ZAddItem{Score: 100, Member: "商品A"},
gredis.ZAddItem{Score: 200, Member: "商品B"},
)

// 获取销量前2名(从高到低)
rank, err := redisClient.ZRevRangeWithScores(ctx, "goods:sales:rank", 0, 1)
for _, item := range rank {
fmt.Printf("%s 销量:%.0f\n", item.Member, item.Score)
// 输出:商品B 销量:200;商品A 销量:100
}

3. 高级操作:事务与管道

  • 事务:确保一组命令原子执行(全部成功或全部失败);
  • 管道:批量发送命令,减少网络往返,提升效率。

事务示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 开启事务
tx, err := redisClient.NewTransaction(ctx)
if err != nil {
g.Log().Error(ctx, "开启事务失败:", err)
}

// 向事务添加命令
tx.Set(ctx, "key1", "val1")
tx.Set(ctx, "key2", "val2")

// 执行事务
_, err = tx.Exec(ctx)
if err != nil {
g.Log().Error(ctx, "事务执行失败:", err)
}

管道示例

1
2
3
4
5
6
7
8
9
10
// 创建管道
pipe := redisClient.NewPipeline()

// 添加批量命令
pipe.Set(ctx, "p1", "v1")
pipe.Set(ctx, "p2", "v2")
pipe.Incr(ctx, "counter")

// 执行管道(一次性发送所有命令)
_, err := pipe.Exec(ctx)

三、分布式框架中 Redis 通讯安全保障

在分布式系统中,Redis 作为共享组件,需确保传输安全、访问控制、数据可靠,防止未授权访问、数据泄露或篡改。

1. 网络传输安全:加密通信

Redis 默认通过明文 TCP 传输数据,存在被中间人窃听的风险。解决方式:启用 TLS/SSL 加密

  • Redis 服务端配置
    redis.conf 中开启 TLS:

    1
    2
    3
    4
    tls-port 6379                  # TLS端口
    tls-cert-file /path/server.crt # 服务器证书
    tls-key-file /path/server.key # 服务器私钥
    tls-auth-clients yes # 验证客户端证书(可选)
  • GoFrame 客户端配置
    gredis.Config 中启用 TLS:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    config := &gredis.Config{
    Address: "127.0.0.1:6379",
    TLSConfig: &tls.Config{
    InsecureSkipVerify: false, // 生产环境禁用(需验证服务器证书)
    RootCAs: x509.NewCertPool(), // 加载CA证书
    },
    }
    // 加载CA证书(验证服务器身份)
    caCert, _ := os.ReadFile("/path/ca.crt")
    config.TLSConfig.RootCAs.AppendCertsFromPEM(caCert)

2. 访问控制:限制谁能访问

  • 密码认证:为 Redis 设置密码,客户端必须提供密码才能连接。
    Redis 配置:requirepass your-strong-password(密码需复杂,避免弱口令);
    GoFrame 客户端配置:config.Password = "your-strong-password"

  • IP 限制:通过防火墙或 Redis 配置限制允许访问的 IP(仅信任应用服务器 IP)。
    Redis 配置:bind 192.168.1.100 192.168.1.101(只允许指定 IP 连接);
    防火墙:如 iptables 只开放 6379 端口给应用服务器。

  • 最小权限原则:避免使用 Redis 管理员账号,为应用分配仅需的命令权限(如仅允许 GET/SET,禁用 FLUSHALL 等危险命令)。
    可通过 Redis 的 rename-command 配置禁用危险命令:

    1
    2
    rename-command FLUSHALL ""   # 禁用清空所有数据的命令
    rename-command CONFIG "" # 禁用修改配置的命令

3. 数据安全:防止泄露与篡改

  • 敏感数据加密存储:Redis 中的数据是明文存储的(即使开启 TLS,存储仍为明文),若需存储半敏感数据(如手机号),需在存入前加密(如 AES 加密),取出后解密。
    示例:

    1
    2
    3
    // 加密手机号后存入Redis
    encryptedPhone := aesEncrypt("13800138000", "your-aes-key")
    redisClient.Set(ctx, "user:phone:100", encryptedPhone, 3600)
  • 避免存储高敏感数据:绝对不存储密码、Token 密钥、银行卡号等,此类数据应仅存于数据库(且密码需哈希加盐)。

  • 数据备份与恢复:开启 Redis 持久化(推荐 AOF+RDB 混合模式),定期备份数据文件,防止 Redis 故障导致数据丢失。

4. 高可用与一致性:避免单点故障

分布式框架中,Redis 需保证服务不中断、数据一致:

  • 主从复制:1 主 N 从,主库写入,从库读,分担读压力,主库故障时可切换到从库;
  • 哨兵(Sentinel):自动监控主从状态,主库故障时自动将从库提升为主库,实现故障转移;
  • 集群(Cluster):分片存储数据(数据分散到多个节点),支持水平扩容,单个节点故障不影响整体服务。

GoFrame 支持直接连接 Redis 集群,配置示例

1
2
3
4
config := &gredis.Config{
Address: "127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381", // 集群节点地址
Cluster: true, // 启用集群模式
}

总结

  • Redis 是高性能内存数据库,支持多数据结构和分布式部署,是缓存、会话存储等场景的核心组件;
  • GoFrame 操作 Redis 主要通过 gredis 组件,API 简洁,支持连接池、事务、管道等高级特性;
  • 分布式安全 需从传输加密(TLS)、访问控制(密码 + IP 限制)、数据加密、高可用(集群 / 哨兵)等方面保障,防止未授权访问和数据风险。