本文最后更新于 48 天前,其中的信息可能已经有所发展或是发生改变。
Redis是什么?用快递柜秒懂
定义:Redis是开源的内存数据库(数据存在内存而非硬盘),像超快读写的“快递柜系统”:
核心特点:
- 内存操作:比MySQL快100倍(毫秒→微秒级响应)
- 键值存储:每个数据都有唯一
key
(类似快递柜号) - 持久化:定期把内存数据存到硬盘(快递柜自动拍照存档)
- 单线程:避免锁竞争(一个管理员高效处理所有请求)
Redis五大常用数据结构(附代码)
假设用Redis实现电商购物车:
数据结构 | 类比 | 操作示例 | 应用场景 |
---|---|---|---|
String | 单个储物格 | SET cart:user100 '{商品ID: 数量}' | 缓存验证码 |
Hash | 带分隔的储物抽屉 | HSET user:100 name 张三 age 30 | 存储用户档案 |
List | 排队通道 | LPUSH news 头条新闻 | 微信消息队列 |
Set | 无重复的集合 | SADD user:100:coupons 优惠券ID | 抽奖参与者记录 |
ZSet | 带分数的排行榜 | ZADD leaderboard 95 玩家A | 游戏实时排名 |
Redis典型使用场景
1. 缓存加速(解决数据库压力)
# Python示例:先查Redis缓存,没有再查数据库
import redis
r = redis.Redis()
def get_product(product_id):
# 尝试从Redis获取
cache_key = f"product:{product_id}"
data = r.get(cache_key)
if data:
return data # 缓存命中直接返回
# 缓存未命中则查数据库
data = db.query("SELECT * FROM products WHERE id=%s", product_id)
# 存入Redis并设置60秒过期
r.setex(cache_key, 60, data)
return data
2. 秒杀系统核心(库存防超卖)
-- 用Lua脚本保证原子性
local stock = tonumber(redis.call('GET', 'stock'))
if stock > 0 then
redis.call('DECR', 'stock')
return "秒杀成功"
else
return "已售罄"
end
3. 实时排行榜(ZSet实现)
# 玩家得分更新
ZADD game_leaderboard 3500 "玩家A"
ZADD game_leaderboard 4200 "玩家B"
# 获取TOP3
ZREVRANGE game_leaderboard 0 2 WITHSCORES
> 1) "玩家B" 2) "4200" 3) "玩家A" 4) "3500"
Redis vs 其他数据库
特性 | Redis | MySQL | Memcached |
---|---|---|---|
存储位置 | 内存+硬盘持久化 | 硬盘 | 纯内存 |
数据结构 | 5种丰富结构 | 只有表结构 | 仅Key-Value |
查询速度 | 微秒级 | 毫秒级 | 微秒级 |
适用场景 | 缓存/实时系统 | 持久化存储 | 简单缓存 |
数据关系 | 无关联数据 | 支持复杂关联查询 | 无关联 |
Redis的局限性
- 内存限制:数据量不能超过服务器内存(解决方案:集群分片)
- 无事务:不支持复杂事务(仅保证单命令原子性)
- 冷启动慢:重启后需要从硬盘加载数据到内存
什么时候该用Redis?
- ✅ 需要超高速读写(如秒杀页面访问量)
- ✅ 需要频繁访问的热数据(用户最近浏览记录)
- ✅ 需要实时统计(在线人数、投票计数)
- ✅ 需要短期存储(短信验证码、登录会话)
- ❌ 复杂SQL查询(用MySQL)
- ❌ 海量冷数据存储(用HBase)
动手体验
- Docker快速启动:
docker run -p 6379:6379 redis
- 基础操作:
redis-cli # 进入命令行
SET name "张三" # 存数据
GET name # 取数据 → "张三"
EXPIRE name 30 # 30秒后自动删除
Redis就像数据的“闪电侠”:
- 内存存储:速度碾压传统数据库
- 丰富结构:不只是简单键值对
- 持久化保障:断电也不丢数据
从微博热搜到双十一秒杀,背后都有Redis的身影!