朋友圈的设计及实现

最近项目需求需要模拟微信的朋友圈功能,实现可以发送图文消息,好友可以查看,满足添加新的好友之后,可以在朋友圈中刷新到好友的消息,看了许多文章,琢磨出来一套流程。这里只记录一下我的实现思路,并不贴上实际的代码。

涉及朋友圈数据的有四个核心的表:
一个是发布。发布数据记录了来自所有用户所有的feed,比如一个用户发布了几张图片,每张图片的URL是什么>,在CDN里的URL是什么,它有哪些元属性,谁可以看,谁不可以看等等。
一个是相册。相册是每个用户独立的,记录了该用户所发布的所有内容。
一个是评论。评论就是针对某个具体发布的朋友评论和点赞操作。
一个是时间线。所谓“刷朋友圈”,就是刷时间线,就是一个用户所有朋友的发布内容。
引用自:微信朋友圈是怎么做的架构?

我在设计的时候参照了上面,把发布和相册融在了一起。
结构有三张表:

1
2
3
4
5
6
7
8
9
10
#消息表
CREATE TABLE `t_friend_circle_message` (
`id` bigint(15) NOT NULL AUTO_INCREMENT COMMENT '主键',
`uid` bigint(15) DEFAULT NULL COMMENT '用户id',
`content` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`picture` varchar(200) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT '' COMMENT '图片',
`location` varbinary(100) DEFAULT '' COMMENT '位置',
`create_time` datetime DEFAULT NULL COMMENT '创建日期',
PRIMARY KEY (`id`)
)

消息表很好理解,存储用户发送的内容,图片存地址。
utf8mb4格式可以存储emoji表情,具体可以参照之前的一篇文章mysql支持emoji

1
2
3
4
5
6
7
8
9
#时间轴表
CREATE TABLE `t_friend_circle_timeline` (
`id` bigint(15) NOT NULL AUTO_INCREMENT,
`uid` bigint(15) DEFAULT NULL COMMENT '用户id',
`fcmid` bigint(15) DEFAULT NULL COMMENT '朋友圈消息id',
`is_own` int(1) DEFAULT '0' COMMENT '是否是自己的',
`create_time` datetime DEFAULT NULL COMMENT '创建日期',
PRIMARY KEY (`id`)
)

时间轴表在朋友圈中是最关键的,因为当用户去拉取好友圈的时候,查询的就是本表。
当用户A有发布了一条朋友圈,用户A及所有和A有好友关系的用户都需要拿到消息id,然后插入到本表里面。
用户A的is_own设置为1,好友设置为0,区分时间轴上的好友消息是否是本人发布的。
表示在每个人的时间轴上都增加了一条消息。

比如有两个用户小王和Mary。小王和Mary各自有各自的相册,可能在同一台服务器上,也可能在不同的服务器上。现在小王上传了一张图片到自己的朋友圈。上传图片不经过微信后台服务器,而是直接上传到最近的腾讯CDN节点,所以非常快。图片上传到该CDN后,小王的微信客户端会通知微信的朋友圈CDN:这里有一个新的发布(比如叫K2),这个发布的图片URL是什么,谁能看到这些图片,等等此类的元数据,来把这个发布写到发布的表里。

在发布的表写完之后,会把这个K2的发布索引到小王的相册表里。所以相册表其实是很小的,里面只有索引指针。相册表写好了之后,会触发一个批处理的动作。这个动作就是去跟小王的每个好友说,小王有一个新的发布,请把这个发布插入到每个好友的时间线里面去。

然后比如说现在Mary上朋友圈了,而Mary是小王的一个好友。Mary拉自己的时间线的时候,时间线会告诉到有一个新的发布K2,然后Mary的微信客户端就会去根据K2的元数据去获取图片在CDN上的URL,把图片拉到本地。

引用自:微信朋友圈是怎么做的架构?

1
2
3
4
5
6
7
8
9
10
#评论表
CREATE TABLE `t_friend_circle_comment` (
`id` bigint(15) NOT NULL AUTO_INCREMENT,
`fcmid` bigint(15) DEFAULT NULL COMMENT '朋友圈信息id',
`uid` bigint(15) DEFAULT NULL COMMENT '用户id',
`content` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`create_time` datetime DEFAULT NULL COMMENT '创建日期',
`like_count` int(10) DEFAULT '0' COMMENT '点赞数',
PRIMARY KEY (`id`)
)

评论表。