面试题答案
一键面试数据结构选择
- 商品详情页:
- 使用哈希(Hash)结构存储商品详情数据。例如,以商品ID为键,商品的各个属性(如名称、价格、描述等)作为哈希的字段和值。这样可以快速定位和获取特定商品的详细信息,且内存使用相对高效。例如:
HSET product:1 name "手机" HSET product:1 price "2999"
- 购物车:
- 采用哈希结构存储购物车数据,以用户ID为键,购物车中的商品ID及对应数量作为哈希的字段和值。同时,可以结合有序集合(Sorted Set)来记录购物车操作的时间顺序(如果需要按操作时间处理一些事务逻辑)。例如:
HSET cart:user1 product:1 2 HSET cart:user1 product:2 1
- 对于购物车事务,可以利用Redis的事务(MULTI/EXEC)功能,将多个购物车操作命令组合在一个事务中执行,保证数据一致性。
内存分配策略
- 配置Redis内存限制:
在Redis配置文件(redis.conf)中设置
maxmemory
参数,根据服务器实际可用内存,合理限制Redis使用的最大内存。例如:maxmemory 10gb
- 内存淘汰策略:
选择
allkeys - lru
(最近最少使用)策略。此策略会在内存达到限制时,优先淘汰最近最少使用的键。这样可以保证热门商品数据能长时间保留在缓存中,提高缓存命中率。在Redis配置文件中设置:maxmemory - policy allkeys - lru
缓存更新机制
- 商品详情页:
- 采用写后更新策略。当商品数据在数据库中更新后,异步更新Redis缓存。可以使用消息队列(如RabbitMQ、Kafka等)来解耦数据库更新和缓存更新操作。例如,数据库更新商品信息后,发送一条消息到消息队列,由专门的消费者从消息队列中获取消息并更新Redis缓存。
- 也可以设置缓存的过期时间(
EXPIRE
命令),当缓存过期后,下一次请求时从数据库加载最新数据并重新缓存。
- 购物车:
- 对于购物车操作,在事务执行成功后立即更新缓存。例如,当用户添加或删除商品时,通过Redis事务确保购物车数据的一致性,同时在事务执行成功后,及时更新购物车对应的哈希结构。
故障恢复策略
- 持久化机制:
- 开启AOF(Append - Only File)持久化方式,在Redis配置文件中设置
appendonly yes
。AOF会以日志的形式记录每次写操作,在Redis重启时通过重放AOF文件来恢复数据。同时,可以结合RDB(Redis Database)快照持久化,设置合适的快照保存条件(如save 900 1
表示900秒内至少有1个写操作就进行快照),以便在故障后快速恢复数据。
- 开启AOF(Append - Only File)持久化方式,在Redis配置文件中设置
- 主从复制与哨兵:
- 配置主从复制,将数据复制到多个从节点,提高数据的可用性。在从节点配置文件中设置
slaveof <masterip> <masterport>
。 - 使用哨兵(Sentinel)机制来监控主节点的状态,当主节点发生故障时,自动进行主从切换。在哨兵配置文件(sentinel.conf)中设置监控的主节点信息等参数。
- 配置主从复制,将数据复制到多个从节点,提高数据的可用性。在从节点配置文件中设置
应对缓存雪崩、缓存穿透和缓存击穿问题
- 缓存雪崩:
- 设置不同过期时间:为不同商品设置随机的过期时间,避免大量缓存同时过期。例如,商品A的过期时间设置为1 - 2小时内的随机值,商品B的过期时间设置为2 - 3小时内的随机值。
- 使用互斥锁:在缓存失效时,通过互斥锁(如
SETNX
命令)保证只有一个请求去加载数据库数据并更新缓存,其他请求等待。当第一个请求更新完缓存后,其他请求可以直接从缓存获取数据。
- 缓存穿透:
- 布隆过滤器:在查询数据前,先通过布隆过滤器判断数据是否存在。如果布隆过滤器判断数据不存在,则直接返回,不再查询数据库。布隆过滤器可以使用Redis的
BF.ADD
和BF.EXISTS
命令实现。 - 缓存空值:当查询数据库发现数据不存在时,也将空值缓存起来,并设置较短的过期时间,避免每次都查询数据库。
- 布隆过滤器:在查询数据前,先通过布隆过滤器判断数据是否存在。如果布隆过滤器判断数据不存在,则直接返回,不再查询数据库。布隆过滤器可以使用Redis的
- 缓存击穿:
- 热点数据不过期:对于热点商品,不设置过期时间,由后台定期更新缓存数据。
- 互斥锁:与缓存雪崩中使用互斥锁类似,在单个热点数据缓存失效时,通过互斥锁保证只有一个请求去加载数据库数据并更新缓存。