编者按:这篇文章的原文是写给开发者们的,对于普通用户而言可能没有那么大的参考价值。作者倡导的方案类似于“为 Obsidian 这样的本地优先软件提供 Dropbox 这样的通用云同步服务,并可以自动解决冲突”,作者一共提供了 3 种方案,其中 1 和 2 是个人用户可以实现的,而方法 3 则需要从开发层面进行功能设计了。你可以从本文中窥见 Local First 的软件为何总在同步问题上出现一些困难。
作者参加了 Local-First Conference,听了 Martin Kleppmann 的演讲。他提到了一些关于本地优先软件的问题,特别是数据同步的问题。
首先,什么是本地优先?
简单来说,本地优先软件就是:
- 数据优先存储在本地;
- 偶尔与互联网同步;
- 如果完全离线,它就是本地软件;
- 如果完全依赖互联网,它就是普通云软件。
本地优先软件的概念是优先将数据存储在本地,同时偶尔与互联网同步。这种软件让用户掌握自己的数据,但同步仍然需要在线组件,比如在个人设备之间同步数据。
然而,如果公司倒闭,同步服务将停止,这对用户来说是一个大问题。
利用 Dropbox 同步的几种方案
为了解决这个问题,Martin Kleppmann 提出了一个简单有效的解决方案:利用 Dropbox 或类似的云同步服务。Dropbox 是一种广泛使用、易于访问的服务,具有多种实现方式,如果一家公司倒闭,用户可以切换到其他服务。
虽然文件同步协议相对简单,不能处理复杂的同步事件或冲突解决,但通过使用 CRDT(冲突自由的复制数据类型),可以有效解决冲突。
在 Martin 的方案中,Dropbox 进行同步有三种主要实现方式。
第一种是超级简单版:将状态保存到一个文件并让 Dropbox 同步。如果在两台机器上更改状态,会出现冲突文件,通常情况下这是个问题,但使用 CRDT 可以解决冲突。CRDT 是一种可以合并数据类型,即使不完美,但总能合并数据,避免冲突。
第二种方法是每个客户端一个文件,每个客户端有自己的文件,避免了冲突,只需在本地编辑,并在其他客户端文件变化时合并数据。因为每个文件只在一个设备上编辑,Dropbox 不会报告冲突,数据冲突可以通过 CRDT 解决。
第三种方法更适合开发者:基于操作的同步。这种方式下,每个客户端记录自己的操作日志,而不是整个状态文件。想象一下,每个设备只是记录它做了哪些改变,而不是记录整个文件的内容。这些操作被写入一个单独的文件中,Dropbox 只需同步这些操作日志文件。这减少了同步负担,避免了大文件的处理。如果操作日志变得过长,可以将操作分成小块,这样 Dropbox 同步时只需处理较小的数据块,客户端也更容易跟上变化。
即使在最简单的形式下,Dropbox 作为公共同步层也能工作。然而,不同的云服务提供商处理冲突文件的方式不同,有些甚至不处理冲突,这需要依赖状态型 CRDT 来保证数据一致性。基于操作的同步方式虽然更加复杂,但通过分块操作,可以显著减少同步负担,提高效率。
尽管 Dropbox 及其他云同步服务相对简单,但足以满足基本的同步需求。虽然不如定制解决方案那么实时,但对于一般用户来说,这已经足够好,尤其是考虑到成本和长久性。
这个解决方案的亮点在于其简单有效,并且适用于大多数用户场景,特别是类似 Apple Photos 的应用:虽然不同步实时数据,但能确保所有照片最终会在各设备上出现。
在最后,Martin Kleppmann 强调,本地优先软件让用户真正掌控数据,使用简单的云同步服务作为基础设施,不仅成本低廉,还能长期使用。这个方法不仅实用,还能为用户提供一种无缝的使用体验。想象一下,如果像 Obsidian Sync 这样的应用只需将文件放入一个文件夹,就能实现免费且永久的无冲突同步,这无疑是一个极具吸引力的解决方案。
题图来源 / 文章原文“本地优先软件的目标是让用户掌控数据,但同步仍然需要服务器。如果公司倒闭,同步就会停止,这也是一个难题。” — Martin Kleppmann