适用人群:后端开发者、全栈开发者
学习时长:约1-2天(每天3小时)
Redis版本:7.0+
重要程度:★★★★☆(性能优化必备)
一、Redis 是什么?
Redis(Remote Dictionary Server)是一个开源的内存数据结构存储,可用作数据库、缓存和消息中间件。
| 特点 | 说明 |
|---|---|
| 性能 | 10万+ QPS(每秒查询数) |
| 数据结构 | String、List、Hash、Set、Sorted Set |
| 持久化 | RDB快照 + AOF日志 |
| 主要用途 | 缓存、会话存储、排行榜、消息队列 |
| 适用场景 | 高并发读取、计数器、实时排行 |
二、安装与配置
2.1 安装
# Docker(推荐)
docker run -d --name redis -p 6379:6379 redis:7-alpine
# Ubuntu
sudo apt install redis-server
# CentOS
sudo yum install redis
sudo systemctl start redis
sudo systemctl enable redis
# macOS
brew install redis
brew services start redis
# 验证
redis-cli ping # 应返回 PONG
2.2 配置
# /etc/redis/redis.conf
# 绑定地址
bind 0.0.0.0
# 密码
requirepass your_password
# 最大内存
maxmemory 256mb
# 内存淘汰策略
maxmemory-policy allkeys-lru
# 持久化
appendonly yes
appendfsync everysec
三、基本数据类型
3.1 String(字符串)
# 设置
SET name "张三"
SET counter 100
SET token "abc123" EX 3600 # 设置并设置过期时间(秒)
# 获取
GET name # "张三"
# 自增/自减
INCR counter # 101
INCRBY counter 10 # 111
DECR counter # 110
DECRBY counter 5 # 105
# 批量操作
MSET key1 "val1" key2 "val2"
MGET key1 key2
# 不存在时设置(分布式锁)
SETNX lock "value"
# 追加
APPEND name " 先生" # "张三 先生"
# 过期
EXPIRE name 3600 # 3600秒后过期
TTL name # 查看剩余时间
3.2 List(列表)
# 添加元素
LPUSH mylist "c" "b" "a" # 从左边添加
RPUSH mylist "d" "e" # 从右边添加
# 获取元素
LINDEX mylist 0 # 获取指定索引
LRANGE mylist 0 -1 # 获取所有元素
LLEN mylist # 获取长度
# 弹出元素
LPOP mylist # 从左边弹出
RPOP mylist # 从右边弹出
# 阻塞弹出(消息队列)
BLPOP mylist 30 # 阻塞30秒等待元素
# 应用场景:消息队列
LPUSH queue "task1" "task2" "task3"
BRPOP queue 0 # 阻塞等待任务
3.3 Hash(哈希)
# 设置字段
HSET user:1 name "张三"
HSET user:1 age 25
HSET user:1 email "zhangsan@example.com"
# 获取字段
HGET user:1 name # "张三"
HGETALL user:1 # 获取所有字段和值
# 批量设置
HMSET user:2 name "李四" age 30 email "lisi@example.com"
# 判断字段存在
HEXISTS user:1 name # 1 (存在)
# 删除字段
HDEL user:1 email
# 自增
HINCRBY user:1 age 1 # 26
# 应用场景:用户信息存储
3.4 Set(集合)
# 添加元素
SADD myset "a" "b" "c" "d"
# 获取所有元素
SMEMBERS myset
# 判断元素存在
SISMEMBER myset "a" # 1 (存在)
# 集合操作
SADD set1 "a" "b" "c"
SADD set2 "b" "c" "d"
SINTER set1 set2 # 交集:["b", "c"]
SUNION set1 set2 # 并集:["a", "b", "c", "d"]
SDIFF set1 set2 # 差集:["a"]
# 随机获取
SRANDMEMBER myset 2 # 随机获取2个元素
# 应用场景:标签、共同好友
3.5 Sorted Set(有序集合)
# 添加元素(带分数)
ZADD leaderboard 100 "张三"
ZADD leaderboard 85 "李四"
ZADD leaderboard 92 "王五"
# 获取排名(从高到低)
ZREVRANGE leaderboard 0 2 WITHSCORES # 前3名
# 获取分数
ZSCORE leaderboard "张三" # 100
# 获取排名
ZREVRANK leaderboard "张三" # 0 (第一名)
# 自增分数
ZINCRBY leaderboard 5 "李四" # 90
# 范围查询
ZRANGEBYSCORE leaderboard 80 100 # 分数80-100的成员
# 应用场景:排行榜
四、PHP 中使用 Redis
<?php
// 安装:composer require predis/predis
use Predis\Client;
$redis = new Client([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
'password' => 'your_password',
]);
// String
$redis->set('name', '张三');
$name = $redis->get('name');
$redis->incr('counter');
$redis->expire('name', 3600);
// Hash
$redis->hset('user:1', 'name', '张三');
$redis->hset('user:1', 'age', 25);
$user = $redis->hgetall('user:1');
// List
$redis->lpush('queue', 'task1');
$redis->rpush('queue', 'task2');
$task = $redis->blpop('queue', 30);
// Set
$redis->sadd('tags', 'php', 'redis', 'mysql');
$tags = $redis->smembers('tags');
// Sorted Set(排行榜)
$redis->zadd('leaderboard', 100, '张三');
$redis->zadd('leaderboard', 85, '李四');
$top = $redis->zrevrange('leaderboard', 0, 2, true);
// 缓存模式
function getCache($key, $ttl, $callback) {
global $redis;
$data = $redis->get($key);
if ($data) {
return json_decode($data, true);
}
// 缓存未命中,从数据库获取
$data = $callback();
$redis->setex($key, $ttl, json_encode($data));
return $data;
}
// 使用示例
$users = getCache('users:all', 3600, function() {
// 从数据库查询
return User::all()->toArray();
});
五、Python 中使用 Redis
# 安装:pip install redis
import redis
import json
# 连接
r = redis.Redis(
host='localhost',
port=6379,
password='your_password',
decode_responses=True # 自动解码
)
# String
r.set('name', '张三')
name = r.get('name')
r.incr('counter')
r.expire('name', 3600)
# Hash
r.hset('user:1', mapping={'name': '张三', 'age': 25})
user = r.hgetall('user:1')
# List
r.lpush('queue', 'task1', 'task2')
task = r.blpop('queue', timeout=30)
# Set
r.sadd('tags', 'python', 'redis', 'mysql')
tags = r.smembers('tags')
# Sorted Set
r.zadd('leaderboard', {'张三': 100, '李四': 85, '王五': 92})
top = r.zrevrange('leaderboard', 0, 2, withscores=True)
# 缓存装饰器
def cache(key_template, ttl=3600):
def decorator(func):
def wrapper(*args, **kwargs):
key = key_template.format(*args, **kwargs)
data = r.get(key)
if data:
return json.loads(data)
result = func(*args, **kwargs)
r.setex(key, ttl, json.dumps(result, ensure_ascii=False))
return result
return wrapper
return decorator
@cache('user:{0}', ttl=3600)
def get_user(user_id):
# 从数据库查询
return User.query.get(user_id).to_dict()
六、Go 中使用 Redis
// 安装:go get github.com/redis/go-redis/v9
package main
import (
"context"
"fmt"
"time"
"github.com/redis/go-redis/v9"
)
var rdb *redis.Client
func init() {
rdb = redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "your_password",
DB: 0,
})
}
func main() {
ctx := context.Background()
// String
rdb.Set(ctx, "name", "张三", time.Hour)
name, _ := rdb.Get(ctx, "name").Result()
fmt.Println(name)
// Hash
rdb.HSet(ctx, "user:1", "name", "张三", "age", 25)
user, _ := rdb.HGetAll(ctx, "user:1").Result()
fmt.Println(user)
// List
rdb.LPush(ctx, "queue", "task1", "task2")
task, _ := rdb.BRPop(ctx, 0, "queue").Result()
fmt.Println(task)
// Sorted Set
rdb.ZAdd(ctx, "leaderboard", redis.Z{Score: 100, Member: "张三"})
rdb.ZAdd(ctx, "leaderboard", redis.Z{Score: 85, Member: "李四"})
top, _ := rdb.ZRevRangeWithScores(ctx, "leaderboard", 0, 2).Result()
for _, z := range top {
fmt.Printf("%s: %.0f\n", z.Member, z.Score)
}
}
七、Java 中使用 Redis
// Spring Boot + Redis
// pom.xml 添加依赖
// <dependency>
// <groupId>org.springframework.boot</groupId>
// <artifactId>spring-boot-starter-data-redis</artifactId>
// </dependency>
// application.yml
// spring:
// data:
// redis:
// host: localhost
// port: 6379
// password: your_password
// 使用RedisTemplate
@Service
public class RedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// String操作
public void set(String key, Object value, long timeout) {
redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
}
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
// Hash操作
public void hSet(String key, String field, Object value) {
redisTemplate.opsForHash().put(key, field, value);
}
public Object hGet(String key, String field) {
return redisTemplate.opsForHash().get(key, field);
}
// List操作
public void lPush(String key, Object value) {
redisTemplate.opsForList().leftPush(key, value);
}
// Sorted Set(排行榜)
public void zAdd(String key, String member, double score) {
redisTemplate.opsForZSet().add(key, member, score);
}
public Set<Object> zRevRange(String key, long start, long end) {
return redisTemplate.opsForZSet().reverseRange(key, start, end);
}
}
八、常见应用场景
8.1 缓存
# 缓存穿透:查询不存在的数据
# 解决:缓存空值或使用布隆过滤器
# 缓存击穿:热点key过期
# 解决:互斥锁或永不过期
# 缓存雪崩:大量key同时过期
# 解决:随机过期时间
8.2 分布式锁
import redis
import uuid
import time
class RedisLock:
def __init__(self, redis_client, key, expire=10):
self.redis = redis_client
self.key = f"lock:{key}"
self.value = str(uuid.uuid4())
self.expire = expire
def acquire(self, timeout=10):
end = time.time() + timeout
while time.time() < end:
if self.redis.set(self.key, self.value, nx=True, ex=self.expire):
return True
time.sleep(0.1)
return False
def release(self):
if self.redis.get(self.key) == self.value:
self.redis.delete(self.key)
# 使用
lock = RedisLock(r, 'order:123')
if lock.acquire():
try:
# 执行业务逻辑
pass
finally:
lock.release()
8.3 排行榜
def update_score(user_id, score):
r.zincrby('leaderboard', score, user_id)
def get_top_n(n=10):
return r.zrevrange('leaderboard', 0, n-1, withscores=True)
def get_rank(user_id):
return r.zrevrank('leaderboard', user_id)
8.4 计数器
# 页面访问量
def incr_page_views(page_id):
key = f"page:views:{page_id}"
return r.incr(key)
# 获取访问量
def get_page_views(page_id):
key = f"page:views:{page_id}"
return int(r.get(key) or 0)
九、最佳实践
✅ 设置合理的过期时间
✅ 使用连接池
✅ 避免存储大Value(>10KB)
✅ 使用Pipeline批量操作
✅ 监控内存使用
✅ 配置持久化(AOF)
✅ 使用Sentinel或Cluster高可用
✅ Key命名规范:业务:对象:ID:属性
学习建议
- 先掌握5种数据类型,理解各自的适用场景
- 理解缓存策略,缓存穿透、击穿、雪崩的解决方案
- 学会在各语言中使用Redis客户端
- 实践常见场景:缓存、排行榜、分布式锁
- 了解Redis集群,生产环境高可用方案