1. Redis有序集合核心特性解析Redis的ZSET有序集合是我在分布式系统开发中最常使用的数据结构之一。与普通集合不同ZSET通过score实现自动排序的特性使其在排行榜、延迟队列等场景中表现卓越。每个元素都是唯一的但score可以重复这种设计在实现热度排序时特别有用。在实际项目中ZSET的典型应用包括实时排行榜如游戏积分榜带权重的任务队列时间轴排序社交动态范围查询地理位置附近的人注意ZSET虽然强大但元素数量超过百万级时内存占用会显著增加。我在电商秒杀系统中就曾遇到过ZSET内存暴涨的问题需要合理控制数据量。2. 基础操作指令详解2.1 元素操作指令ZADD是使用频率最高的指令其完整语法为ZADD key [NX|XX] [GT|LT] [CH] [INCR] score member [score member...]我在实际使用中发现几个关键点NX/XX参数控制更新行为NX仅添加新元素默认XX仅更新已存在元素LT/GT参数在Redis 6.2引入用于智能更新# 只在新score小于当前值时更新 ZADD myzset LT 90 player1CH返回值包含被修改元素总数包括新增和更新ZSCORE获取元素分值127.0.0.1:6379 ZSCORE rankings player1 89.52.2 范围查询指令ZRANGE和ZREVRANGE是最常用的范围查询指令我建议始终带上WITHSCORES参数ZRANGE rankings 0 -1 WITHSCORES # 正序获取全部 ZREVRANGE rankings 0 9 WITHSCORES # 倒序Top10在社交APP开发中我发现分页查询时使用ZRANGEBYSCORE更高效# 获取分数在80-100之间的元素 ZRANGEBYSCORE rankings 80 100 LIMIT 0 103. 高级应用与性能优化3.1 聚合操作指令ZUNIONSTORE和ZINTERSTORE可以实现多集合运算。在合并多个排行榜时WEIGHTS参数非常实用# 合并日榜和周榜日榜权重70% ZUNIONSTORE total_rank 2 daily_rank weekly_rank WEIGHTS 0.7 0.3重要经验聚合操作复杂度O(N)O(M)大集合合并建议在从库执行3.2 排名统计技巧ZCOUNT和ZLEXCOUNT的差异常被忽视ZCOUNT基于score范围统计ZLEXCOUNT基于字典序统计所有元素score必须相同在实现90分以上玩家占比功能时ZCARD rankings # 总人数 ZCOUNT rankings 90 inf # 90分以上人数3.3 内存优化方案当遇到ZSET内存问题时我通常采用以下方案拆分大ZSET# 按首字母拆分 ZRANGE all_data 0 1000 | xargs -L 100 redis-cli ZADD subset_使用ziplist编码需调整redis.confzset-max-ziplist-entries 128 zset-max-ziplist-value 64定期清理过期数据ZREMRANGEBYSCORE hot_topics -inf (current_timestamp - 86400)4. 实战问题排查记录4.1 分数精度问题在金融场景中使用ZSET时发现score的浮点数精度会导致排序异常ZADD transactions 10.0000000001 txn1 ZADD transactions 10.0000000002 txn2 ZRANGE transactions 0 -1 # 可能乱序解决方案使用整数放大法ZADD transactions 100000000001 txn1或者改用字符串分数ZADD transactions 10.0000000001 txn14.2 并发更新竞争在秒杀系统中遇到score更新竞争问题解决方案WATCH user_rank score ZSCORE user_rank user1 MULTI ZADD user_rank XX score10 user1 EXEC4.3 大key监控方法通过redis-cli定位大ZSETredis-cli --bigkeys | grep zset或者使用memory命令深入分析MEMORY USAGE my_big_zset5. 扩展应用模式5.1 时间序列存储利用ZSET存储时间戳事件数据ZADD events 1651234567 user:login ZADD events 1651234578 order:create # 查询最近1小时事件 ZRANGEBYSCORE events (1651234567-3600) 16512345675.2 延迟队列实现经典延迟队列方案# 添加任务 ZADD delay_queue 执行时间戳 task_data # 消费任务 while true; do tasks$(ZRANGEBYSCORE delay_queue 0 $(date %s) LIMIT 0 10) [ -z $tasks ] sleep 1 continue # 处理任务... ZREM delay_queue $tasks done5.3 热点数据统计滚动窗口统计热点商品-- 用LUA保证原子性 local key KEYS[1] local item ARGV[1] local now tonumber(ARGV[2]) local window 3600 redis.call(ZREMRANGEBYSCORE, key, 0, now - window) redis.call(ZADD, key, now, item) return redis.call(ZCOUNT, key, now - window, now)在电商系统中这套方案可以支撑每秒万级的热点更新请求。我建议对LUA脚本进行SHA缓存减少网络开销SCRIPT LOAD lua_script_content EVALSHA sha1_value 1 key_name item_name timestamp
阅读完成 · 觉得有帮助?