面试题答案
一键面试Redis数据结构设计
- 有序集合(Sorted Set):继续使用现有有序集合存储商品ID和销量。有序集合天然支持根据分值(销量)进行排序,可方便获取升序或降序数据。
- 哈希表(Hash):为每个商品ID创建一个哈希表,存储商品的详细信息,包括价格。例如,
HSET product:商品ID price 价格
。这样可以通过商品ID快速获取商品价格。
命令使用
- 获取升序商品列表:使用
ZRANGEBYSCORE
命令,指定价格区间对应的商品ID范围,同时可通过WITHSCORES
选项获取销量。例如,获取价格在100到200之间的商品,按销量升序排列:ZRANGEBYSCORE product:销量 0 +inf WITHSCORES BYLEX -[100,200]
(这里假设通过Lex字典序结合价格区间来筛选,实际应用中可根据具体情况调整)。 - 获取降序商品列表:使用
ZREVRANGEBYSCORE
命令,同样指定价格区间,获取按销量降序排列的商品ID列表及销量。例如:ZREVRANGEBYSCORE product:销量 +inf 0 WITHSCORES BYLEX -[100,200]
。 - 获取商品详细信息:根据获取到的商品ID,通过
HGETALL
命令从哈希表中获取商品详细信息。例如,HGETALL product:商品ID
。
高并发场景问题及解决方案
- 竞争问题:多个客户端同时对有序集合和哈希表进行读写操作可能导致数据不一致。
- 解决方案:使用Redis事务(
MULTI
、EXEC
)或Lua脚本。事务可以保证一组命令的原子性执行,Lua脚本在Redis服务器端执行,避免了网络开销和竞争条件。例如,在Lua脚本中可以同时处理有序集合查询和哈希表查询,确保数据一致性。
- 解决方案:使用Redis事务(
- 性能瓶颈:高并发读操作可能导致Redis服务器负载过高。
- 解决方案:
- 缓存分层:在应用层增加本地缓存(如Guava Cache),对于经常查询的商品列表进行缓存,减少对Redis的直接访问。
- 读写分离:使用Redis Sentinel或Redis Cluster实现读写分离,主节点负责写操作,从节点负责读操作,分担读压力。
- 解决方案:
- 数据一致性:在高并发写操作后,读操作可能获取到旧数据。
- 解决方案:
- 设置合理的过期时间:对缓存数据设置适当的过期时间,使数据在一定时间后更新,保证数据的最终一致性。
- 使用发布/订阅机制:当商品销量或价格更新时,通过发布/订阅机制通知相关客户端清除本地缓存,确保后续查询获取最新数据。
- 解决方案: