跳到主要内容

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 分
  • 设置一个最长更新间隔,当最晚下次更新时间超过最长更新间隔时设置为最长更新间隔,但不修改预测分数

论证

理想递减

考虑一个固定每 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)

实现

预处理

  1. 取当前时间time t0
  2. 将过去十天的数据读入内存,设为循环数组vector A
  3. 设发布时间为tPublish,将数组AtSort = (t0 - tPublish) % [24h]排序
  4. 设状态值 float s = 0
  5. 计算下次更新时间

计算下次更新时间

  1. 取当前时间time t1
  2. 搜索数组A并将指针p指向tSort > (t0 - t1) % [24h]tSort最小的项目,设指针指向的项目的发布时间为time tp
  3. 设下次更新时间time t = [5min] / s
  4. tp < t则更新状态值 s = s + 1 - {int((tp - t) / [24h]) * 0.1},取s = min(s, 1)
  5. s > 1,则下次更新时间t = tp
  6. 将指针向tSort增加的方向移动一个项目
  7. tp < t,回到第四步
  8. 设置计划任务

更新后处理

  1. 对于获取到的新项目
    1. 若发布时间不可解析,设置为此次更新的执行时间
    2. 若发布时间不合理(远远早于或晚于此次更新的执行时间),则警告该订阅不适用本算法,更换为固定间隔刷新
  2. 将新项目加入循环数组A
  3. 状态值s = s / 2
  4. 计算下次更新时间