本文部分翻译自Josiah L Carlson的《Redis in Action》,CHAPTER 8: Building a simple social network。
分享是Twitter这样的社交网站的基本功能。关注则意味着你对对方所发表的内容感兴趣并且希望得到对方的关注。
本节我们将讨论如何管理用户的关注与粉丝列表,以及在进行关注/取消关注后用户首页的时间轴的变化。
在之前实现时间轴时,我们将状态消息的ID和时间戳放在ZSET中,这里同样可以使用该方法,将用户ID作为成员并以关注的时间作为分数。如下图所示:
在进行关注或取消关注的时候,需要更新用户的关注列表以及对方的粉丝列表,并更新各用户profile内的相应计数。之后还需将对方的时间轴拉取过来以保证能即时显示对方的动态。以下代码实现了关注操作:
HOME_TIMELINE_SIZE = 1000 def follow_user(conn, uid, other_uid): fkey1 = 'following:%s'%uid fkey2 = 'followers:%s'%other_uid # 如已经关注了,则返回None if conn.zscore(fkey1, other_uid): return None now = time.time() pipeline = conn.pipeline(True) # 将被关注者的uid添加到关注者的关注列表中, # 并将关注者的id添加到被关注者的粉丝列表中 pipeline.zadd(fkey1, other_uid, now) pipeline.zadd(fkey2, uid, now) # 获得count pipeline.zcard(fkey1) pipeline.zcard(fkey2) # 获得被关注者最近的状态消息 pipeline.zrevrange('profile:%s'%other_uid, 0, HOME_TIMELINE_SIZE-1, withscores=True) following, followers, status_and_score = pipeline.execute()[-3:] # 数据更新 pipeline.hset('user:%s'%uid, 'following', following) pipeline.hset('user:%s'%other_uid, 'followers', followers) # 添加对方最近的状态消息至关注用户的首页时间轴内 if status_and_score: pipeline.zadd('home:%s'%uid, **dict(status_and_score)) # 删除超出的部分 pipeline.zremrangebyrank('home:%s'%uid, 0, -HOME_TIMELINE_SIZE-1) pipeline.execute() return True
而取消关注的很明显就是关注的逆操作,如下所示:
def unfollow_user(conn, uid, other_uid): fkey1 = 'following:%s'%uid fkey2 = 'followers:%s'%other_uid if not conn.zscore(fkey1, other_uid): return None pipeline = conn.pipeline(True) # 从相关用户的关注/粉丝列表中去掉 pipeline.zrem(fkey1, other_uid) pipeline.zrem(fkey2, uid) # 重新计算计数 pipeline.zcard(fkey1) pipeline.zcard(fkey2) # 提取取消关注的那个用户的状态消息列表 pipeline.zrevrange('profile:%s'%other_uid, 0, HOME_TIMELINE_SIZE-1) following, followers, statuses = pipeline.execute()[-3:] # 数据更新 pipeline.hset('user:%s'%uid, 'following', following) pipeline.hset('user:%s'%other_uid, 'followers', followers) # 将对方的状态消息从时间轴中去掉 if statuses: pipeline.zrem('home:%s'%uid, *statuses) pipeline.execute() return True
这样,一个基本的关注/取消关注功能就实现了。