redis 新浪微博中部分应用分析

Jackey Redis 2,650 次浏览 , 没有评论

创建用户账号

注册一个新的微博账号,有三样信息是必须的:
1. 邮箱地址,不能和已有的 邮箱地址相同(实际上也可以使用手机来注册,但 这里只考虑邮箱)。
2. 密码
3. 名字,不能和已有的名字相同。
需要解决的问题:
1. 实现一个检查指定的邮箱和名字是否已经被使用的程序。
2. 实现一个储存邮箱地址、密码和名字等用户信息的程序,并为每个用户分配一个唯一的用户 ID 。

唯一值检查

为了检查指定的名字和邮箱是否已经存在,程序会使用 weibo::used_names 和 weibo::used_emails这两个集合来分别储存所有已经被使用的名字以及所有已 经被使用的邮箱地址:
weibo::used_names = {‘mary’, ‘jack’, ‘tom’, …}
weibo::used_emails = {‘abcdefg999@gmail.com’, ‘go123@qq.com’, ‘qwe10086@163.com’, …}
每当用户尝试注册账号的时候,程序就检查这两个集合,看指定的名字或者 邮箱是否已经被使用。
如果用户指定的名字和邮箱都没有被使用,那么程序就会允 许用户注册,当用户成功注册的时候,程序就会使用 SADD 命令,把新用户的名字和邮箱地址分别添加到两个集合里面。

SISMEMBER 检查元素是否唯一

储存账号信息

当用户指定的邮箱地址和名字都可以使用 时,程序就会为这个新用户分配一个唯一 ID ,并将 ID 、邮箱地址、名字、密码等信息都储存到格式为 weibo::user::<id> 的散列键里面。
举个例子,如果程序给用户分配的 ID 为 10086 ,用户给定的邮箱为 hello@gmail.com 、名字为 peter、密码为 123456 ,那么程序将执行以下命令:

HMSET weibo::user::10086 id 10086
                         email hello@gmail.com
                         name peter
                         password 123456

虽然键名里面已经包含了 ID ,但是将 ID 也包含在散列里面,在取出用 户的所有信息时比较方便。

关联用户的 email 地址和 ID

除了将用户的信息储存到散列里面之外,程序 还必须再使用一个散列来记录用户的 email 和 ID 之间的关联,这是因为用户在登录的时候,需要输入 email 和密码,但如果程序不知道这个 email 对应的用户ID 是什么的话,那么用户身份验证操作将无法进行。
email 和 ID 之间的关联使用 weibo::email_to_uid 散列来保存,对于 email 为 hello@gmail.com , ID 为10086 的账号,程序将执行以下命令来对它们进行关联:
HSET weibo::email_to_uid hello@gmail.com 10086
这样在登录的时候,程序就可以通过 weibo::email_to_uid 这个散列,查询到与邮箱 hello@gmail.com 对应的用户的 ID 为 10086 ,接着就可以通过取出 weibo::user::10086 散列里面的信息来进行身份验证操作。

根据 email 查找与之关联的用户 ID ,然后根据 ID 取出用户数据,进行密码对比。

用户关系的实现

为了实现关注功能,程序会为每个用户使用两个集合:
1. 关注集合,用于储存用户关注的人的 ID ,键名格式为 weibo::user::<id>::following 。
2. 粉丝集合,用于储存用户的粉丝的 ID ,键名格式为 weibo::user::<id>::fans 。
每当用户 A 关注用户 B 的时候,程序会执行以下两个动作:
1. 将用户 B 的 ID 添加到用户 A 的关注集合里面。
2. 将用户 A 的 ID 添加到用户 B 的粉丝集合里面。
举个例子,假设 ID 为 10086 的用户关注了 ID 为 12345 的用户,那么程序将执行以下命令:
1. SADD weibo::user::10086::following 12345
2. SADD weibo::user::12345::fans 10086

检查 a 的关注集合是否包含 b,判断a是否关注b

检查 a 的关注集合是否包含 b ,以及 b 的关注集合是否包含 a ,判断a、b是否相互关注

计算 a 和 b 的关注集合的交集,获取共同关注的人

发送微博功能的实现

对于每条微博,程序都会 为它分配一个唯一的 ID ,并将这条微博的 ID 、作者的用户 ID、内容、UNIX时间戳格式的发送时间等信息储存到一个格式为 weibo::message::<id> 的散列键里面。
举个例子,假设 ID 为 10086 的用户在时间 1409468643 发送了一条内容为 “hello world” 的微博,并且程序为这条微博分配的唯一 ID 为 65535 ,那么程序将执行以下命令来储存这条微博:

