Categories
technology|技术 中文

支撑10亿用户的技术方案(实战篇)

项目简述

  • 总体需求:实现一个类Twitter的网站(仅实现网页版)
  • 功能列表:
  1. 帐号系统 (account)
  2. 个人资料页 (profile)
  3. 设置 (settings)
  4. 帮助 (help)
  5. 主页时间线 (home page, a.k.a., home timeline)
  6. 帖子 (post)
  7. 关注者,正在关注 (followers & following)
  8. 搜索 (search)
  9. 趋势 – 热门标签 (trending – popular hashtags)
  10. 热门用户 (popular users)
  11. 标签页 (搜索页的一种) – hashtags
  12. 通知 – notification

团队人员配置:

产品:1人,设计:1人,前端:1人,后端:2人

技术架构

参考文章: 支撑10亿用户的技术方案(思路篇)

Twitter架构图

开发实现

  • 开发节奏

1. 产品需求细化

对每个功能模块做具体的描述,画出产品的线框图

2. 前后端基础框架选择和制定标准的通讯接口

前后端都有成熟的框架可用,根据团队人员的经验进行选择即可。标准的通讯接口通常包括:1)正常代码和错误代码;2)返回的数据结构; 3)通讯安全策略

3. 数据库结构设计

根据需求文档定义数据库结构。在这个产品需求里,很容易整理出来,需要的数据表如下:user, post, reply, like, user_relationship。更详细的表结构定义在后面。

4. 数据接口(API)设计

有了线框图,就有了页面,根据页面元素,就可以整理出需要的数据,API就能定义出来了。

5. 前端页面实现(根据API,用模拟数据)

6. 后端API实现(常规实现,不包括高并发的方案)

7. 前后端联调

8. 后端支持分库分表,应对高并发

9. 部署方案

10. 功能测试 & 安全测试

11. 高并发测试

  • 时间评估

第一周:完成1和2

第二周:完成3和4

第三周~第五周:完成5、6、7

第六~第七周:完成8和9

第八~第十周:完成10和11,通过测试后就可以准备上线了

补充说明:时间的评估,要根据团队成员的经验和能力来,以上评估可以作为参考。由于产品有完全可参考的对象,无需原创;如果再机上团队成员能力很强,并且有丰富的高并发处理经验,以上评估是合理的。

数据库表结构设计

Mysql Database table structures


— Table structure for table tb_user

CREATE TABLE tb_user (
id bigint unsigned NOT NULL AUTO_INCREMENT,
username varchar(15) COLLATE utf8mb4_general_ci NOT NULL,
email varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
password varchar(64) COLLATE utf8mb4_general_ci NOT NULL,
display_name varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
banner_url varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
avatar_url varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
phone varchar(32) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
description text COLLATE utf8mb4_general_ci NOT NULL,
website varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
language varchar(8) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
time_zone varchar(8) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
location varchar(16) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
verified tinyint unsigned NOT NULL DEFAULT ‘0’,
suspended tinyint unsigned NOT NULL DEFAULT ‘0’,
dob_day tinyint unsigned NOT NULL DEFAULT ‘0’,
is_visible_dob_day tinyint unsigned NOT NULL DEFAULT ‘0’,
dob_month tinyint unsigned NOT NULL DEFAULT ‘0’,
is_visible_dob_month tinyint unsigned NOT NULL DEFAULT ‘0’,
dob_year smallint unsigned NOT NULL DEFAULT ‘0’,
is_visible_dob_year tinyint unsigned NOT NULL DEFAULT ‘0’,
activate_code varchar(6) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
is_activated tinyint unsigned NOT NULL DEFAULT ‘0’,
created_at bigint NOT NULL DEFAULT ‘0’,
updated_at bigint NOT NULL DEFAULT ‘0’,
PRIMARY KEY (id),
UNIQUE KEY uiq_username (username),
UNIQUE KEY uiq_email (email)
) ENGINE=InnoDB AUTO_INCREMENT=1000001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_user_extended

