Redis
一、Redis基础
1.1 Redis概述
Redis是什么?主要特点是什么?
解析
Redis是开源的内存数据结构存储,用作数据库、缓存和消息代理。特点包括高性能、支持多种数据结构、持久化、主从复制等。
1.2 Redis数据类型
Redis支持哪些数据类型?各自的应用场景?
解析
- String: 缓存、计数器(如
INCR) - Hash: 存储对象(如用户信息)
- List: 消息队列、最新消息(如
LPUSH+LRANGE) - Set: 去重、共同好友(如
SINTER) - Sorted Set: 排行榜(如
ZADD+ZRANGE) - HyperLogLog: 基数统计(如UV统计)
- Stream: 消息队列(类似Kafka)
1.3 持久化机制
RDB和AOF的区别?如何选择?
解析
- RDB: 快照存储,恢复快但可能丢数据。
- AOF: 日志追加,数据更安全但文件大。
- 选择: 生产环境通常结合使用(
AOF保证数据安全,RDB用于备份)。
二、Redis高级特性
2.1 发布订阅
Redis的Pub/Sub如何工作?有什么缺点?
解析
发布者发送消息到频道,订阅者接收。缺点:消息不持久化,订阅者离线会丢失消息。
2.2 事务与Lua脚本
Redis事务的原子性如何理解?
解析
Redis事务是“部分原子性”——命令按顺序执行且不会被其他客户端打断,但单命令失败不会回滚(与MySQL不同)。
2.3 管道(Pipeline)
Pipeline的作用是什么?Golang中如何实现?
解析
批量发送命令减少RTT。Go示例:
pipe := client.Pipeline()
pipe.Incr("counter1")
pipe.Incr("counter2")
_, err := pipe.Exec()三、Redis性能与优化
3.1 高性能原因
Redis为什么快?
解析
内存操作、单线程避免锁竞争、IO多路复用、高效数据结构(如跳表)。
3.2 大Key问题
3.2.1 如何发现和处理大Key?
解析
- 发现:
redis-cli --bigkeys或SACN+MEMORY USAGE。 - 处理: 拆分Key、使用Hash分片、异步删除(
UNLINK)。
提醒
在使用 redis-cli --bigkeys 需要使用通过 --pass 指定密码,如果有用户名不是 default 可以通过 --user 指定。但是这样不太安全,可以通过 export REDISCLI_AUTH="default" 导出一个临时的环境变量,如果用户名不是 default 则可以通过 export REDISCLI_AUTH="default:default" 导出,之后在使用 redis-cli --bigkeys 即可!
点击查看更多相关说明
🍔 1. 使用 redis-cli --bigkeys (自动分析)
输出类似如下信息
# Scanning the entire keyspace to find biggest keys as well as
# average sizes per key type. You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).
-------- summary -------
Sampled 0 keys in the keyspace!
Total key length in bytes is 0 (avg len 0.00)
0 hashs with 0 fields (00.00% of keys, avg size 0.00)
0 lists with 0 items (00.00% of keys, avg size 0.00)
0 strings with 0 bytes (00.00% of keys, avg size 0.00)
0 streams with 0 entries (00.00% of keys, avg size 0.00)
0 sets with 0 members (00.00% of keys, avg size 0.00)
0 zsets with 0 members (00.00% of keys, avg size 0.00)优缺点
✅ 优点:
- 自动分析所有 Key,无需手动编写命令。
- 按数据类型分类,方便定位问题。
❌ 缺点:
- 可能漏掉某些大 Key(采样不完全)。
- 对生产环境有一定性能影响(建议低峰期运行)。
🍔 2. 使用 SCAN + MEMORY USAGE(手动分析)
- 功能:手动遍历 Key,检查内存占用情况。
- 适用场景:
--bigkeys无法满足需求时(如更精确分析、过滤特定 Key)。
使用方法
1. 遍历所有 Key
redis-cli --scan --pattern '*' | head -n 1000 # 只取前 1000 个 Key(避免太多)或进入交互模式:
127.0.0.1:6379> SCAN 0 COUNT 1000 # 从游标 0 开始,每次返回 1000 个 Key2. 检查 Key 内存占用
127.0.0.1:6379> MEMORY USAGE your_key # 返回字节数
127.0.0.1:6379> TYPE your_key # 查看 Key 类型
127.0.0.1:6379> STRLEN your_key # String 类型长度
127.0.0.1:6379> HLEN your_hash # Hash 的字段数量
127.0.0.1:6379> LLEN your_list # List 的元素数量3. 使用脚本自动化
redis-cli --scan --pattern '*' | while read key; do
size=$(redis-cli MEMORY USAGE "$key")
if [ "$size" -gt 10240 ]; then # 大于 10KB 的 Key
echo "Big key: $key ($size bytes)"
fi
done优缺点
✅ 优点:
- 更灵活,可自定义过滤条件(如只检查特定前缀的 Key)。
- 可精确计算每个 Key 的内存占用。
❌ 缺点:
- 需要手动编写命令或脚本,效率较低。
- 对生产环境有一定性能影响(建议分批执行)。
3.3 慢查询优化
如何排查Redis慢查询?
解析
- 配置
slowlog-log-slower-than。 - 通过
SLOWLOG GET查看。 - 优化复杂命令(如
KEYS改为SCAN)。
四、Redis集群与高可用
4.1 主从复制
主从复制的流程是什么?
解析
全量同步(RDB快照)→ 增量同步(缓冲区命令)。
4.2 Sentinel与Cluster
Sentinel和Cluster的区别?
解析
- Sentinel: 监控主从节点,自动故障转移。
- Cluster: 数据分片(16384 slots),支持水平扩展。
4.3 Golang连接集群
Go如何连接Redis Cluster?
解析
使用go-redis库:
client := redis.NewClusterClient(&redis.ClusterOptions{
Addrs: []string{"node1:6379", "node2:6379"},
})五、Redis与Golang集成
5.1 客户端选择
Go中常用的Redis客户端有哪些?
解析
go-redis(推荐,支持Cluster/Pipeline)。redigo(轻量级)。
5.2 连接池配置
如何优化Go的Redis连接池?
client := redis.NewClient(&redis.Options{
PoolSize: 100, // 连接池大小
IdleTimeout: 5 * time.Minute,
})六、Redis实战问题
6.1 缓存击穿/雪崩
如何解决缓存雪崩?
解析
- 雪崩: 大量Key同时失效 → 随机过期时间。
- 击穿: 热点Key失效 → 互斥锁(如
SETNX)。
6.2 分布式锁
Golang如何实现Redis分布式锁?
解析
使用SETNX+过期时间:
ok, err := client.SetNX("lock_key", "1", 10*time.Second).Result()
defer client.Del("lock_key")七、Redis运维与监控
7.1 监控指标
需要监控哪些Redis指标?
解析
内存使用率、QPS、慢查询、连接数、复制延迟。
7.2 安全配置
如何保证Redis安全?
解析
设置密码、禁用高危命令(如FLUSHDB)、绑定IP。
八、Redis新特性
8.1 Redis Streams
Streams如何实现消息队列?
解析
支持消费者组、消息持久化,类似Kafka:
XADD mystream * field1 value1
XREAD GROUP mygroup consumer1 STREAMS mystream >8.2 Redis 7新功能
Redis 7有什么改进?
解析
多线程IO(非命令执行)、ACL增强、Function API(替代Lua脚本)。
总结
以上问题覆盖了Redis的核心知识点,特别标注了Golang相关的实现细节。实际面试中可根据候选人经验选择不同深度的问题。