如何使用表格存储实现网盘文件的极速秒传

目前不少云备份、网盘等产品都提供了秒传的功能,一方面能够显著的提高了用户的使用体验,另外一方面由于避免了不必要的文件传输,又有效的降低了存储成本与带宽成本。

而实现文件的"秒传",只需要通过客户端从文件中获取一个特征值,比如常用的 MD5 值,然后在服务器上保存所有文件的特征值进行比较,如果有重复的,就无需再上传数据,只需要复制一份文件的存储路径即可。进一步考虑到文件的分享、保存以及后期的清理,我们将文件的特征值与当前引用计数存储在元数据 DB 中。

"秒传"机制看起来容易,但是在实现细节上也有不少问题需要处理。

面临的问题

上传的一致性问题

同一个文件同时由多个用户上传,如果没有锁保护,会出现先更新的值被后更新的值覆盖掉的情况,计数会低于实际引用的用户数量,导致文件可能被提前删除。

如何使用表格存储实现网盘文件的极速秒传

删除的一致性问题

在删除时, __使用异步删除能够明显的提高响应延时,并且,异步删除能够更方便的控制实际删除的时间__,在用户误删除或者删除之后的重新上传的情况(云相册的删除和重新同步)下都能够获得更好的用户体验。

但是使用异步删除后,在启动删除前有可能有用户重新上传该文件,由于文件名一致,则有可能会覆盖当前的文件,此时启动删除动作,会将该重新上传的文件删除掉,导致用户上传成功,但文件被删除。

尽管可以在删除时再次检查引用计数是否为0,仍然有可能有用户在检查之后和实际删除启动之间上传新的文件,依然避免不了上述的一致性问题。

如何使用表格存储实现网盘文件的极速秒传

并发及性能

将文件的MD5信息与引用计数作为元数据存放在DB中,由于文件的个数数以亿计,活跃用户数也数以千万计,为了提供真正的秒传秒复制,元数据的读写性能和并发能力都极为重要。

在百万级并发、亿级数据量的情况下,读写性能需要保证在毫秒级。

解决方案

文件上传

在文件上传时,先读取到当前的该文件的引用计数:

  • 若不存在该条记录,说明为第一次上传,文件上传成功后调用PutRow使用期望行不存在的条件 EXPECT_NOT_EXIST 将计数写入 1。避免有多个用户同时写入该文件,如果条件检查失败,即有其他用户先上传成功,转入 引用计数不为0 的处理逻辑。
  • 若大于 0,则对引用计数进行加1操作,返回给用户 __上传成功__,达到秒传或者秒拷贝的效果,流程见下图。
  • 若为 0,说明文件 将要被删除__,见下文 __文件删除 处理部分。
  • 若为 -1,说明文件 正在被删除__,为了保证一致性,等待文件删除完之后才能上传,详见下文 __文件删除 处理部分。

如何使用表格存储实现网盘文件的极速秒传

文件删除

在文件上传时,由于为了提高系统的响应时间或者应对误删除的再次上传(尤其是相册同步),一般采用异步删除,由于文件存储系统无锁机制,需要对跨系统的 文件存储系统 + 元数据DB 进行一致性保证,处理逻辑如下:

如何使用表格存储实现网盘文件的极速秒传

客户端逻辑

  1. 若该行不存在或者引用计数大于0,参考上文中 文件上传 处理逻辑。
  2. 若引用计数为 -1,进行等待直到引用计数Count为 0,由于 OSS Object 删除延时很低,该等待时间可控。
  3. 若引用计数为 0, __先进行引用计数加1__,成功后通知用户上传成功。
  4. 若引用计数大于 0, 参考上文中 文件上传 处理逻辑。

删除任务逻辑

  1. 当删除任务被激活时,先进行删除标志位检查,需要检查引用计数为 0,确保可以正常删除。
  2. 将引用计数置为 -1,此时禁止用户上传,如果条件检查失败(set Count to -1 if Count=0),说明此时有用户上传该文件,删除任务作废。
  3. 如果引用计数 Count 置为 -1 成功,进行文件删除,删除之后 Count 置为 0,允许用户新上传。此时也可以将该条元数据记录直接删除。
  4. 删除工作完成。

方案说明

  1. 上述是基于表格存储(原OTS)接口实现,不同的DB有类似的实现方式。
  2. 由于需要处理 文件删除时 的一致性问题,故单纯的自增自减不适用,需要使用条件更新,否者会将 Count 减到小于 0,破坏上述的一致性机制。 __需要保证引用计数Count由且只能由删除任务置为-1__。而 TableStore 支持带条件的自加或自减,例如 Count+=1 if condition,可以大大简化开发逻辑。

对存储元数据 DB 的要求

1.毫秒级的性能

为了保证整个链路的时延,元数据的读写都必须在单个毫秒。传统的关系型数据库在千万级以上规模的查询效率会显著下降。

TableStore的机制能够保证单行查询的延时可预期,只与查询的结果集大小相关,与基础数据量无关。高性能实例的单行随机查询在TB级数据量与PB级数据量均为单个毫秒。

2.高并发

互联网应用中,并发峰值会与活跃用户数有线性关系,千万级活跃用户数的应用需要保证 百万级 的并发以应对访问峰值。一般的 DB 会受到单机能力的上限。

TableStore为NoSQL分布式数据库服务,提供弹性资源,能够支持0到百万的访问TPS。

3.能够简化开发及运维工作

为了保证性能和提高并发能力,使用一般的 DB 需要搭建集群,在业务上也要进行分库分表的操作,这会大大增加开发和运维的难度。

上述方案中调用的单行写 PutRow、单行读 GetRow 及单行更新 UpdateRow都 简单易用。为提高效率,TableStore也提供批量读写 BatchWriteRow 及 BatchGetRow 接口。TableStore 服务端会根据数据量及访问情况对数据进行自动分裂,而MD5天然具有很好的离散型,能够充分打散到多台服务器上,从而提供最大 N * 单机服务能力 的访问并发,该过程对用户完全透明。

4.成本

TableStore会根据实际使用进行计费,不会产生资源闲置。以每天1000W新增文件为例,使用高性能实例日费用为60元左右,使用预留读写模式或者是容量型实例更可以控制到10元以内。 10亿 条单条记录 100B 的高性能数据存储日费用为 2.5元 左右,而容量型实例每天不到1元钱。

正因为高并发、低延时、弹性资源等特点,表格存储非常适合互联网信息的元数据存储,更多这方面的应用实践还希望能多多和大家一起交流!

上一篇:[LeetCode] Decode String 解码字符串


下一篇:使用HBase Client访问阿里云NoSQL数据库表格存储