Redis的String类型:你以为它只是字符串?其实它是个宝藏!

95 阅读4分钟

Redis的String类型:你以为它只是字符串?其实它是个宝藏!

—— 从入门到精通,一篇全搞定


一、String类型:不只是“Hello World”

Redis的String类型是最基础、最灵活的数据结构,但千万别被名字骗了!它可不是普通的字符串,而是能存储数字、JSON、二进制数据(如图片) 的“万金油”。

核心特点

  • 二进制安全:能存任何数据,包括带\0的字节流(比如一张猫图)。
  • 最大512MB:足够存一部《三体》小说(不过别真这么干)。
  • 三种编码:根据数据内容智能切换int、embstr、raw三种模式,内存管理极客范儿。

适合场景:缓存、计数器、分布式锁、短链服务……只有想不到,没有做不到!


二、用法大全:从“菜鸟”到“老司机”

1. 基本操作:

# 存值(带过期时间)  
SET user:1 "老王" EX 60  # 60秒后自动消失  
# 取值  
GET user:1  
# 自增计数器(文章阅读量+1)  
INCR article:10086:views  
# 批量操作(减少网络开销)  
MSET name "老王" age 18  
MGET name age  

2. 高级玩法:

  • 分布式锁SET lock:order 1 NX PX 10000(10秒自动释放,防止死锁)。
  • 位图统计:用SETBIT记录用户每日签到,省内存又高效。
  • 限流INCR+EXPIRE实现接口每秒限100次调用。

3. 避坑指南

  • 别用String存大对象:比如10万用户的JSON,改用Hash更省内存。
  • 慎用INCR超长整型:超过2^63-1会报错,记得先检查范围。
  • 分布式锁的坑
    • 忘记设置过期时间 → 锁永远不释放(服务重启也救不了)!
    • 误删他人锁 → 加锁时存入唯一标识(如UUID),删除前先校验。

三、底层原理:String的“黑科技”

1. SDS(简单动态字符串)
Redis不用C语言的字符串,而是自研SDS,原因如下:

  • O(1)获取长度:C语言要遍历到\0,SDS直接读len属性。
  • 自动扩容:像智能行李箱,空间不足时自动扩展(小于1MB翻倍,超过则每次+1MB)。
  • 惰性释放:缩短字符串时不立刻缩容,而是记录空闲空间(下次直接用)。

2. 三种编码的“变形记”

  • int编码:存8字节整数(如INCR的计数器),直接省去指针开销。
  • embstr编码:≤44字节的字符串,和RedisObject“同居”同一块内存(效率高但只读)。
  • raw编码:>44字节的字符串,RedisObject和SDS分居两地(可修改但内存占用多)。

3. 内存开销的“隐形刺客”

  • 元数据占大头:存一个10位数ID,实际数据16字节,但加上RedisObject、dictEntry等元数据,总开销64字节(内存浪费75%!)。
  • 解决方案:改用Hash或Ziplist存储小数据,内存立省70%。

四、最佳实践:让String更“高效”

  1. 键命名规范:用业务:ID:属性格式(如user:1001:name),清晰易维护。
  2. 设置过期时间:缓存数据务必加EX,避免内存泄漏。
  3. 小数据优化
    • 数字优先用INCR存储(int编码省内存)。
    • 短字符串尽量≤44字节(触发embstr编码)。
  4. 大对象拆分:用户信息存Hash,而非拼接JSON字符串。

五、面试考点:征服面试官的秘籍

  1. String的底层结构?
    • SDS(len、alloc、buf) + RedisObject(type、encoding、指针)。
  2. embstr和raw的区别?
    • embstr内存连续、只读;raw内存分离、可修改。
  3. 为什么Redis单线程还快?
    • 内存操作 + 多路复用 + 避免锁竞争。
  4. String存图片ID为何内存爆炸?
    • 元数据开销占比高,改用Hash或Ziplist更省。

六、总结:String的“功”与“过”

优点:灵活、原子操作、支持丰富场景。
缺点:小数据内存开销大、大字符串性能下降。

使用哲学

  • “杀鸡别用牛刀”:小数据慎用String,优先考虑Hash、Ziplist。
  • “好钢用在刀刃上”:缓存、计数器、分布式锁才是String的主场!

彩蛋

  • 如果Redis的String会说话,它一定想说:“别老让我存大JSON,我累了!”