本文目录导读:

- 方案一:基于固定公式的简单排序(适合MVP或中小型项目)
- 方案二:基于对数函数的Hacker News风格算法(适合社区/新闻站)
- 方案三:使用Redis实现实时热度排序(适合高并发)
- 方案四:定时离线计算(适合复杂逻辑、大数据量)
- 总结建议
在PHP项目中实现热度排序,通常需要结合时效性和用户行为来设计算法,常见的方案有两种:基于固定公式的权重排序(适合中小型项目)和基于对数衰减的分数计算型平台)。
下面提供几种核心实现思路和对应的PHP代码示例。
核心思想
热度 = 用户行为得分 × 时间衰减因子
- 用户行为:浏览量、点赞、评论、收藏、分享等,不同行为赋予不同权重。
- 时间衰减:越新的内容,热度加成越高;越旧的内容,得分慢慢变低。
基于固定公式的简单排序(适合MVP或中小型项目)
这种方案直接在SQL查询中计算得分,适合数据量不大的场景。
数据库表结构示例
CREATE TABLE articles (
id INT PRIMARY KEY AUTO_INCREMENT,VARCHAR(255),
views INT DEFAULT 0,
likes INT DEFAULT 0,
comments INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
PHP + MySQL 代码实现
<?php
// 定义行为权重
define('WEIGHT_VIEW', 1);
define('WEIGHT_LIKE', 5);
define('WEIGHT_COMMENT', 10);
// 定义时间衰减参数(半衰期:3600秒 = 1小时)
define('HALF_LIFE', 3600);
function getHotArticles($pdo, $page = 1, $pageSize = 20) {
$offset = ($page - 1) * $pageSize;
$now = time();
$sql = "SELECT id, title,
(
(views * :weight_view + likes * :weight_like + comments * :weight_comment)
/ POWER(2, (:now - UNIX_TIMESTAMP(created_at)) / :half_life)
) AS hot_score
FROM articles
ORDER BY hot_score DESC
LIMIT :offset, :pageSize";
$stmt = $pdo->prepare($sql);
$stmt->execute([
':weight_view' => WEIGHT_VIEW,
':weight_like' => WEIGHT_LIKE,
':weight_comment' => WEIGHT_COMMENT,
':half_life' => HALF_LIFE,
':now' => $now,
':offset' => $offset,
':pageSize' => $pageSize
]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
说明:
- 公式:
热度 = (权重之和) / 2^((当前时间-发布时间)/半衰期) - 每经过一个半衰期,热度权重减半。
基于对数函数的Hacker News风格算法(适合社区/新闻站)
Hacker News 的经典热度算法更侧重于爆发性和早期推荐。
算法公式
热度 = (点赞数 - 踩数 + 1) / ((当前时间 - 发布时间) / 3600 + 2)^1.5
- 幂次1.5控制时间衰减的速度(越老衰减越快)。
PHP实现
<?php
function getHackerNewsScore($upvotes, $downvotes, $postTime) {
$score = ($upvotes - $downvotes);
if ($score < 0) $score = 0; // 防止负分
$ageHours = (time() - $postTime) / 3600;
if ($ageHours < 0) $ageHours = 0; // 防止未来时间
// 核心公式
return ($score + 1) / pow(($ageHours + 2), 1.5);
}
// 查询时直接计算
function getHackerNewsHotArticles($pdo) {
$sql = "SELECT id, title, upvotes, downvotes, created_at,
((upvotes - downvotes + 1) / POW((UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(created_at))/3600 + 2, 1.5)) AS hot_score
FROM articles
ORDER BY hot_score DESC
LIMIT 30";
return $pdo->query($sql)->fetchAll();
}
使用Redis实现实时热度排序(适合高并发)
如果项目量较大,直接在MySQL里算会拖慢查询,用Redis的 Sorted Set 可以实时更新热度。
行为发生时更新Redis
<?php
// 用户点赞某篇文章
$redis->zIncrBy('hot_articles', 5, 'article:123'); // 5 = 点赞权重
// 某文章被浏览
$redis->zIncrBy('hot_articles', 1, 'article:123'); // 1 = 浏览权重
// 时间衰减(定期执行)
$redis->zAdd('hot_articles', ['CH' => true], 'article:123', $newScore);
定时任务进行时间衰减
可以使用Laravel的Task Scheduling或crontab,每分钟执行一次衰减:
<?php
// 对Sorted Set中的所有元素执行时间衰减
public function decayHotScores() {
// 每个元素分数乘以衰减因子 0.95(每5分钟衰减5%)
$redis->zInterstore('hot_articles_temp', ['hot_articles'], [0.95]);
$redis->rename('hot_articles_temp', 'hot_articles');
}
获取热度排序
$hotArticles = $redis->zRevRange('hot_articles', 0, 19, true); // 前20名
定时离线计算(适合复杂逻辑、大数据量)
如果权重、算法经常变,或数据量极大,可以用定时脚本(如Laravel Job、cron任务)在后台算出热度并存入数据库缓存字段。
建立一个缓存字段
ALTER TABLE articles ADD COLUMN hot_score DECIMAL(10,4) DEFAULT 0;
定时脚本更新
<?php
// 每10分钟执行一次
function recalculateScores() {
$articles = Article::all();
foreach ($articles as $article) {
$age = time() - $article->created_at->timestamp;
$score = ($article->views * 1 + $article->likes * 5 + $article->comments * 10)
/ pow(($age / 3600 + 2), 1.5);
$article->hot_score = $score;
$article->save();
}
}
查询时直接 ORDER BY hot_score DESC,速度极快。
总结建议
| 项目规模 | 建议方案 | 原因 |
|---|---|---|
| 小型(日活<1000) | MySQL公式 | 简单、无额外依赖 |
| 中型社区/新闻站 | 方案二 + 方案四缓存 | 逻辑清晰,速度快 |
| 高并发、实时性强 | Redis Sorted Set | 避免数据库压力 |
| 算法复杂且多变 | 离线计算 | 灵活易维护 |
关于时间衰减的调整建议:
- 电影、知识类:半衰期可以设为7天(衰减慢)
- 短视频、新闻:半衰期设为30分钟(衰减快)
- 电商商品:可以按绝对时间分段(24小时内加权,之后逐步减弱)
你可以根据产品的核心指标(比如更看重“新”还是“热”)来调节权重和时间衰减系数。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播