云表格的技术(二)

来源:互联网 发布:域名查所在地 编辑:程序博客网 时间:2024/06/09 10:47

WPS云是一款云端的产品,也就是说,在客户端给用户呈现的如此多的功能,都有赖于云端的处理能力和储存能力。最简单的来讲,用户的文件,必然是要储存在云端的。那么问题来了,用户的文件,是存储在后端的分布式文件系统里呢?还是后端有自己的文件储存格式呢?这个问题其实见仁见智,君不见,诸如百度云这样的产品,用户上传的文件,必定是以普通文件的形式存储的。

但是,显然WPS云不是一个简单的云盘,因为WPS云是提供在线协同编辑的。根据前文的介绍,在线协同编辑的主流技术是基于Operational Transformation的。作为一个经典的分布式算法,Operational Transformation是非常仰赖于后端。来自多个客户端的操作,会汇总到云,并且被串行化,再经由后端的Operational Transformation处理,将操作应用到后端的数据中,完成用户操作在云端的持久化。

云必然是分布式的。但是,Operational Transformation算法要求,对于同一份EXECL文件的操作,是需要串行化,一一处理的。正因为如此,我们可以想象,在多个客户端,连接到云端,编辑同一份文件时,不能任由多个AP服务这些客户端,多个AP之间的并行会破坏Operational Transformation,从而导致协同编辑功能的紊乱。

显然,消息中间件是一个很好的解决方案。各个AP可以作为生产者,将来自客户端的操作,写入消息中间件,而各个AP,也作为消费者,消费来自中间件的操作。为了达到对同一个文件,串行化所有的操作的目标,需要满足一个条件,就是对于同一个文件的操作,只有一个消费者消费。这其实不是一个简单的问题,因为,文件不是静态的,而是任何客户端,可以随时打开任何一个文件,并且,任何客户端,可以随时离开这个文件。另一方面,多AP的云端,需要能够提供较强的容错性,也就是说,某个AP的宕机,应该是不影响整个云的可用性的。

公司现有的方案是基于kafka的广播,将用户的操作广播出去,而AP之间通过zookeeper协调,到达AP后,AP根据master election的结果,选择消费该操作或者丢弃该操作。如此,即可保证操作的串行处理。

但是,这种结构一方面浪费了带宽(广播的消息大多数被丢弃了),另外,这种结构在AP宕机的情况下,可能重复消费或者丢失信息。根源在于,被广播信息的消费,各个AP是异步的,我们无法保证消息的广播到达各个AP是同时的。

Kafka可以解决这个问题。利用Consumer Group,可以保证对于同一个文件的操作,只有一个消费者消费。

应对宕机,kafka会触发re-balance,重新在Consumer Group中选择partition owner.

另一方面,对单个AP而言,可能有很多客户端连接到该AP上,并且编辑着多份不同的文件。为了提高Throughput,显然不能粗暴的将来自各种文件的所有的操作都串行化一一处理,最恰当的做法应该是,多线程处理,一个线程处理一个文件的所有操作。

在实际的应用中,我们还需要考虑kafka topic的数目问题。过多的topic数目,会给zookeeper带来过大的压力,所以,后端的设计需要考虑创建多个topic还是对topic划分多个partition.

如果topic数目不会太多,那么可以选择创建topic对应每个文档。将以上两点结合起来, 可以形成这样的结构,即每个AP会动态的创建Consumer instance, 每个consumer instance对应一个文件的所有操作的处理。如果该AP上的客户端打开多个不同文件,那么自然会有多个Consumer instance.

如果不想铺张过多的topic,可以仅创建一个topic,并且,根据不同的文档,划分不同的partition.

协同编辑是需要广播机制的。假设多个终端,连接着多个AP,但是打开的是同一份文件。那么,所有的编辑操作,都会被集中到某个AP进行Operational Transformation。但是,这个OT后的结果,是需要广播到所有AP去的。

Kafka同样可以解决广播的问题。只需要将各个AP上的consumer instance设定不同的group id,就可以实现广播。

综上所述,对于某个AP而言,处理每一个文件,都会有两个Consumer instance,一个是用来接收待OT的操作的,一个是用来接收已处理操作的。接收待处理操作的consumer instance是隶属于某个consumer group的(保证对于同一个文件的操作,只有一个消费者消费),而接收已处理操作的Consumer instance是自称一个group(为了达到广播效果)