Redis 7用ZSET实现游戏排行榜(如ZADD、ZREVRANGE)和String+TTL管理在线状态(如SET EX、EXISTS),结合原子操作、过期策略与PHP pipeline优化,兼顾高性能与可靠性。

用 Redis 7 存游戏排行榜和在线状态,核心是选对数据结构、用好原子操作、注意过期策略——不是所有场景都适合用同一个命令。
排行榜用 Sorted Set(ZSET)最稳
ZSET 天然支持按分数排序、范围查询、排名计算,特别适合实时榜单。Redis 7 对 ZSET 做了性能优化(比如跳表改进),高并发写入更可靠。
-
存玩家分数:用玩家 ID 当 member,当前得分为 score,例如
ZADD leaderboard 12500 "uid:8892" -
查前 10 名:用
ZREVRANGE leaderboard 0 9 WITHSCORES(倒序,最高分在前) -
查某人排名:用
ZREVRANK leaderboard "uid:8892"(返回从 0 开始的索引,+1 就是名次) -
分数动态更新:直接
ZADD leaderboard XX 13200 "uid:8892"(XX 表示只更新已有成员,避免误插入) - 自动清理旧数据:不建议给 ZSET 设过期时间(Redis 不支持),改用定期脚本或业务层逻辑淘汰低分条目
在线状态用 String + 过期键最轻量
每个玩家上线时设一个带 TTL 的 key,下线删掉;没删干净也不怕,超时自动消失。Redis 7 的内存淘汰策略(如 volatile-lru)能更好应对突发大量在线用户。
-
标记上线:用
SET online:uid:8892 1 EX 300(5 分钟自动过期) -
刷新心跳:上线后每 2–3 分钟执行一次
EXPIRE online:uid:8892 300 -
查是否在线:
EXISTS online:uid:8892或批量用MEXISTS online:uid:8892 online:uid:7711(Redis 7.0+ 支持) -
查总在线数:用
SCAN配合模式匹配(如online:uid:*)再计数,或另起一个计数器INCR online:total/DECR online:total(需保证上下线操作原子性)
PHP 实操要点(Redis 7 客户端适配)
PHP 用 phpredis 扩展(v5.3.7+ 支持 Redis 7 新特性),别用老版本或 Predis(不支持部分新命令)。
-
连接要启用 pipeline:批量更新排行榜或心跳时,用
$redis->pipeline()->zAdd(...)->expire(...)->exec()减少网络开销 - ZSET 分数用整型:PHP 传浮点分数可能精度丢失,统一转成 int(如得分 × 100)
-
防穿透加布隆过滤器(可选):高频查不存在的 uid 时,先过一层
BF.EXISTS(RedisBloom 模块),减少无效 key 查询 -
上线/下线要幂等:用
SET online:uid:8892 1 NX EX 300(NX 确保只设一次),下线用DEL即可
别踩这些坑
Redis 不是万能数据库,有些逻辑必须由 PHP 控制边界。
- ZSET 的
ZCARD返回总人数,但不等于“活跃在线”,它包含所有历史记录;在线状态必须单独维护 - 不要把玩家详细资料(昵称、头像)全塞进 ZSET 的 member 字符串里——member 只该是唯一 ID,详情查 MySQL 或缓存到 Hash
- 排行榜全量拉取(如 ZRANGE leaderboard 0 -1)在百万级数据时会卡主进程,前端分页查、后端加 LIMIT,必要时用
SCAN渐进式同步 - 单机 Redis 要做好持久化(RDB+AOF)和主从,线上务必禁用
FLUSHALL权限,防误操作清空榜单
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











