[TOC] #### 1. 前言 --- 上一阶段我们认识了 Redis 的五大数据结构,但只是混了个脸熟,从这一讲开始,每种数据结构深入展开 先从最常用的 String 开始 你可能觉得 String 不就是存个字符串吗 ?有什么好讲的 ? 还真不是,String 是 Redis 里的 “万金油”,能干的事远比你想的多 #### 2. 底层结构:SDS --- Redis 没用 C 语言原生的字符串,自己搞了一个叫 SDS(Simple Dynamic String)。 为什么不用 C 自带的 ? 两个原因: + C 字符串获取长度要一个个数,O(n),SDS 内部维护了一个 len 字段,获取长度直接 O(1),不用遍历 + C 字符串遇到 \0 就截断,不能存二进制数据(比如图片、压缩数据),SDS 没有这个问题,什么都能存 你不用记 SDS 的具体实现,面试的时候知道 “Redis 用 SDS 替代了 C 原生字符串,获取长度 O(1),二进制安全” 就够了 #### 3. 三种编码 --- Redis 会根据你存的数据自动选择最合适的编码方式: + value 是整数:用 int 编码,最省内存 + 字符串长度 ≤ 44 字节:用 embstr 编码,一次内存分配,效率高 + 字符串长度 > 44 字节:用 raw 编码,两次分配 你可以用这个命令看当前 key 用的什么编码: ```plaintext object encoding <key> ``` 为什么要关心编码?因为不同的编码内存占用差很多 一个存了 100 万个短字符串的 Redis,用 embstr 比 raw 能省不少内存 #### 4. 缓存 --- 缓存:这是 String 最常见的用法。把 MySQL 查询结果存到 Redis,下次直接取: ```bash set user:1001 '{"name":"zhangsan","age":25}' ex 3600 ``` 缓存 1 小时,这期间所有查 `user:1001` 的请求都走 Redis,不碰 MySQL,这个模式几乎所有项目都在用 #### 5. 计数器 --- 文章阅读数: ```bash set article:1001:views 0 # 阅读量默认为 0 incr article:1001:views # 每次访问 +1 ``` incr 是原子操作,10 万个并发同时 +1 也不会出错 点赞数、下载次数、接口调用次数、秒杀库存扣减,都是这个思路 #### 6. 分布式锁(基础版) --- 多台服务器抢同一个资源: ```bash set lock:order:1001 1 nx ex 30 ``` NX = key 不存在才设置(抢锁成功) EX 30 = 30 秒自动过期(防止死锁) 这只是基础版,释放锁要用 Lua 脚本保证原子性,第 18 讲会详细讲 #### 7. 验证码 --- 用户获取验证码: ```bash set sms:13800138000 123456 ex 300 ``` 5 分钟后自动过期,不用你手动删,验证的时候 get 取出来比对就行 #### 8. 分布式 Session --- 传统项目 Session 存在单台服务器内存里 分布式部署后,用户请求可能打到不同机器,Session 就丢了 解决方案:存 Redis ```bash set session:abc123 '{"userId":1001}' ex 1800 ``` 不管请求打到哪台机器,都从 Redis 取 Session,用户无感知 #### 9. 本文小结 --- 小总结: + 底层 SDS,三种编码自动选择 + 缓存、计数器、分布式锁、验证码、Session 全能干 + String 是万能结构,但存对象字段多的时候考虑用 Hash + incr 是原子操作,并发安全