Redis 从入门到实战:核心数据类型、持久化与事务详解
Redis 是后端开发中最常用的中间件之一,但很多初学者只停留在使用 SET/GET 命令,对它的核心机制和适用场景缺乏深入理解。本文将基于实际开发经验,从安装开始,带你系统掌握 Redis 的五大核心数据类型、持久化策略以及事务与管道的区别。
读完本文,你将能够:
理解五种数据类型的设计哲学和适用场景
根据业务需求正确选择数据类型,避免“滥用字符串”
在生产环境中配置合理的持久化策略
区分事务与管道的本质差异,并在项目中正确使用
前置知识:本文假设你已具备基本的后端开发经验(PHP/Go),了解命令行操作。
一、环境准备:5秒启动一个Redis
我们使用 Docker 来快速搭建实验环境,无需纠结于安装细节。
bash
# 拉取并运行 Redis 7.0 容器docker run -d --name redis-lab -p 6379:6379 redis:7.0# 进入容器命令行docker exec -it redis-lab redis-cli# 测试连接127.0.0.1:6379> PING PONG
如果你更喜欢在代码中验证,这是 Go 语言的连接示例:
go
package mainimport (
"context"
"fmt"
"github.com/redis/go-redis/v9")func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // 生产环境务必设置密码
DB: 0,
})
ctx := context.Background()
err := rdb.Ping(ctx).Err()
if err != nil {
panic(err)
}
fmt.Println("连接成功!")}二、五大核心数据类型详解
1. String(字符串)—— 最通用的基础类型
内部编码:int、embstr、raw
常用命令:
| 命令 | 作用 |
|---|---|
SET key value [EX seconds] | 设置值,可同时指定过期时间 |
GET key | 获取值 |
MSET k1 v1 k2 v2 | 批量设置 |
INCR key | 原子自增1 |
SETNX key value | 仅当 key 不存在时设置(实现分布式锁) |
典型应用场景与代码示例
场景一:缓存对象(JSON序列化)
go
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Age int `json:"age"`}// 缓存用户信息,有效期1小时user := User{ID: 1, Name: "火龙", Age: 28}data, _ := json.Marshal(user)rdb.Set(ctx, "user:1", data, time.Hour)场景二:分布式锁(利用 SETNX + 过期时间)
go
// 原子性加锁并设置过期时间,防止死锁ok, err := rdb.SetNX(ctx, "lock:order:123", "node-1", 30*time.Second).Result()if ok {
// 获得锁,执行关键业务
defer rdb.Del(ctx, "lock:order:123") // 释放锁} else {
// 获取锁失败}场景三:计数器(限流、点赞数)
go
// 文章阅读数 +1rdb.Incr(ctx, "article:10086:views")
选型建议:String 是最通用、性能最高的类型(单条命令 QPS 可达 10万+)。能用 String 解决时,优先不要用复杂类型。
2. Hash(哈希)—— 存储对象的神器
内部编码:ziplist(压缩列表,小数据时)、hashtable(哈希表)
常用命令:
| 命令 | 作用 |
|---|---|
HSET key field value | 设置字段值 |
HGET key field | 获取字段值 |
HGETALL key | 获取所有字段和值 |
HINCRBY key field increment | 字段原子自增 |
典型应用场景
场景:存储用户信息/商品详情
go
// 存储用户信息(每个字段独立存储)rdb.HSet(ctx, "user:1", map[string]interface{}{
"name": "火龙",
"age": 28,
"city": "杭州",})// 单独更新年龄字段,无需重写整个对象rdb.HIncrBy(ctx, "user:1", "age", 1)Hash vs String+JSON 对比:
| 对比项 | String+JSON | Hash |
|---|---|---|
| 读取整个对象 | 一次 GET | 一次 HGETALL |
| 修改单个字段 | 需要 GET→修改→SET(3次操作) | 一次 HSET 即可 |
| 内存占用 | 整体序列化,较紧凑 | 有小幅度额外开销 |
| 适用场景 | 对象整体读写(如配置信息) | 频繁修改部分字段(如用户资料、购物车) |
3. List(列表)—— 消息队列与时间线
内部编码:ziplist(小数据量)、linkedlist(链表)
常用命令:
| 命令 | 作用 |
|---|---|
LPUSH key value | 从左侧插入 |
RPUSH key value | 从右侧插入 |
LPOP key | 从左侧弹出 |
LRANGE key start stop | 获取指定范围元素 |
BLPOP key timeout | 阻塞式弹出(实现消息队列) |
典型应用场景
场景一:最新消息/时间线(如新闻列表)
go