5 协同编辑系统设计
协同编辑系统设计
Scenario
协同合作
Service + Storage
实时系统 (real time application)
-
游戏
-
聊天 (wechat, whatsapp, messager)
-
股票交易 (robinhood, webull)
-
协同合作 (google docs)
实时系统的网络协议一般使用 websocket, 这样使得 server 可以向 client 推送消息. 而 http 协议只能 client 请求消息, server 应答, server 并不能主动给 client 发消息, 所以不适合用在实时系统上.
文件的元信息需要存放在 SQL 中, 文件的内容存放在文件系统中.
GFS 见详解见分布式文件系统笔记
创建文件 / 删除文件
读取文件
文件编辑
-
以"行"为一个粒度: 这一行改变了就 update 这一行, 如 Quip
-
以"词"为一个粒度: 这一个词改变了就 update 这一个词, 如 Google Docs
假设以行为粒度, 为方便多个用户以行为单位进行增删改查, 文件中的内容应该如何优化?
可以做一下 lintcode 中的 LRU Cache 这道题
文件在分布式文件系统中是以具体的文件形式存储的, Web Server 将文件从分布式文件系统中加载到本地, 然后将它写入内存. 文件的内容是存储在内存中的.
双向链表在任意位置插入或者删除的性能很好, 文件中的每一行的数据匹配链表中的一个节点. 内容的变化相当于链表节点的变化.
那文件内容如何转换为链表呢
type node struct {
Uid string // uuid, 唯一标识
Value string // 行数据
pre *node
nxt *node
}
唯一标识由前端生成, 在页面渲染时生成, 并记录下来.
Post Body
{
prelineUid
nextlineUid
lineUUID // 代表行的唯一标识, 前端生成(新增行时需要和lineNumber配合使用)
timestamp // 操作时间
optype // 操作类型: Create/Update/Delete
}
Scale
如何在网页中显示有多个人实时编辑的头像?
用户点击前端加载文件时都会传 token, 来进行身份验证. 这样我们就知道了哪个用户正在看这个文件, 同时也知道了 websocket 应该向哪个 IP 地址推送修改的信息. 在 Redis 中维护一个打开的用户列表 List, 然后从 DB 中查找头像即可, 然后将头像存在 Redis 中.
如何显示某一行正在被编辑
点击的时候, 前端就向后端发送这个行为, 后端存放在 Redis 中, 并且向所有用户推送. 如果有一个新人上线, 那么就将所有的信息推送过去.
之前的设计都是基于行锁定的, 有没有不需要锁定的
可以使用 OT 算法. 通过版本号来控制, 如果两个用户传递过来的版本号相同, 那么就进行一个类似于 git merge 操作, 然后在分别推送. 版本号在前端控制.