CREATE TABLE tb_user_extended (
user_id bigint unsigned NOT NULL,
count_followers int unsigned NOT NULL DEFAULT ‘0’,
count_followings int unsigned NOT NULL DEFAULT ‘0’,
count_posts int unsigned NOT NULL DEFAULT ‘0’,
count_likes int unsigned NOT NULL DEFAULT ‘0’,
pinned_post_id bigint unsigned NOT NULL DEFAULT ‘0’,
last_login bigint NOT NULL DEFAULT ‘0’,
timeline_updated_at bigint NOT NULL DEFAULT ‘0’,
created_at bigint NOT NULL DEFAULT ‘0’,
updated_at bigint NOT NULL DEFAULT ‘0’,
PRIMARY KEY (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_user_reset

CREATE TABLE tb_user_reset (
id bigint unsigned NOT NULL AUTO_INCREMENT,
user_id bigint unsigned NOT NULL,
username varchar(16) COLLATE utf8mb4_general_ci NOT NULL,
email varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
reset_code varchar(64) COLLATE utf8mb4_general_ci NOT NULL,
created_at bigint NOT NULL,
updated_at bigint NOT NULL DEFAULT ‘0’,
PRIMARY KEY (id),
KEY idx_email (email),
KEY idx_username (username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_reserved_username

CREATE TABLE tb_reserved_username (
id bigint unsigned NOT NULL AUTO_INCREMENT,
reserved_username varchar(16) COLLATE utf8mb4_general_ci NOT NULL,
notes text COLLATE utf8mb4_general_ci NOT NULL,
created_by int unsigned NOT NULL,
created_at bigint unsigned NOT NULL,
updated_at bigint unsigned NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY reserved_username (reserved_username)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_post

CREATE TABLE tb_post (
id bigint unsigned NOT NULL AUTO_INCREMENT,
user_id bigint unsigned NOT NULL,
post_type tinyint unsigned NOT NULL COMMENT ‘0: original post; 1: repost; 2: quoted repost; 3: comment (or reply)’,
original_type tinyint DEFAULT ‘0’,
original_id bigint unsigned NOT NULL,
content_text varchar(300) COLLATE utf8mb4_general_ci NOT NULL COMMENT ‘Text content; Max length 280’,
image_url varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
video_url varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
hashtags text COLLATE utf8mb4_general_ci NOT NULL,
location varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
place varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
source tinyint unsigned NOT NULL DEFAULT ‘0’ COMMENT ‘The source label of this post, e.g., iPhone, Android, Web, Default 0’,
reply_settings tinyint unsigned NOT NULL DEFAULT ‘0’ COMMENT ‘Shows you who can reply to a given Tweet. Fields returned are “everyone”, “mentioned_users”, and “followers”. default 0 “reply_settings”: “everyone” ‘,
is_deleted tinyint unsigned NOT NULL DEFAULT ‘0’,
created_at bigint NOT NULL DEFAULT ‘0’,
updated_at bigint NOT NULL DEFAULT ‘0’,
deleted_at bigint NOT NULL DEFAULT ‘0’,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_post_extended

CREATE TABLE tb_post_extended (
post_id bigint unsigned NOT NULL,
user_id bigint unsigned NOT NULL,
count_comments int unsigned NOT NULL DEFAULT ‘0’,
count_likes int unsigned NOT NULL DEFAULT ‘0’,
count_reposts bigint NOT NULL DEFAULT ‘0’,
count_quote int unsigned NOT NULL DEFAULT ‘0’,
count_shares int unsigned NOT NULL DEFAULT ‘0’,
count_reported bigint NOT NULL DEFAULT ‘0’,
is_deleted tinyint unsigned NOT NULL DEFAULT ‘0’,
created_at bigint NOT NULL DEFAULT ‘0’,
updated_at bigint NOT NULL DEFAULT ‘0’,
deleted_at bigint NOT NULL DEFAULT ‘0’ ,
PRIMARY KEY (post_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_post_like

CREATE TABLE tb_post_like (
id bigint unsigned NOT NULL AUTO_INCREMENT,
content_type tinyint DEFAULT ‘0’ COMMENT ‘0 post, 1 reply’,
record_id bigint unsigned NOT NULL,
liker_id bigint unsigned NOT NULL,
is_like tinyint unsigned NOT NULL DEFAULT ‘0’,
created_at bigint unsigned NOT NULL DEFAULT ‘0’,
updated_at bigint unsigned NOT NULL DEFAULT ‘0’,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_post_reply

CREATE TABLE tb_post_reply (
id bigint unsigned NOT NULL AUTO_INCREMENT,
user_id bigint unsigned NOT NULL,
post_id bigint unsigned NOT NULL,
content_text varchar(300) COLLATE utf8mb4_general_ci NOT NULL COMMENT ‘Text content; Max length 280’,
image_url varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
video_url varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
hashtags text COLLATE utf8mb4_general_ci NOT NULL,
location varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
place varchar(64) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ”,
source tinyint unsigned NOT NULL DEFAULT ‘0’ COMMENT ‘The source label of this post, e.g., iPhone, Android, Web, Default 0’,
is_deleted tinyint unsigned NOT NULL DEFAULT ‘0’,
created_at bigint NOT NULL DEFAULT ‘0’,
deleted_at bigint NOT NULL DEFAULT ‘0’,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_post_reply_extended

CREATE TABLE tb_post_reply_extended (
post_reply_id bigint unsigned NOT NULL,
user_id bigint unsigned NOT NULL,
post_id bigint unsigned NOT NULL,
count_comments int unsigned NOT NULL DEFAULT ‘0’,
count_likes int unsigned NOT NULL DEFAULT ‘0’,
count_reposts bigint NOT NULL DEFAULT ‘0’,
count_quote int unsigned NOT NULL DEFAULT ‘0’,
count_shares int unsigned NOT NULL DEFAULT ‘0’,
count_reported bigint NOT NULL DEFAULT ‘0’,
is_deleted tinyint unsigned NOT NULL DEFAULT ‘0’,
created_at bigint NOT NULL DEFAULT ‘0’,
updated_at bigint NOT NULL DEFAULT ‘0’,
deleted_at bigint NOT NULL DEFAULT ‘0’,
PRIMARY KEY (post_reply_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_post_reply_hashtag

CREATE TABLE tb_post_reply_hashtag (
id bigint unsigned NOT NULL AUTO_INCREMENT,
content_type tinyint DEFAULT NULL COMMENT ‘0 post, 1 reply’,
record_id bigint unsigned NOT NULL,
hashtag_id bigint unsigned NOT NULL,
created_at bigint NOT NULL DEFAULT ‘0’,
updated_at bigint NOT NULL DEFAULT ‘0’,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_recommended_hashtag

CREATE TABLE tb_recommended_hashtag (
id int NOT NULL AUTO_INCREMENT,
hashtag_id int NOT NULL,
rank int NOT NULL DEFAULT ‘0’,
created_at bigint unsigned DEFAULT ‘0’,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;


— Table structure for table tb_recommended_user

CREATE TABLE tb_recommended_user (
id int NOT NULL AUTO_INCREMENT,
user_id bigint unsigned DEFAULT NULL,
rank int DEFAULT ‘0’,
created_at bigint unsigned DEFAULT ‘0’,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;


— Table structure for table tb_reported_content

CREATE TABLE tb_reported_content (
id bigint unsigned NOT NULL AUTO_INCREMENT,
content_type tinyint DEFAULT ‘0’ COMMENT ‘0 post, 1 reply’,
record_id bigint unsigned NOT NULL,
post_user_id bigint unsigned NOT NULL,
reporter_id bigint unsigned NOT NULL,
report_reason tinyint unsigned NOT NULL,
created_at bigint NOT NULL DEFAULT ‘0’,
updated_at bigint NOT NULL DEFAULT ‘0’,
PRIMARY KEY (id),
KEY idx_post_id (record_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_reported_user

CREATE TABLE tb_reported_user (
id bigint unsigned NOT NULL AUTO_INCREMENT,
user_id bigint unsigned NOT NULL,
reporter_id bigint unsigned NOT NULL,
report_reason tinyint unsigned NOT NULL,
created_at bigint unsigned NOT NULL DEFAULT ‘0’,
updated_at bigint unsigned NOT NULL DEFAULT ‘0’,
PRIMARY KEY (id),
KEY idx_user_id_reporter_id (user_id,reporter_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_user_relationship

CREATE TABLE tb_user_relationship (
id bigint unsigned NOT NULL AUTO_INCREMENT,
user_id bigint unsigned NOT NULL,
target_user bigint unsigned NOT NULL,
status_follow tinyint unsigned NOT NULL DEFAULT ‘0’ COMMENT ‘0: unfollow; 1: follow; 2: block’,
status_mute tinyint unsigned NOT NULL DEFAULT ‘0’ COMMENT ‘0: unmute; 1: mute’,
created_at bigint NOT NULL DEFAULT ‘0’,
updated_at bigint NOT NULL DEFAULT ‘0’,
PRIMARY KEY (id),
UNIQUE KEY uiq_user_id_follwer_id (user_id,target_user),
KEY idx_follower_id (target_user)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_user_relationship_reversed

CREATE TABLE tb_user_relationship_reversed (
id bigint NOT NULL AUTO_INCREMENT,
user_id bigint DEFAULT NULL,
follower_id bigint DEFAULT NULL,
created_at bigint DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;


— Table structure for table tb_hashtag

CREATE TABLE tb_hashtag (
id bigint unsigned NOT NULL AUTO_INCREMENT,
tag_name varchar(128) COLLATE utf8mb4_general_ci NOT NULL,
user_id bigint unsigned NOT NULL,
count_mentions int unsigned NOT NULL DEFAULT ‘0’,
created_at bigint NOT NULL DEFAULT ‘0’,
updated_at bigint NOT NULL DEFAULT ‘0’,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;


— Table structure for table tb_parsed_url

CREATE TABLE tb_parsed_url (
id bigint NOT NULL AUTO_INCREMENT,
url varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
title varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
description varchar(45) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL,
created_at bigint DEFAULT NULL,
updated_at bigint DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE KEY id_UNIQUE (id),
UNIQUE KEY url_UNIQUE (url)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

API设计

基本约定:
1.获取数据用get,提交数据用post
2.返回的数据格式:{“code”: 0, “message”:”ok”, “data”:{} }, 成功的时候code为0,否则为非0

Account部分

1.创建账户 account/create
Method:POST
Params:
{“username”:”yourname”, “email”:”you@email.com”,”password”:”yourpwd”}
Response:
{
“code”: 0,
“data”: {
“activeCode”: “147849”,
“avatarUrl”: “”,
“bannerUrl”: “”,
“countFollowers”: “0”,
“countFollowings”: “0”,
“countLikes”: “0”,
“countPosts”: “0”,
“createdAt”: “1624266544”,
“description”: “”,
“displayName”: “”,
“dobDay”: “0”,
“dobMonth”: “0”,
“dobYear”: “0”,
“email”: “youremail@gmail.com”,
“iD”: “100000003”,
“isActived”: “0”,
“isVisibleDobDay”: “0”,
“isVisibleDobMonth”: “0”,
“isVisibleDobYear”: “0”,
“language”: “”,
“lastLogin”: “0”,
“location”: “”,
“password”: “123456”,
“phone”: “”,
“pinnedPostId”: “0”,
“suspended”: “0”,
“timeZone”: “”,
“updatedAt”: “1624266544”,
“username”: “myname”,
“verified”: “0”,
“website”: “”
},
“message”: “ok”
}

2.激活账户 account/activate (通过email里面的链接进行激活)
Method:POST
Params:
{“username”:”yourname”, “activate_code”:”toatciveyouraction”}
Response:
{
“code”: 0,
“data”: null,
“message”: “ok”
}

3.发送重置密码代码 account/send_reset_code
Method:POST
Params:
{“email”:”you@email.com”}
Response:
{
“code”: 0,
“data”: null,
“message”: “ok”
}
校验代码: account/verify_code
Method:POST
Params:
{“email”:”youremail@google.com”,”code”:”resetcode123″}
重置密码: account/reset_password
Method:POST
Params:
{“email”:”youremail@google.com”, “reset_code”:”restcode123″,”password”}
Response:
{
“code”: 0,
“data”: null,
“message”: “ok”
}

User 部分


1.用户登陆 user/login
Method:POST
Params:
{“name”:”yourname”,”password”:”yourpwd”}
Notes: name是username或者email
Response:
{
“code”: 0,
“data”: {
“token”: “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MjQ4NzA4MDAsImp0aSI6IjEwMDAwMDAwMyIsImlhdCI6MTYyNDI2NjAwMCwibmJmIjoxNjI0MjY2MDAwfQ.Hs2LTfG47Q1IDOhr9lY15usqyDPP1r7wKLk3l9nd4LQ”
},
“message”: “ok”
}

2.用户登出 user/logout(前端直接清理token)
Method:POST

3.修改语言 user/change_language
Method:POST
Params: {“language”:”en”}
Notes: 参数的值是options(目前只有en,zh),不能随意填写
Response:
{
“code”: 0,
“data”: {},
“message”: “ok”
}

4.修改密码 user/change_password
Method:POST
Params: {“password”:”newpasswd”,”old_password”:”oldpasswd”}
Notes: 密码有要求,最少8位,最少包含字母和数字
Response:
{
“code”: 0,
“data”: {},
“message”: “ok”
}
5.修改其它信息 user/save_info
Method:POST
Params:
{
“display_name”: “name1”,
“banner_url”: “”,
“avatar_url”: “”,
“location”: “bg”,
“website”: “http://www.mysite.com”,

“dob_year”: “2001”,
“dob_month”: “12”,
“dob_day”: “12”
}
Response:
{
“code”: 0,
“data”: {},
“message”: “ok”
}

6.查看用户页面(该页面有3个tab,所以一起有4个api)
6.1 user/profile
Method:GET
Params: {“username”:”yourname”}
Response:
{
“code”: 0,
“data”: {
“avatarUrl”: “”,
“bannelUrl”: “”,
“countFollowers”: “0”,
“countFollowings”: “0”,
“createdAt”: “1624266544”,
“description”: “”,
“displayName”: “name1”,
“dobDay”: “12”,
“dobMonth”: “12”,
“dobYear”: “2001”,
“email”: “youremail@gmail.com”,
“id”: “100000003”,
“isVisibleDobDay”: “0”,
“isVisibleDobMonth”: “0”,
“isVisibleDobYear”: “0”
},
“message”: “ok”
}

6.2 user/posts
Params: {“username”:”yourname”, “cursor”:101}
Notes: cursor初始不传,每次返回的结果中会带上新的cursor,下次请求的时候用这个值即可(后续所有的cursor都是一样的逻辑)
如果没有新的内容可加载,cursor会返回 -1

6.3 user/replies
Params: {“username”:”yourname”, “cursor”:101}

6.4 user/likes
Params: {“username”:”yourname”, “cursor”:101}

7.查看用户关注的人 user/following
Method:GET
Params: {“username”:”yourname”, “cursor”:101}
Response:
{
“code”: 0,
“data”: {
“cursor”: “0”,
“users”: [
{
“avatarUrl”: “”,
“description”: “”,
“displayName”: “”,
“id”: “100000001”
},
{
“avatarUrl”: “”,
“description”: “”,
“displayName”: “”,
“id”: “100000002”
},
{
“avatarUrl”: “”,
“description”: “”,
“displayName”: “name1”,
“id”: “100000003”
}
]
},
“message”: “ok”
}

8.查看关注该用户的人 user/followers
Method:GET
Params: {“username”:”yourname”,”cursor”:101}
用户部分2(在他人页面操作,登陆后可操作)
Response:
{
“code”: 0,
“data”: {
“cursor”: “0”,
“users”: [
{
“avatarUrl”: “”,
“description”: “”,
“displayName”: “”,
“id”: “100000001”
},
{
“avatarUrl”: “”,

“description”: “”,
“displayName”: “”,
“id”: “100000002”
},
{
“avatarUrl”: “”,
“description”: “”,
“displayName”: “name1”,
“id”: “100000003”
}
]
},
“message”: “ok”
}

——– 以下API需要用户登陆认证 ———

9.查看自己block的用户 user/blocked
Method:GET
Params: {“cursor”:101}

10.查看自己mute的用户 user/muted
Method:GET
Params: {“cursor”:101}

11.follow某个用户 user/follow
Method:POST
Params: {“target_username”:”tusername”, “flag”:1}
Notes: flag1表示follow, 0表示unfollow
database operation:在tb_user_relationship增加或者修改记录,具体参看表的定义
Response:
{
“code”: 0,
“data”: null,
“message”: “ok”
}

12.block某个用户 user/block
Method:POST
Params: {“target_username”:”tusername”, “flag”:1}
Notes: flag 1表示block, 0表示unblock
database operation:在tb_user_relationship增加或者修改记录,具体参看表的定义
Response:
{
“code”: 0,
“data”: null,
“message”: “ok”
}

13.mute某个用户 user/mute
Method:POST
Params: {“target_username”:”tusername”, “flag”:1}
Notes: flag1表示mute, 0表示unmute
database operation:在tb_user_relationship增加或者修改记录,具体参看表的定义
Response:
{
“code”: 0,
“data”: null,
“message”: “ok”
}

14.report某个用户 user/report
Method:POST
Params: {“target_username”:”tusername”, “report_reason”:1}
database operation: 在tb_reported_user表里增加记录
Response:
{
“code”: 0,
“data”: null,
“message”: “ok”
}


15.获取上传图片签名地址:upload/sign_image
Method: GET
Params: {“ext”:”jpg”} jpg|png|jpeg|gif
Response:
{
“code”: 0,
“data”: {
“url”: “https://twitter6-dev-bucket.s3.ap-northeast-1.amazonaws.com/images/20210622/cca1yk47jcsg92508.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIATWAJJDEPJQWRB524%2F20210622%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20210622T095116Z&X-Amz-Expires=1800&X-Amz-SignedHeaders=host&X-Amz-Signature=fb349171cd2d3cb5e49b711d9bf1950bba154081ad55534a3fcada33fcd0700a”
},
“message”: “ok”
}

16.获取上传视频签名地址:upload/sign_video
Method: GET
Params: {“ext”:”mp4″}
Response:
{
“code”: 0,
“data”: {
“url”: “https://twitter6-dev-bucket.s3.ap-northeast-1.amazonaws.com/videos/20210622/cca1yk47jcsg92508.mp4?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIATWAJJDEPJQWRB524%2F20210622%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20210622T095116Z&X-Amz-Expires=1800&X-Amz-SignedHeaders=host&X-Amz-Signature=fb349171cd2d3cb5e49b711d9bf1950bba154081ad55534a3fcada33fcd0700a”
},
“message”: “ok”
}


Post部分


1.发布推特 post/create
Method:POST
Params: {“content_text”:”text”, “media”: “image or video”}
Response:
{
“code”: 0,
“data”: {id: “a”},
“message”: “ok”
}

2.回复推特 post/reply
Method:POST
Params: {“content_text”:”text”, “media”: “image or video”,”original_post_id”:11122,”usename”:”namename”}
Response:
{
“code”: 0,
“data”: {id: “a”},
“message”: “ok”
}

3.转发推特
3.1 post/repost
Method:POST
Params: {“original_post_id”:11122, “usename”:”namename”,”content_text”:”repost content”}
Notes: 转推的时候也可以补充内容,原贴的repost数量要+1
Response:
{
“code”: 0,
“data”: {id: “a”},
“message”: “ok”
}
3.2 post/undo_repost 取消转推
Method:POST
Params: {“post_id”:11122}
Notes:这个记录可以直接删除了,另外原贴的repost数量要-1

4.点赞推特/取消点赞 post/like
Method:POST
Params: {“islike”:”1″,”post_id”:11122, “usename”:”namename”}
Notes: islike 1表示点赞,0表示取消点赞
Response:
{
“code”: 0,
“data”: null,
“message”: “ok”
}

5.举报推特 post/report
Method:POST
Params: {“post_id”:123123, “usename”:”namename”,”report_reason”:1}
database operation: 在tb_reported_post表里增加记录
Response:
{
“code”: 0,
“data”: null,
“message”: “ok”
}

6.推特详情
6.1 post/detail
Method: GET
Params: {“post_id”:123456, “usename”:”namename”}
Response:
{
“code”: 0,
“data”: {
“contentText”: “us is sb”,
“countComments”: “2”,
“countLikes”: “1”,
“countRepots”: “1”,
“id”: “b”,
“imageUrl”: “”,
“originalPostId”: “0”,
“userId”: “100000003”,
“videoUrl”: “”
},
“message”: “ok”
}
6.2 post/replies
Method: GET
Params: {“post_id”:123456, “usename”:”namename”,”cursor”:101}
Response:

7.删除推特 post/delete
Method: POST
Params: {“post_id”:123456}
database operation:把tb_post对应的记录is_deleted设置为1,并设置deleted_at
Response:
{
“code”: 0,
“data”: null,
“message”: “ok”
}

8.内容置顶 post/pin
Method: POST
Params: {“post_id”:123456, “ispin”:1}
Notes: ispin 1表示置顶,0表示取消置顶,默认是1
database operation:设置tb_user对应的记录pinned_post_id
Response:
{
“code”: 0,
“data”: {},
“message”: “ok”
}

数据表和API设计的细节

  • 分库分表策略:设计了tb_user_relationship和tb_user_relationship_reversed两个表,都按照user_id进行分库分表,这样不管是获取follower list还是following list,都是一次查询即可查到。
  • 数据归档策略:由于Twitter访问最多的是最新几天的post数据,可以对post按照一定的时间(如:一个月或者一周)进行归档,这样可以保证最新的post表数据不会过大。
  • 对于查询的优化:考虑数据的更新频率,把不会更新的数据放在一个表(如:tb_post),充分利用缓存;把经常更新的数据放在另外一个表(如:tb_post_extended),经常更新的字段是定长字段,mysql的查询性能也会非常高。
  • 体验上的优化:API设计的时候,把获取帖子内容和帖子统计数据(评论数、点赞数)也分开了。前端先获取帖子的内容,并立即显示给用户;然后再异步请求统计数据。这样还可以做到定时更新列表的统计数据,特别是大V可以不用刷新页面,也能看到点赞数和评论数在增加,获得良好的用户体验感。
  • Timeline处理细节:1.在cache中存放timeline的post id list,每次直接从cache中获取;2.用户如果是登陆后进入首页,登陆后异步生成timeline(生成时间小于3s),然后进入首页后再请求timeline,就可以直接从缓存获取到;3.用户如果已经是登陆状态,打开首页,前端从浏览器缓存中获取老的timeline数据先进行显示,同时异步请求timeline进行刷新。4.对于重要的用户,发了推之后,利用kafka的异步机制,主动刷新在线的关注者的timeline,以方便重要的post可以第一时间发出。

Leave a Reply

Your email address will not be published.