在redis中使用out-on-write的实用方法是什么?

时间:2014-04-05 01:59:40

标签: redis news-feed jedis

我有一个有很多主题的新闻网站。可能有数百万用户关注主题。 我为每个用户维护一个sortedset,以加载属于他们所关注主题的新闻。添加或更新文章时,我会将此文章写入受影响的用户列表。 具体来说,伪代码如下:

if a article is added/updated
  get all topics that the article belong (each article may belong to many topics)
    for each topic: get all topic followers
      update_user_news_list(userId, articleId)

这是带jedis的java代码:

static final int LIMIT_BATCH = 1000;
static void addToUserHomeFeed(int index, Jedis jd) {
        int range_limit = index + LIMIT_BATCH - 1;
        Set<String> list = jd.zrange("Follower:Topic:Id", index, range_limit); // get list of followers
        if (list.isEmpty())  return;
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
           // update user list
        }
        addToUserHomeFeed(range_limit + 1, jd);
}

问题是,我的网站目前有近100万用户,一些热门话题后面跟着大约80万用户,有时系统会产生“缓冲区溢出”错误。 我做错了什么还是有更好的方法? 我使用redis 2.4

1 个答案:

答案 0 :(得分:0)

好吧,我不是Redis的专家,但在我看来,喜欢在基于时间的排序集中存储最新的文章+文章的主题应该这样做:

ZADD lasttopics -[timestamp] Topic:1-Article:1 -[timestamp] Topic:2-Article:1 

将第1条添加到集合中,每个主题添加1次。集合中的每个键按unix时间戳的负数排名(因此后面的文章成为集合中的第一个)

现在,当用户登录时,首先获取他所关注的所有主题,然后使用“ZSCAN lasttopics 0”等迭代排序集,直到您在用户感兴趣的主题中有足够的文章。

这样,每次插入文章时,每个主题都会执行1次写入,并且您可以长篇大论地重复进入文章历史记录(仅针对非常老的主题感兴趣的用户 完成,大多数用户将在没有超载Redis的情况下,在前几篇文章中找到有趣的文章。

对于维护,您可以使用时间分数来移除旧组中的文章。