面试题答案
一键面试设计思路
- 用户权限与商品权限关联:根据用户的会员等级、购买历史等标签,确定其对不同商品分类、价格区间和库存状态的访问权限。
- 利用Redis SORT命令:借助Redis SORT命令,通过对商品数据进行排序和过滤,只返回符合用户权限的商品列表。
数据结构
- 用户数据:使用哈希表(Hash)存储用户信息,键为用户ID,值为包含会员等级、购买历史等标签的哈希表。例如:
HSET user:1 member_level 3 purchase_history "product1,product2"
- 商品数据:同样使用哈希表存储商品信息,键为商品ID,值为包含分类、价格、库存状态等信息的哈希表。例如:
HSET product:1 category "electronics" price 100 stock_status "in_stock"
- 权限映射:使用有序集合(Sorted Set)来建立用户权限与商品的映射关系。有序集合的成员为商品ID,分值可以用来表示优先级等信息。例如,对于会员等级为3的用户,其有权访问的电子产品:
ZADD user:1:category:electronics 0 product:1
命令实现
- 获取用户权限内商品列表:
# 获取用户的会员等级
MEMBER_LEVEL=$(HGET user:{user_id} member_level)
# 获取用户权限对应的商品ID集合
ZRANGE user:{user_id}:category:{category} 0 -1 WITHSCORES | \
while read product_id score; do
# 获取商品详细信息
HGETALL product:$product_id
done
- 结合SORT命令进行过滤:如果需要根据价格区间等更多条件过滤,可以结合SORT命令。假设要获取价格在50到150之间的商品:
SORT product:* BY price ASC GET product:*->category GET product:*->price \
WHERE price >= 50 AND price <= 150
并发访问问题应对
- 乐观锁:在更新商品库存等操作时,使用乐观锁机制。例如,在修改库存前,先获取当前库存值,更新时通过
WATCH
命令监控该键,确保在更新过程中库存未被其他进程修改。
WATCH product:{product_id}
current_stock=$(HGET product:{product_id} stock_status)
# 假设减少库存操作
new_stock=$((current_stock - 1))
MULTI
HSET product:{product_id} stock_status $new_stock
EXEC
- 队列处理:对于并发访问量较大的场景,可以将请求放入队列(如Redis的List),然后由后台进程按顺序处理,避免同时对商品数据进行读写操作导致的数据不一致问题。
# 将商品购买请求放入队列
RPUSH purchase_queue {user_id}:{product_id}
后台进程不断从队列中取出请求并处理:
while true; do
request=$(LPOP purchase_queue)
if [ -n "$request" ]; then
# 处理购买请求逻辑
IFS=: read user_id product_id <<< "$request"
# 调用上述库存更新等操作
fi
done