Appearance
附录:Redis 核心知识点汇总
1. 核心命令速记
1.1 通用命令
| 命令 | 功能 | 示例 |
|---|---|---|
KEYS pattern | 查找匹配的键 | KEYS user:* |
EXISTS key | 检查键是否存在 | EXISTS user:101 |
DEL key [key ...] | 删除键 | DEL user:101 |
TYPE key | 查看键的数据类型 | TYPE user:101 |
EXPIRE key seconds | 设置键的过期时间 | EXPIRE user:101 3600 |
TTL key | 查看键的剩余过期时间 | TTL user:101 |
PERSIST key | 移除键的过期时间 | PERSIST user:101 |
FLUSHDB | 清空当前数据库 | FLUSHDB |
FLUSHALL | 清空所有数据库 | FLUSHALL |
SELECT index | 切换数据库 | SELECT 1 |
DBSIZE | 查看当前数据库键数量 | DBSIZE |
1.2 String 类型命令
| 命令 | 功能 | 示例 |
|---|---|---|
SET key value | 设置键值对 | SET name "zhangsan" |
GET key | 获取键值 | GET name |
SETEX key seconds value | 设置键值并指定过期时间 | SETEX code "1234" 60 |
MSET key1 value1 key2 value2 ... | 批量设置键值 | MSET name "zhangsan" age 25 |
MGET key1 key2 ... | 批量获取键值 | MGET name age |
APPEND key value | 字符串拼接 | APPEND name "123" |
STRLEN key | 获取字符串长度 | STRLEN name |
INCR key | 数字自增1 | INCR counter |
DECR key | 数字自减1 | DECR counter |
INCRBY key increment | 数字增加指定值 | INCRBY counter 10 |
DECRBY key decrement | 数字减少指定值 | DECRBY counter 5 |
1.3 Hash 类型命令
| 命令 | 功能 | 示例 |
|---|---|---|
HSET key field value | 设置哈希字段值 | HSET user id 101 name "zhangsan" |
HGET key field | 获取哈希字段值 | HGET user name |
HMSET key field1 value1 field2 value2 ... | 批量设置哈希字段 | HMSET user id 101 name "zhangsan" age 25 |
HMGET key field1 field2 ... | 批量获取哈希字段 | HMGET user id name |
HGETALL key | 获取哈希所有字段和值 | HGETALL user |
HKEYS key | 获取哈希所有字段 | HKEYS user |
HVALS key | 获取哈希所有值 | HVALS user |
HDEL key field [field ...] | 删除哈希字段 | HDEL user age |
HEXISTS key field | 判断哈希字段是否存在 | HEXISTS user name |
HLEN key | 获取哈希字段数量 | HLEN user |
1.4 List 类型命令
| 命令 | 功能 | 示例 |
|---|---|---|
LPUSH key element [element ...] | 从左侧插入元素 | LPUSH list "a" "b" "c" |
RPUSH key element [element ...] | 从右侧插入元素 | RPUSH list "a" "b" "c" |
LPOP key | 从左侧弹出元素 | LPOP list |
RPOP key | 从右侧弹出元素 | RPOP list |
LRANGE key start stop | 查看列表元素 | LRANGE list 0 -1 |
LLEN key | 查看列表长度 | LLEN list |
LREM key count element | 删除列表中指定元素 | LREM list 2 "a" |
LSET key index element | 修改列表指定位置元素 | LSET list 0 "d" |
LINDEX key index | 获取列表指定位置元素 | LINDEX list 1 |
1.5 Set 类型命令
| 命令 | 功能 | 示例 |
|---|---|---|
SADD key member [member ...] | 向集合添加元素 | SADD set "a" "b" "c" |
SMEMBERS key | 查看集合所有元素 | SMEMBERS set |
SISMEMBER key member | 判断元素是否在集合中 | SISMEMBER set "a" |
SREM key member [member ...] | 删除集合中指定元素 | SREM set "a" |
SCARD key | 查看集合元素数量 | SCARD set |
SINTER key1 key2 | 集合交集 | SINTER set1 set2 |
SUNION key1 key2 | 集合并集 | SUNION set1 set2 |
SDIFF key1 key2 | 集合差集 | SDIFF set1 set2 |
1.6 Sorted Set 类型命令
| 命令 | 功能 | 示例 |
|---|---|---|
ZADD key score member [score member ...] | 向有序集合添加元素 | ZADD rank 100 "zhangsan" 90 "lisi" |
ZRANGE key start stop [WITHSCORES] | 查看有序集合元素(升序) | ZRANGE rank 0 -1 WITHSCORES |
ZREVRANGE key start stop [WITHSCORES] | 查看有序集合元素(降序) | ZREVRANGE rank 0 -1 WITHSCORES |
ZSCORE key member | 查看元素分数 | ZSCORE rank "zhangsan" |
ZINCRBY key increment member | 修改元素分数 | ZINCRBY rank 10 "zhangsan" |
ZREM key member [member ...] | 删除有序集合中指定元素 | ZREM rank "zhangsan" |
ZRANK key member | 查看元素排名(升序) | ZRANK rank "zhangsan" |
ZREVRANK key member | 查看元素排名(降序) | ZREVRANK rank "zhangsan" |
ZCARD key | 查看有序集合元素数量 | ZCARD rank |
2. 五大数据类型对比与使用场景汇总
| 数据类型 | 特点 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|---|
| String | 简单的键值对,存储字符串或数字 | 缓存、计数器、会话存储 | 操作简单,支持过期时间 | 不适合存储复杂结构 |
| Hash | 键值对集合,适合存储对象 | 用户信息、商品详情、配置信息 | 支持单独修改字段,节省内存 | 不支持嵌套,字段过多时性能下降 |
| List | 有序可重复集合,基于链表实现 | 消息队列、最新列表、栈/队列 | 支持顺序操作,插入删除快 | 查找元素慢,不适合随机访问 |
| Set | 无序不可重复集合 | 标签、去重、共同好友 | 自动去重,支持集合运算 | 不支持排序,查找元素需要遍历 |
| Sorted Set | 有序不可重复集合,带分数 | 排行榜、排名、范围查询 | 支持排序,范围查询高效 | 内存占用较大,插入性能较低 |
2.1 数据类型选择建议
- 存储简单值:使用 String
- 存储对象:使用 Hash
- 存储有序数据:使用 List
- 存储唯一数据:使用 Set
- 存储需要排序的数据:使用 Sorted Set
3. 持久化(RDB/AOF)配置步骤与对比
3.1 RDB 配置
配置步骤:
- 编辑 redis.conf 文件
- 设置快照触发条件
- 设置 RDB 文件名称和存储路径
- 重启 Redis 服务
配置示例:
txt
# 快照触发条件
save 900 1 # 900秒内有1个键被修改
save 300 10 # 300秒内有10个键被修改
save 60 10000 # 60秒内有10000个键被修改
# RDB文件名称
dbfilename dump.rdb
# RDB文件存储路径
dir /var/lib/redis3.2 AOF 配置
配置步骤:
- 编辑 redis.conf 文件
- 开启 AOF 功能
- 设置同步策略
- 设置 AOF 重写参数
- 重启 Redis 服务
配置示例:
txt
# 开启AOF
appendonly yes
# AOF文件名称
appendfilename "appendonly.aof"
# 同步策略(always/everysec/no)
appendfsync everysec
# AOF重写触发条件
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 开启混合持久化(Redis 4.0+)
aof-use-rdb-preamble yes3.3 RDB 与 AOF 对比
| 特性 | RDB | AOF |
|---|---|---|
| 持久化方式 | 内存快照 | 命令日志 |
| 数据安全性 | 较低(可能丢失数据) | 较高(最多丢失1秒数据) |
| 恢复速度 | 快 | 慢 |
| 文件大小 | 小 | 大 |
| 对性能影响 | 小(仅在快照时) | 较大(每次写操作) |
| 适用场景 | 备份、灾难恢复 | 数据安全性要求高的场景 |
3.4 最佳实践
- 开发环境:可以只开启 RDB
- 生产环境:建议开启 AOF 或混合持久化
- 高安全性要求:使用 AOF 的 always 同步策略
- 高性能要求:使用 RDB 或 AOF 的 everysec 同步策略
4. 分布式锁、缓存防护常用模板
4.1 分布式锁模板
获取锁:
bash
# 设置分布式锁,过期时间10秒
SET lock:key 1 NX EX 10释放锁(使用 Lua 脚本确保原子性):
lua
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
else
return 0
end完整实现(Python 示例):
python
import redis
import uuid
import time
class DistributedLock:
def __init__(self, redis_client, lock_name, expire_time=10):
self.redis = redis_client
self.lock_name = f"lock:{lock_name}"
self.expire_time = expire_time
self.lock_value = str(uuid.uuid4())
def acquire(self):
"""获取锁"""
return self.redis.set(self.lock_name, self.lock_value, nx=True, ex=self.expire_time)
def release(self):
"""释放锁"""
script = """
if redis.call('get', KEYS[1]) == ARGV[1]:
return redis.call('del', KEYS[1])
else:
return 0
"""
return self.redis.eval(script, 1, self.lock_name, self.lock_value)
def __enter__(self):
"""支持上下文管理器"""
while not self.acquire():
time.sleep(0.1)
return self
def __exit__(self, exc_type, exc_val, exc_tb):
"""支持上下文管理器"""
self.release()
# 使用示例
redis_client = redis.Redis(host='localhost', port=6379, db=0)
with DistributedLock(redis_client, 'resource'):
# 执行需要加锁的操作
print("获取锁成功,执行操作...")
time.sleep(5)
print("操作完成,锁已释放")4.2 缓存防护模板
缓存穿透防护:
python
def get_with_penetration_protection(key):
"""带缓存穿透防护的获取方法"""
# 先查缓存
value = redis.get(key)
if value:
return value if value != "NULL" else None
# 缓存未命中,查数据库
value = db.query(key)
if value:
# 缓存存在的值
redis.set(key, value, ex=3600)
else:
# 缓存空值,设置较短过期时间
redis.set(key, "NULL", ex=300)
return value缓存击穿防护:
python
def get_with_breakdown_protection(key):
"""带缓存击穿防护的获取方法"""
# 先查缓存
value = redis.get(key)
if value:
return value
# 缓存未命中,尝试获取分布式锁
lock = DistributedLock(redis, f"lock:{key}")
if lock.acquire():
try:
# 再次检查缓存(防止其他线程已经更新)
value = redis.get(key)
if value:
return value
# 查数据库
value = db.query(key)
if value:
# 缓存热点数据,设置较长过期时间
redis.set(key, value, ex=7200)
finally:
# 释放锁
lock.release()
else:
# 未获取到锁,等待一段时间后重试
time.sleep(0.1)
return get_with_breakdown_protection(key)
return value缓存雪崩防护:
python
def set_with_avalanche_protection(key, value, base_expire=3600):
"""带缓存雪崩防护的设置方法"""
# 添加随机过期时间,避免同时过期
expire_time = base_expire + int(random.uniform(0, 600))
redis.set(key, value, ex=expire_time)5. 新手易错点对照表
| 错误类型 | 常见表现 | 原因 | 解决方案 |
|---|---|---|---|
| 命令拼写错误 | 执行命令返回错误 | 命令拼写不正确 | 检查命令拼写,使用 HELP 命令查看正确用法 |
| 数据类型不匹配 | 执行命令返回错误 | 对错误的数据类型执行命令 | 使用 TYPE 命令查看数据类型,使用正确的命令操作 |
| 键不存在 | 执行命令返回 (nil) | 尝试操作不存在的键 | 使用 EXISTS 命令检查键是否存在,或设置默认值 |
| 密码错误 | 连接时提示认证失败 | Redis设置了密码,输入错误 | 检查密码配置,使用正确的密码登录 |
| 端口占用 | 服务启动失败 | Redis默认端口被其他进程占用 | 查看端口占用情况,修改Redis端口或停止占用进程 |
| 内存不足 | 服务启动失败或写操作失败 | 系统内存不足或Redis内存配置过小 | 增加系统内存,调整Redis最大内存配置 |
| 持久化未开启 | 服务重启后数据丢失 | 未开启RDB或AOF持久化 | 开启持久化配置,选择合适的持久化方式 |
| 危险命令误操作 | 数据被误删除 | 执行了FLUSHDB/FLUSHALL等危险命令 | 重命名或禁用危险命令,谨慎操作 |
| 缓存穿透 | 大量请求打数据库 | 查询不存在的数据 | 缓存空值,设置较短过期时间 |
| 缓存击穿 | 热点数据过期导致数据库压力骤增 | 热点key过期 | 使用分布式锁,设置永不过期 |
| 缓存雪崩 | 大量key同时过期导致数据库压力骤增 | 批量数据设置了相同的过期时间 | 设置随机过期时间,避免同时过期 |
| 分布式锁死锁 | 锁无法释放 | 未设置过期时间,或进程崩溃 | 始终设置过期时间,使用唯一标识避免误解锁 |
6. Redis 与后端语言协同示例代码
6.1 PHP 连接 Redis
安装扩展:
bash
# 使用PECL安装
pecl install redis
# 或使用包管理器
sudo apt-get install php-redis # Ubuntu
sudo yum install php-redis # CentOS示例代码:
php
<?php
// 连接Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 验证密码(如果设置了密码)
// $redis->auth('your_password');
// 字符串操作
$redis->set('name', 'zhangsan');
echo $redis->get('name'); // 输出:zhangsan
// 哈希操作
$redis->hSet('user', 'id', 101);
$redis->hSet('user', 'name', 'zhangsan');
$redis->hSet('user', 'age', 25);
print_r($redis->hGetAll('user'));
// 列表操作
$redis->lPush('list', 'a');
$redis->lPush('list', 'b');
$redis->lPush('list', 'c');
print_r($redis->lRange('list', 0, -1));
// 集合操作
$redis->sAdd('set', 'a');
$redis->sAdd('set', 'b');
$redis->sAdd('set', 'c');
print_r($redis->sMembers('set'));
// 有序集合操作
$redis->zAdd('rank', 100, 'zhangsan');
$redis->zAdd('rank', 90, 'lisi');
$redis->zAdd('rank', 80, 'wangwu');
print_r($redis->zRevRange('rank', 0, -1, true));
// 关闭连接
$redis->close();
?>6.2 Java 连接 Redis
添加依赖:
xml
<!-- Maven依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>示例代码:
java
import redis.clients.jedis.Jedis;
public class RedisExample {
public static void main(String[] args) {
// 连接Redis
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 验证密码(如果设置了密码)
// jedis.auth("your_password");
// 字符串操作
jedis.set("name", "zhangsan");
System.out.println(jedis.get("name")); // 输出:zhangsan
// 哈希操作
jedis.hset("user", "id", "101");
jedis.hset("user", "name", "zhangsan");
jedis.hset("user", "age", "25");
System.out.println(jedis.hgetAll("user"));
// 列表操作
jedis.lpush("list", "a");
jedis.lpush("list", "b");
jedis.lpush("list", "c");
System.out.println(jedis.lrange("list", 0, -1));
// 集合操作
jedis.sadd("set", "a");
jedis.sadd("set", "b");
jedis.sadd("set", "c");
System.out.println(jedis.smembers("set"));
// 有序集合操作
jedis.zadd("rank", 100, "zhangsan");
jedis.zadd("rank", 90, "lisi");
jedis.zadd("rank", 80, "wangwu");
System.out.println(jedis.zrevrangeWithScores("rank", 0, -1));
// 关闭连接
jedis.close();
}
}6.3 Python 连接 Redis
安装依赖:
bash
pip install redis示例代码:
python
import redis
# 连接Redis
r = redis.Redis(host='localhost', port=6379, db=0)
# 验证密码(如果设置了密码)
# r.auth('your_password')
# 字符串操作
r.set('name', 'zhangsan')
print(r.get('name')) # 输出:b'zhangsan'
# 哈希操作
r.hset('user', 'id', 101)
r.hset('user', 'name', 'zhangsan')
r.hset('user', 'age', 25)
print(r.hgetall('user'))
# 列表操作
r.lpush('list', 'a')
r.lpush('list', 'b')
r.lpush('list', 'c')
print(r.lrange('list', 0, -1))
# 集合操作
r.sadd('set', 'a')
r.sadd('set', 'b')
r.sadd('set', 'c')
print(r.smembers('set'))
# 有序集合操作
r.zadd('rank', {'zhangsan': 100, 'lisi': 90, 'wangwu': 80})
print(r.zrevrange('rank', 0, -1, withscores=True))
# 关闭连接(Redis-py 3.0+ 自动管理连接池)
# r.close()7. 高频面试题及参考答案
7.1 基础概念题
Q1: 什么是 Redis? A: Redis 是一个开源的、高性能的、基于内存的键值对数据库,主打高速缓存与数据存储,是最流行的非关系型数据库之一。
Q2: Redis 的核心优势有哪些? A: 高速读写、支持多数据类型、可持久化、支持分布式、轻量易用,解决高并发场景下的数据访问瓶颈。
Q3: Redis 支持哪些数据类型? A: 字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)。
Q4: Redis 的应用场景有哪些? A: 缓存应用、会话存储、计数器与限流、消息队列、排行榜等。
Q5: Redis 与 MySQL 的区别是什么? A: Redis 是内存存储(高速),非关系型数据库;MySQL 是磁盘存储(持久),关系型数据库。两者互补使用。
7.2 核心命令题
Q1: 如何设置一个键值对并指定过期时间? A: 使用 SET key value EX seconds 命令,例如 SET name "zhangsan" EX 3600。
Q2: 如何批量设置多个键值对? A: 使用 MSET key1 value1 key2 value2 ... 命令,例如 MSET name "zhangsan" age 25。
Q3: 如何查看哈希类型的所有字段和值? A: 使用 HGETALL key 命令,例如 HGETALL user。
Q4: 如何向列表左侧插入元素? A: 使用 LPUSH key element [element ...] 命令,例如 LPUSH list "a" "b" "c"。
Q5: 如何获取有序集合的前 N 个元素(降序)? A: 使用 ZREVRANGE key 0 N-1 [WITHSCORES] 命令,例如 ZREVRANGE rank 0 4 WITHSCORES。
7.3 实战场景题
Q1: 如何解决缓存穿透问题? A: 缓存空值,设置较短的过期时间,避免请求直接打数据库。
Q2: 如何解决缓存击穿问题? A: 使用分布式锁,确保只有一个线程去数据库查询;或设置热点数据永不过期。
Q3: 如何解决缓存雪崩问题? A: 为批量数据设置随机过期时间,避免同时过期;或使用分层缓存。
Q4: 如何实现分布式锁? A: 使用 SET key value NX EX seconds 命令获取锁,使用 Lua 脚本原子释放锁。
Q5: 如何选择 RDB 和 AOF 持久化方式? A: 开发环境可以只使用 RDB;生产环境建议使用 AOF 或混合持久化;高安全性要求使用 AOF 的 always 同步策略;高性能要求使用 RDB 或 AOF 的 everysec 同步策略。
7.4 安全题
Q1: 如何提高 Redis 的安全性? A: 设置强密码、修改默认端口、绑定IP、禁用危险命令、及时更新版本。
Q2: 如何设置 Redis 密码? A: 在 redis.conf 文件中设置 requirepass your_password,或使用 CONFIG SET requirepass your_password 临时设置。
Q3: 如何禁用危险命令? A: 在 redis.conf 文件中使用 rename-command 指令重命名或禁用危险命令,例如 rename-command FLUSHDB ""。
7.5 进阶题
Q1: Redis 集群的工作原理是什么? A: Redis Cluster 使用哈希槽(16384个)将数据分布到多个节点,每个主节点负责一部分哈希槽,从节点作为备份。当主节点故障时,从节点自动提升为主节点。
Q2: Redis 的内存淘汰策略有哪些? A: volatile-lru、allkeys-lru、volatile-ttl、volatile-random、allkeys-random、noeviction。
Q3: Redis 的持久化机制有哪些? A: RDB(快照持久化)和 AOF( Append Only File)。
Q4: Redis 的主从复制原理是什么? A: 主节点将数据同步到从节点,从节点作为只读副本。复制方式包括全量复制和增量复制。
Q5: 如何优化 Redis 的性能? A: 合理设计键名、使用批量命令、优化数据结构、配置合适的内存淘汰策略、选择合适的持久化方式、使用管道操作、避免使用危险命令。
7.6 面试技巧
- 理解核心概念:掌握 Redis 的基本概念、数据类型和常用命令。
- 熟悉实战场景:了解 Redis 在实际项目中的应用场景和解决方案。
- 掌握优化技巧:了解 Redis 的性能优化和安全防护措施。
- 准备实际案例:准备一个自己使用 Redis 的实际案例,展示实践经验。
- 理清思路:回答问题时,先理清思路,分点作答,逻辑清晰。
- 诚实面对:遇到不会的问题,坦诚承认,表现出学习意愿。
实战总结
本附录汇总了Redis的核心知识点,包括常用命令、数据类型对比、持久化配置、分布式锁模板、新手易错点、后端语言集成示例和面试题等内容。这些知识点是Redis学习和应用的重要参考资料,希望能帮助你快速掌握Redis的核心功能和最佳实践。
Redis是一个功能强大的缓存和数据存储系统,通过不断学习和实践,你可以将其威力发挥到极致,为你的应用提供高性能、高可用的数据存储解决方案。
