Rails 关于实现一个近期热搜功能

luiswood · 2019年08月27日 · 最后由 luckrill 回复于 2019年08月29日 · 4696 次阅读

实现

目前自己用 mysql 实现了一个近期热搜功能,记录关键字、搜索次数、日期三个字段。

当用户搜索一个关键字时,会使用INSERT INTO DUPLICATE KEY UPDATE语句对关键字记录创建或更新搜索次数。

这样我就可以每隔一周,使用 SQL 语句分组累计查询出最近一周 TOP10 的关键字列表,并使用 redis 缓存,过一周后再刷新。

问题

目前每次刷新缓存时,分组累计查询语句会很慢,每天产生的记录很多,这种查询比较低效。


所以想来问一下有没有更高效的实现方式?

比如用 redis 的 sortset,但使用这个实现的话,取最近一周的日期怎么解决?

先按日期筛选一周的数据,然后按搜索次数排序,取 10 个数,满足需求吗?

我有个思路是定一个最小的时间间隔,比如每分钟的记录为一个 sortset,然后按需统计

redis = Redis.current
redis.zincrby("keyword:#{Time.now.strftime('%Y%m%d%H%M')}", 1, 'Ruby')

# 前一个小时的统计
hour = Time.now - 1.hour
start_time = hour.beginning_of_hour
end_time = hour.end_of_hour
keys = start_time.to_i.step(end_time.to_i, 60).collect { |t| "keyword:#{Time.at(t).strftime('%Y%m%d%H%M')}" }
redis.zunionstore("keyword:#{start_time.strftime('%Y%m%d%H')}", keys, aggregate: 'sum')

# 前一天的统计
day = Time.now - 1.day
start_time = day.beginning_of_day
end_time = day.end_of_day
keys = start_time.to_i.step(end_time.to_i, 60 * 60).collect { |t| "keyword:#{Time.at(t).strftime('%Y%m%d%H')}" }
redis.zunionstore("keyword:#{start_time.strftime('%Y%m%d')}", keys, aggregate: 'sum')

# 近一周top10关键词
start_time = (Time.now - 1.week).beginning_of_minute
end_time = Time.now.end_of_minute
keys = start_time.to_i.step(end_time.to_i, 60).collect { |t| "keyword:#{Time.at(t).strftime('%Y%m%d%H%M')}" }
redis.zunionstore("keyword:#{start_time.strftime('%Y%m%d%H%M')}-#{end_time.strftime('%Y%m%d%H%M')}", keys, aggregate: 'sum')
redis.zrevrange("keyword:#{start_time.strftime('%Y%m%d%H%M')}-#{end_time.strftime('%Y%m%d%H%M')}", 0, 9, with_scores: true)
3 楼 已删除
w7938940 回复

谢谢回复,下午试了一下这个方法,非常好,现在不仅解决了性能问题,近期热搜更新时间间隔我也减少到一天。 😁 😁

5 楼 已删除

keyword 和 weekday 做主键 weekday 和 search count 上面加索引 按每周倒排 top 5 不用缓存也飞快啊

需要 登录 后方可回复, 如果你还没有账号请 注册新账号