面试题答案
一键面试合理配置Redis参数
- maxmemory:
- 设置合适的值:根据服务器内存情况设置
maxmemory
参数,限制Redis使用的最大内存。例如,如果服务器有8GB内存,并且其他进程预计使用2GB,那么可以将maxmemory
设置为6GB。计算公式为:maxmemory = 服务器总内存 - 其他进程预计使用内存
。 - 动态调整:在运行过程中,可根据实际内存使用情况,通过
CONFIG SET maxmemory <new_value>
命令动态调整该值。
- 设置合适的值:根据服务器内存情况设置
- maxmemory-policy:
- 选择合适策略:
- volatile - lru:从设置了过期时间的键中,使用LRU(最近最少使用)算法淘汰键。适用于大部分数据有过期时间,且希望优先淘汰不常用的过期数据的场景。
- allkeys - lru:从所有键中,使用LRU算法淘汰键。当数据大部分不会主动设置过期时间,且希望通过淘汰不常用数据来释放内存时使用。
- volatile - ttl:从设置了过期时间的键中,优先淘汰剩余存活时间TTL(Time To Live)短的数据。适用于希望优先淘汰即将过期数据的场景。
- 调整策略:根据业务场景,通过
CONFIG SET maxmemory - policy <new_policy>
命令调整该策略。
- 选择合适策略:
选择合适的数据结构
- 字符串(String):
- 适用场景:简单的键值对存储,如缓存用户信息中的单个字段,像用户昵称、用户ID等。如果MySQL中某张用户表的用户ID为12345,其昵称为“张三”,可以在Redis中存储为
SET user:12345:nickname 张三
。 - 优点:简单高效,占用内存相对较少。
- 适用场景:简单的键值对存储,如缓存用户信息中的单个字段,像用户昵称、用户ID等。如果MySQL中某张用户表的用户ID为12345,其昵称为“张三”,可以在Redis中存储为
- 哈希(Hash):
- 适用场景:存储对象类型的数据,如完整的用户信息。假设用户表有字段
id
、name
、age
、email
,可以在Redis中使用哈希结构存储为HSET user:12345 id 12345 name 张三 age 25 email zhangsan@example.com
。 - 优点:相比多个字符串存储对象,哈希结构在内存使用上更紧凑,因为它将多个字段存储在一个键下,减少了键的数量。
- 适用场景:存储对象类型的数据,如完整的用户信息。假设用户表有字段
- 集合(Set):
- 适用场景:用于存储无序且不重复的数据集合,如某用户的所有关注用户ID集合。可以通过
SADD user:12345:followed_users 54321 67890
等命令添加关注用户ID。 - 优点:适合去重场景,并且可以方便地进行集合操作,如交集、并集、差集运算。
- 适用场景:用于存储无序且不重复的数据集合,如某用户的所有关注用户ID集合。可以通过
- 有序集合(Sorted Set):
- 适用场景:当需要对数据进行排序时使用,如按照用户积分对用户进行排名。可以使用
ZADD user_scores 100 12345 200 67890
,这里12345
和67890
是用户ID,100
和200
是对应的积分。 - 优点:在实现排序功能的同时,内存使用相对合理。
- 适用场景:当需要对数据进行排序时使用,如按照用户积分对用户进行排名。可以使用
设计缓存淘汰策略
- 基于业务热度:
- 识别热点数据:通过分析MySQL的查询日志,统计不同数据的查询频率。例如,对于电商系统,热门商品的查询频率会远高于普通商品。可以使用工具如
pt - query - digest
分析MySQL查询日志。 - 设置不同过期时间:对于热点数据,设置较长的过期时间,减少从MySQL读取的次数;对于非热点数据,设置较短的过期时间,以便在内存紧张时优先淘汰。如热门商品缓存设置过期时间为1小时,普通商品缓存设置过期时间为10分钟。
- 识别热点数据:通过分析MySQL的查询日志,统计不同数据的查询频率。例如,对于电商系统,热门商品的查询频率会远高于普通商品。可以使用工具如
- 分层缓存:
- 构建多层缓存:可以构建两级缓存,一级缓存使用Redis的内存缓存,二级缓存可以使用磁盘缓存(如Redis的AOF或RDB持久化文件,或者使用其他基于磁盘的缓存系统如Memcached的磁盘扩展模块)。
- 缓存读取逻辑:先从一级缓存读取数据,如果未命中,再从二级缓存读取。如果二级缓存也未命中,才从MySQL读取,并将数据同时写入一级和二级缓存。这样可以在保证性能的同时,减少对Redis内存的依赖。
- 定期清理:
- 主动删除无用数据:通过编写脚本,定期扫描Redis中的数据,删除不再使用的数据。例如,对于一些时效性很强的数据,如限时活动的缓存数据,在活动结束后,通过脚本主动删除相关缓存键。
- 结合过期时间:配合Redis的过期时间设置,让Redis自动清理过期数据,减少手动清理的工作量。