Redis 核心数据结构(一)—— String 与数字

别被"数据结构"三个字吓到,String 就是你熟悉的字符串,只不过它能自动做加减法。

本次导航:

  • String 在 Redis 里长什么样(内部编码偷偷帮你省内存)
  • 最常用的命令:SET、GET、INCR、MSET、SETNX......
  • 实战场景:计数器、缓存 Session、分布式锁的基础
  • 几个容易踩的坑

发车前温馨提醒:

如果你还没把 Redis 跑起来,建议先看上一篇:

👉 5 分钟跑起 Redis(Docker 版)

有了一个能敲命令的 Redis,咱们就可以进行实操了。

一、String:最不起眼但用得最多的类型

String 是 Redis 最基础的数据类型。基础到什么程度呢?你随便用一个缓存,八成存的就是 String。

几个特点:

  • 二进制安全:可以存图片、序列化对象、JSON 字符串,随便什么字节流。
  • 最大容量 512 MB------够用了,别真往里塞视频就行。
  • 内部会根据值的类型和长度,自动选用三种编码之一来省内存。

内部编码

编码 条件 说明
int 值是 64 位有符号整数 直接用 long 存储,不额外分配内存
embstr 字符串长度 ≤ 44 字节 一次分配连续内存,读取快
raw 字符串长度 > 44 字节 两次分配,适合大字符串

你可以用 OBJECT ENCODING key 看一眼当前 key 用的什么编码:

bash 复制代码
SET counter 100
OBJECT ENCODING counter   # 输出 "int"

SET short "hello"
OBJECT ENCODING short     # 输出 "embstr"

SET long "这里写一个超过44个字符的字符串看看会发生什么..."
OBJECT ENCODING long      # 输出 "raw"

Redis 自己会帮你选最优解,你只需要 SET 和 GET 就行。

二、常用命令:从存读到加减乘除

基础三件套

bash 复制代码
SET name "zhangsan"   # 存
GET name              # 取 "zhangsan"
DEL name              # 删

批量操作(少跑几次网络,省时间)

bash 复制代码
MSET a 1 b 2 c 3
MGET a b c   # 返回 ["1","2","3"]

数字专用:原子加减

bash 复制代码
SET views 0
INCR views        # 1
INCR views        # 2
INCRBY views 10   # 12
DECR views        # 11
DECRBY views 5    # 6

原子性 :多个客户端同时 INCR 同一个 key,Redis 会排队一个个执行,不会出现"加了一次只加了半次"的情况。这事很重要,后面做计数器全靠它。

带过期时间的写入(缓存标配)

bash 复制代码
# 写法一:SETEX
SETEX session:1001 3600 "user_data_json"

# 写法二:SET 带 EX 参数(推荐,更统一)
SET session:1001 "user_data_json" EX 3600

# 查看剩余存活时间(秒)
TTL session:1001

不存在才写入(分布式锁的基础)

bash 复制代码
SET lock:order_001 "locked" NX
# 如果 key 已存在,返回 nil,写入失败

NX 的意思是 "Not eXists"。

从 Redis 2.6.12 开始,SET 命令已经集成了 NX、EX、PX 等参数,不用再分开写 SETNX + EXPIRE 了。

三、实战场景:String 能帮你干什么

场景1:计数器(文章阅读量、限流)

bash 复制代码
# 用户点开一篇文章
INCR article:10086:views

# 获取阅读量
GET article:10086:views   # 输出 "12345"

限流:比如限制每个 IP 每分钟最多访问 10 次

bash 复制代码
# 伪代码:每次请求执行下面两步
current = INCR rate_limit:192.168.1.1
if current == 1:
    EXPIRE rate_limit:192.168.1.1 60
if current > 10:
    return "请求太频繁"

场景2:缓存 Session(存用户信息)

用户登录后,把用户对象序列化成 JSON 字符串存进去,设置过期时间:

bash 复制代码
SET user:session:abc123 '{"id":1001,"name":"zhangsan","role":"admin"}' EX 7200

下次请求来了,GET 出来反序列化,不用查数据库。

场景3:分布式锁(基础版)

多个服务同时抢一个锁,谁 SET NX 成功谁就拿到:

bash 复制代码
# 抢锁(5秒自动释放,防止死锁)
SET lock:order_pay "node1" NX EX 5

# 返回 OK 表示抢到,返回 nil 表示被别人占了

释放锁的时候直接 DEL。

注意:这个基础版有个小问题------可能误删别人的锁(比如锁超时了,A 刚拿到,B 删了)。生产环境要用更严谨的 Lua 脚本版本,后面会有专门的文章讲。

四、几个容易踩的坑

坑1:KEYS * 别在生产环境用

KEYS * 会遍历所有 key,数据量大的时候 Redis 直接卡住几秒。

想看有哪些 key,用 SCAN 游标迭代:

bash 复制代码
SCAN 0 MATCH user:* COUNT 100

坑2:String 存大 JSON 要谨慎

一个 key 塞几十 KB 甚至 MB 的 JSON,会拖慢整个 Redis(读写大对象耗 CPU,网络传输也慢)。

解决办法:拆成 Hash 存,或者压缩后再存。

坑3:数字不要超过 2^63-1

Redis 的 int 编码只支持 64 位有符号整数(-9223372036854775808 到 9223372036854775807)。

超过这个范围,会转成字符串存储,但 INCR 会报错。

powershell 复制代码
127.0.0.1:6379> SET big 9223372036854775807
OK
127.0.0.1:6379> INCR big
(error) ERR increment or decrement would overflow

坑4:忘了设过期时间,内存爆炸

缓存场景一定要给 key 加 EX 或 EXPIRE,否则 Redis 会变成"永不删除的数据库",直到内存撑爆。

五、小结

String 是 Redis 的"万金油":

  • 存文本、数字、序列化对象都行
  • 数字操作用 INCR / DECR,原子性保证不错乱
  • 批量操作用 MSET / MGET 省网络
  • 分布式锁靠 SET NX EX
  • 缓存记得设过期时间

你不需要记住所有命令,记住 SET、GET、INCR、MSET、SET NX EX 这五个,就能应付 80% 的场景。


OK,本次导航结束,下次继续。

相关推荐
明月_清风2 小时前
Tomcat 到底是什么?一篇文章搞懂 Java Web 的 Tomcat
java·后端
小白男神2 小时前
MySQL进阶学习五(锁)
后端·mysql
CRZZX2 小时前
阶段 1.1:用 SQLAlchemy 和 Alembic 建立可演进的数据库基线
后端
GoGeekBaird2 小时前
云沙箱的文件通道:Agent 真正操作的是 Workspace
后端·agent
小卿噢2 小时前
EXPLAIN 里显示用了索引,不代表索引生效了
后端
苍何2 小时前
开源微信流,微信聊天记录,可以直接给 Codex 和 Obsidan 了
后端
明月_清风2 小时前
JEV 又有新玩法:当 AI Agent 开始拥有一个“决策层”
人工智能·后端·agent
沙蒿同学2 小时前
Wails v2 实战:用 Go + Vue3 做一个真正能用的 AI 桌面应用
前端·javascript·后端
站大爷IP2 小时前
Python的FastAPI把我坑惨了,原来async def和def的区别这么大
后端