HMSET weibo::message::65535 id 65535
                            author 10086
                            time 1409468643
                            content “hello world”

时间线功能的实现

程序会为每个用户储存两条时间线:
1. 定制时间线,包含了用户自己以及用户正在关注的人发送的微博,键名为 weibo::user::<id>::custom_timeline 。
2. 个人时间线,只包含用户自己发送的微博,键名为 weibo::user::<id>::personal_timeline 。
每条时间线都是一个有序集合,有序集合的元素 为微博的 ID ,分值为微博的发布时间。每当用户发送新的微博时,程序就会使用 ZADD 命令,将新微博的 ID 以及发布时间添加到有序集合里面。
举个例子,如果 ID 为 10086 的用户在时间 1409485668 发表了 ID 为 65535 的新微博,那么为了将这条微博推入到用户的个人时间线里面,程序将执行命令:
ZADD weibo::user::10086::personal_timeline 1409485668 65535

ZREVRANGE 以从新到旧的顺序翻页取出有序集合储存的微博 ID

广播操作

每当用户发送一条新微博的时候,程序不仅要将这条微博推入到该用户的定制时间线和个人时间线里面,还需要将这条微博推入到该用户的所有粉丝的定制时间线里面。
举个例子,假设 ID 为 255255 、 123321、 98765 的用户正在关注 ID 为 10086 的用户,那么当 ID 为10086 的用户在时间 1409485668 发送一条 ID 为 65535 的微博时,程序不仅要将这条微博推入到用户 10086 的定制时间线和个人时间线里面:
ZADD weibo::user::10086::custom_timeline 1409485668 65535
ZADD weibo::user::10086::personal_timeline 1409485668 65535
还需要将这条微博推入到 10086 的三个粉丝的定制时间线里面:
ZADD weibo::user::255255::custom_timeline 1409485668 65535
ZADD weibo::user::123321::custom_timeline 1409485668 65535
ZADD weibo::user::98765::custom_timeline 1409485668 65535

点赞功能的实现

对于每条微博,程序都会创建一个 weibo::message::<id>::like 集合来储存所有已经为该微博点赞的用户。
举个例子,假设 ID 为 10086 的用户为 ID 为 65535 的微博点赞了,那么程序将执行命令:
SADD weibo::message::65535::like 10086

SISMEMBER 检查用户是否有点赞

SREM 将用户 ID 从集合中移除

SCARD 获取点赞人数

SMEMBERS 返回所有点赞用户

评论示例

用户可以对每条微博进行评论。
对于每条评论,程序都会分配一个唯一的 评论 ID ,并使用格式为 weibo::comment::<id> 的散列键来储存评
论的发布者、发布时间和内容。对于每条微博,程序都会使用一个列表来 储存该微博获得的所有评论的 ID ,列表的键名格式为 weibo::message::<id>::comments 。
每当微博有新的评论出现时,程序就会将新评论的 ID推入到列表里面。

举个例子,假设 ID 为 10086 的用户对 ID 为 65535 的微博发表了内容为 “nice post” 的评论,并且程序为评论分配的 ID 为 3050 的话,那么程序将执行以下命令来储存这条评论:

HMSET weibo::comment::3050 id 3050
                           author 10086
                           content “nice post”
                           time 1410123456

并执行以下命令,将评论推入到 ID 为 65535 的微博的评论列表里面:
LPUSH weibo::message::65535::comments 3050

LLEN 获取评论总量

LRANGE 分页获取数据

转发微博示例

举个例子,如果 ID 为 12345 的用户在时间 1500000000 转发了 ID 为 65535 的消息,转发时说的内容为 “又获得推荐了,感谢码农周刊![太开心]” 的话,并因此产生一条 ID 为 100000 的新微博的话,那么程序将执行以下命令来创建这条转发微博:

HMSET weibo::message::100000 id 100000
                             author 12345
                             time 1500000000
                             content “又获得推荐了,感谢码农周刊![太开心]”
                             origin_message_id 65535

除了多出一个引用属性 origin_message_id 之外,转发产生的微博和普通微博之 间没有任何不同,所以转发微博可以与普通微博共用相同格式的 键名,以及 ID 生成器、时间线、点赞、评论等功能。
唯一需要注意的是,当程序需要取出 时间线里面的微博并显示给用户看的时候,普通微博可以直接 显示,而转发微博则需要根据 origin_message_id 取出被引用的微博之后,才能 显示。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Go