传统方式下,设备之间的数据同步,需要开发者完成消息处理逻辑,包括:建立通信链接、消息收发处理、错误重试、数据冲突解决等操作,工作量非常大。而且设备越多,调试复杂度也将同步增加。
其实设备之间的状态、消息发送进度、发送的数据等都是“变量”。如果这些变量支持“全局”访问,那么开发者跨设备访问这些变量就能像操作本地变量一样,从而能够自动高效、便捷地实现数据多端同步。
分布式数据对象即实现了对“变量”的“全局”访问。向应用开发者提供内存对象的创建、查询、删除、修改、订阅等基本数据对象的管理能力,同时具备分布式能力。为开发者在分布式应用场景下提供简单易用的JS接口,轻松实现多设备间同应用的数据协同,同时设备间可以监听对象的状态和数据变更。满足超级终端场景下,相同应用多设备间的数据对象协同需求。与传统方式相比,分布式数据对象大大减少了开发者的工作量。
分布式内存数据库
分布式内存数据库将数据缓存在内存中,以便应用获得更快的数据存取速度,不会将数据进行持久化。若数据库关闭,则数据不会保留。
分布式数据对象
分布式数据对象是一个JS对象型的封装。每一个分布式数据对象实例会创建一个内存数据库中的数据表,每个应用程序创建的内存数据库相互隔离,对分布式数据对象的“读取”或“赋值”会自动映射到对应数据库的get/put操作。
分布式数据对象的生命周期包括以下状态:
图1 分布式数据对象运作机制
分布式数据对象生长在分布式内存数据库之上,在分布式内存数据库上进行了JS对象型的封装,能像操作本地变量一样操作分布式数据对象,数据的跨设备同步由系统自动完成。
为每个分布式数据对象实例创建一个内存数据库,通过SessionId标识,每个应用程序创建的内存数据库相互隔离。
在分布式数据对象实例化的时候,(递归)遍历对象所有属性,使用“Object.defineProperty”定义所有属性的set和get方法,set和get中分别对应数据库一条记录的put和get操作,Key对应属性名,Value对应属性值。
在开发者对分布式数据对象进行“读取”或者“赋值”的时候,都会自动调用到set和get方法,映射到对应数据库的操作。
表1 分布式数据对象和分布式数据库的对应关系
分布式对象实例 | 对象实例 | 属性名称 | 属性值 |
---|---|---|---|
分布式内存数据库 | 一个数据库(sessionID标识) | 一条数据库记录的key | 一条数据库记录的value |
分布式数据对象,最重要的功能就是对象之间的数据同步。可信组网内的设备可以在本地创建分布式数据对象,并设置sessionID。不同设备上的分布式数据对象,通过设置相同的sessionID,建立对象之间的同步关系。
如下图所示,设备A和设备B上的“分布式数据对象1”,其sessionID均为session1,这两个对象建立了session1的同步关系。
图2 对象的同步关系
一个同步关系中,一个设备只能有一个对象加入。比如上图中,设备A的“分布式数据对象1”已经加入了session1的同步关系,所以设备A的“分布式数据对象2”就加入失败了。
建立同步关系后,每个Session有一份共享对象数据。加入了同一个Session的对象,支持以下操作:
(1)读取/修改Session中的数据。
(2)监听数据变更,感知其他设备对共享对象数据的修改。
(3)监听状态变更,感知其他设备的加入和退出。
关于分布式数据对象的数据同步,值得注意的是,同步的最小单位是“属性”。比如,下图中对象1包含三个属性:name、age和parents。当其中一个属性变更时,则数据同步时只需同步此变更的属性。
图3 数据同步视图
分布式对象主要运行在应用程序的进程空间。当调用分布式对象持久化接口时,通过分布式数据库对对象进行持久化和同步,进程退出后数据也不会丢失。
该场景是分布式对象的扩展场景,主要用于以下情况:
在设备上创建持久化对象后APP退出,重新打开APP,创建持久化对象,加入同一个Session,数据可以恢复到APP退出前的数据。
在设备A上创建持久化对象并同步后持久化到设备B后,A设备的APP退出,设备B打开APP,创建持久化对象,加入同一个Session,数据可以恢复到A设备退出前的数据。
在分布式对象中,可以使用资产类型来描述本地实体资产文件,分布式对象跨设备同步时,该文件会和数据一起同步到其他设备上。当前只支持资产类型,不支持资产类型数组。如需同步多个资产,可将每个资产作为分布式对象的一个根属性实现。
当分布式对象中包含的资产和关系型数据库中包含的资产指向同一个实体资产文件,即两个资产的Uri相同时,就会存在冲突,我们把这种资产称为融合资产。若想解决融合资产的冲突,需要先进行资产的绑定。当应用退出session后,绑定关系随之消失。
不同设备间只有相同bundleName的应用才能直接同步。
分布式数据对象的数据同步发生在同一个应用程序下,且同sessionID之间。
不建议创建过多的分布式数据对象,每个分布式数据对象将占用100-150KB内存。
每个分布式数据对象大小不超过500KB。
设备A修改1KB数据,设备B收到变更通知,50ms内完成。
单个应用程序最多只能创建16个分布式数据对象实例。
考虑到性能和用户体验,最多不超过3个设备进行数据协同。
如对复杂类型的数据进行修改,仅支持修改根属性,暂不支持下级属性修改。资产同步机制中,资产类型的数据支持下一级属性修改。
支持JS接口间的互通,与其他语言不互通。
以下是分布式对象跨设备数据同步功能的相关接口,大部分为异步接口。异步接口均有callback和Promise两种返回形式,下表均以callback形式为例,更多接口及使用方式请见分布式数据对象。
接口名称 | 描述 |
---|---|
create(context: Context, source: object): DataObject | 创建并得到一个分布式数据对象实例。 |
genSessionId(): string | 创建一个sessionId,可作为分布式数据对象的sessionId。 |
setSessionId(sessionId: string, callback: AsyncCallback<void>): void | 设置同步的sessionId,当可信组网中有多个设备时,多个设备间的对象如果设置为同一个sessionId,就能自动同步。 |
setSessionId(callback: AsyncCallback<void>): void | 退出所有已加入的session。 |
on(type: ‘change’, callback: (sessionId: string, fields: Array<string>) => void): void | 监听分布式数据对象的数据变更。 |
off(type: ‘change’, callback?: (sessionId: string, fields: Array<string>) => void): void | 取消监听分布式数据对象的数据变更。 |
on(type: ‘status’, callback: (sessionId: string, networkId: string, status: ‘online’ | ‘offline’ ) => void): void | 监听分布式数据对象的上下线。 |
off(type: ‘status’, callback?: (sessionId: string, networkId: string, status: ‘online’ |‘offline’ ) => void): void | 取消监听分布式数据对象的上下线。 |
save(deviceId: string, callback: AsyncCallback<SaveSuccessResponse>): void | 保存分布式数据对象。 |
revokeSave(callback: AsyncCallback<RevokeSaveSuccessResponse>): void | 撤回保存的分布式数据对象。 |
bindAssetStore(assetKey: string, bindInfo: BindInfo, callback: AsyncCallback<void>): void | 绑定融合资产。 |
以一次分布式数据对象同步为例,说明开发步骤。