RSS刷新
思路
- 维护一个预测分数,该预测分数是一个取值范围 [1,0] 的浮点数
- 将历史记录按天分组,一天前的每条记录提供1分,两天前每条提供0.9分,线性减少,一共使用十天的数据
- 每次执行更新后,将预测分数除以二(指数衰减)
- 预测分数到达1时立刻更新,否则将五分钟除以预测分数得出最晚下次更新时间
- 从当前开始累加历史记录中从当前时间点到下次更新时间的记录的分数,每加一次,重新计算最晚下次更新时间,若某次加分导致最晚下次更新时间早于加分时间,则在加分时刻更新
- 例如当前时间为1点,预测分数为0.5,存在一条前一天1点6分的记录,则预测分数为
min(0.5+0.9, 1) = 1
,下次更新时间为1点6分 - 又如当前时间为1点,预测分数为0.5,不存在1点至1点10分之间的记录,则下次更新时间为1点10分
- 又如当前时间为1点,预测分数为0.5,存在一条六天前1点6分的记录,则预测分数加0.4,计算最晚下次更新时间为1点5分30秒,不能早于加分时间,故设置为1点6分
- 例如当前时间为1点,预测分数为0.5,存在一条前一天1点6分的记录,则预测分数为
- 设置一个最长更新间隔,当最晚下次更新时间超过最长更新间隔时设置为最长更新间隔,但不修改预测分数
论证
理想递减
考虑一个固定每23小时更新一次的订阅源,即每天都比前一天早一小时更新。第一天20点更新,则第十天10点更新,在第十一天初始化本算法,几个关键时间点:
- 10点(得分0+1->1更新1->0.5)
- 10点10分(更新0.5->0.25)
- 10点30分(更新0.25->0.125)
- 11点(得分0.125+0.9->1更新1->0.5)
- ...
- 12点(得分0.125+0.8->0.925更新0.925->0.4625)
- ...
- 13点(得分0.115+0.7->0.815更新0.815->0.4)
- ...
一天中一共进行了约30次更新,平均更新频率48分钟/次
理想递增
考虑一个固定每25小时更新一次的订阅源,即每天都比前一天晚一小时更新,第一天10点更新,则第十天20点更新,在第是一天初始化本算法,几个关键时间点:
- 10点(得分0+0.1->0.1更新0.1->0.05)
- 11点(得分0.05+0.2->0.25更新0.25->0.125)
- 11点40分(更新0.125->0.0625)
- 12点(得分0.0625+0.3->0.3625更新0.3625->0.18125)
- 12点27分(更新0.18125->0.09)
- 13点(得分0.09+0.4->0.49更新0.49->0.245)
实现
预处理
- 取当前时间
time t0
- 将过去十天的数据读入内存,设为循环数组
vector A
- 设发布时间为
tPublish
,将数组A
按tSort = (t0 - tPublish) % [24h]
排序 - 设状态值
float s = 0
- 计算下次更新时间
计算下次更新时间
- 取当前时间
time t1
- 搜索数组
A
并将指针p
指向tSort > (t0 - t1) % [24h]
中tSort
最小的项目,设指针指向的项目的发布时间为time tp
- 设下次更新时间
time t = [5min] / s
- 若
tp < t
则更新状态值s = s + 1 - {int((tp - t) / [24h]) * 0.1}
,取s = min(s, 1)
- 若
s > 1
,则下次更新时间t = tp
- 将指针向
tSort
增加的方向移动一个项目 - 若
tp < t
,回到第四步 - 设置计划任务
更新后处理
- 对于获取到的新项目
- 若发布时间不可解析,设置为此次更新的执行时间
- 若发布时间不合理(远远早于或晚于此次更新的执行时间),则警告该订阅不适用本算法,更换为固定间隔刷新
- 将新项目加入循环数组
A
- 状态值
s = s / 2
- 计算下次更新时间