首页 > 编程语言 >ThinkPHP 8.0 基于 Redis Sorted Set 实现排行榜【热榜】

ThinkPHP 8.0 基于 Redis Sorted Set 实现排行榜【热榜】

来源:互联网 2026-07-15 19:30:03

在ThinkPHP8.0中,基于RedisSortedSet实现热榜需配置连接与前缀,通过zAdd写入热度分数,用zRevRange分页获取TopN,更新时直接zAdd覆盖,删除单条用zRem,清空榜单用del。需注意整数转字符串、分数强转及分页起始位置计算等细节。

在ThinkPHP 8.0中,利用Redis Sorted Set构建实时热榜的核心步骤包括:配置Redis连接与prefix,使用zAdd写入热度分数,通过zRevRange分页获取Top N,更新时直接zAdd覆盖,单条删除使用zRem,清空整个榜单用del。每个环节都需注意细节,以确保系统稳定高效。

ThinkPHP 8.0 基于 Redis Sorted Set 实现排行榜【热榜】

长期稳定更新的攒劲资源: >>>点此立即查看<<<

无论是文章、商品还是视频,凡涉及热度排序的场景,都需要一个能实时更新的排行榜。若直接使用数据库的ORDER BY,当数据量增大时,响应时间会急剧上升。因此,必须借助Redis的Sorted Set结构。

配置Redis连接并启用Sorted Set支持

打开config/cache.php,确认默认缓存驱动已设为redis,并仔细检查redis配置项中的host、port、password、database是否填写正确。若使用哨兵或集群模式,还需额外配置sentinel或cluster选项,否则Sorted Set操作将静默失败,导致排查问题耗时。

此外,在config/redis.php中,确保'prefix'字段不为空(例如设为'tp8:'),这样多个项目共享同一Redis实例时,key不会发生冲突。

定义热榜数据写入逻辑

在业务模型或服务类中,调用Redis客户端的zAdd方法写入分数。分为两种情况:

单条写入(适用于用户行为触发场景)
最常见的是用户点赞、评论时触发。直接调用 $this->redis->zAdd('hot:article', $score, $articleId) 即可。这里的$score为整型热度值,计算方式可自定义,例如阅读数×10 + 点赞数×50 + 评论数×100。注意,$articleId必须传字符串,若传整数ID,Redis虽会自动转为字符串,但容易导致去重异常,因此建议提前转换。

批量写入(适用于后台定时更新)
构造二维数组 $data = [['score' => 1280, 'member' => '1001'], ['score' => 942, 'member' => '1002']],然后调用 $this->redis->zAdd('hot:article', ...array_merge(...$data))。这里有一处陷阱:PHP 8.1及以上版本无法使用splat操作符展开关联数组,需先用array_column($data, 'score', 'member')转为key-value格式再传入。

获取热榜前N名及分页数据

第一步:获取Top 10(降序,分数最高在前)
执行 $top10 = $this->redis->zRevRange('hot:article', 0, 9, ['withscores' => true]),返回格式类似 ['1001' => '1280', '1002' => '942']。注意score为字符串类型,参与计算前需用(int)强转。

第二步:分页获取第2页(每页20条)
起始位置 = (页码 1) × 每页条数,即$start = 20;结束位置 = 起始位置 + 每页条数 1 = 39。然后执行 $this->redis->zRevRange('hot:article', $start, $end, ['withscores' => true])

第三步:带条件过滤(如仅查有效文章)
先用zRevRange获取ID列表,再通过Db::whereIn('id', $ids)->select()到数据库补全字段。Sorted Set本身不支持条件筛选,因此该过滤必须在应用层完成。

更新与删除热榜条目

更新某文章热度:直接再次调用zAdd,传入相同member,Redis自动覆盖旧分数,无需先zRem再zAdd,节省操作步骤。

下架某文章(从热榜移除):必须使用zRem,而非del删除整个key,否则整个榜单数据将丢失。调用 $this->redis->zRem('hot:article', $articleId) 即可。

清空整个热榜(慎用)$this->redis->del('hot:article')。该操作不可逆,且会阻塞Redis其他请求直至删除完成,因此仅在必要时使用。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备14008430号-1 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。