#星光计划2.0# OpenHarmony 源码解析之分布式数据库 原创 精华

深开鸿
发布于 2021-12-10 09:35
浏览
3收藏

作者:卞绍雷

【本文正在参与51CTO HarmonyOS技术社区创作者激励计划-星光计划2.0】

1 简介

本文基于OpenHarmonyOS 3.0 LTS 来讲解分布式数据服务(Distributed Data Service,DDS) 提供不同设备间数据库数据分布式的能力。从架构上来说,分布式数据服务是开源鸿蒙底层服务的基础服务,与分布式任务调度同层。然而在使用分布式任务调度功能时,基本上都需要进一步要求数据交互功能,完成完整的分布式功能,因此在学习分布式任务调度的同时,不可避免的需要学习分布式数据服务相关的功能与底层服务。

本文在写作时,调试JS的DEMO时发现了更底层的方舟JS运行层的BUG,提交了ISSUE,并试图提交了PR。如果大家在运行DEMO时发现问题,请先尝试合并上述PR并重新全部编译系统并刷机再试。

1.1 分布式相关

《OpenHarmony 源码解析之分布式任务调度》

《OpenHarmony 源码解析之分布式数据库》

1.2 OpenHarmony架构图

#星光计划2.0# OpenHarmony 源码解析之分布式数据库-鸿蒙开发者社区

2 基础知识

2.1 概述

先看开源鸿蒙官方文档对分布式数据服务的描述:

分布式数据服务(Distributed Data Service,DDS) 提供不同设备间数据库数据分布式的能力。通过结合帐号、应用和数据库三元组,分布式数据服务对数据进行隔离。在通过可信认证的设备间,分布式数据服务支持数据相互同步,为用户提供在多种终端设备上一致的数据访问体验。

目前开源鸿蒙还没有整合账号功能,因此测试的时候账号可以自由选择,填写一致即可。应用和数据库则必须保持一致,才能进行完整的分布式数据数据隔离,提供数据在多种终端设备上一致的访问体验。

2.2 源码结构

├── BUILD.gn
├── figures
│   ├── en-us_image_0000001162536643.png
│   └── zh-cn_image_0000001162536643.png
├── frameworks
│   ├── innerkitsimpl
│   │   └── distributeddatafwk # 框架层实现
│   │       ├── include
│   │       ├── src
│   │       └── test
│   └── jskitsimpl
│       └── distributeddata    # JS接口实现
│           ├── include
│           └── src
├── interfaces
│   ├── innerkits                # 内部接口,主要是头文件
│   │   ├── app_distributeddata 
│   │   │   ├── BUILD.gn
│   │   │   └── include
│   │   └── distributeddata
│   │       ├── BUILD.gn
│   │       └── include
│   └── jskits                   # JS接口,BUILD用
│       └── distributeddata
│           └── BUILD.gn
├── LICENSE
├── OAT.xml
├── ohos.build
├── README.md
├── README_zh.md
├── services
│   └── distributeddataservice
│       ├── adapter              # 适配实现
│       │   ├── account          # 账号适配
│       │   ├── autils           # 实用库,包括任务、线程、目录等
│       │   ├── broadcaster      # 发送广播
│       │   ├── BUILD.gn
│       │   ├── communicator     # 通讯适配
│       │   ├── dfx              # 日志、统计、错误等相关处理
│       │   ├── include
│       │   ├── LICENSE
│       │   ├── permission        # 权限
│       │   ├── security          # 安全相关
│       │   ├── test
│       │   └── utils
│       ├── app                   # 用户程序实现
│       ├── libs
│       │   └── distributeddb
│       │       ├── BUILD.gn
│       │       ├── common
│       │       ├── communicator  # 设备间通讯
│       │       ├── include
│       │       ├── interfaces
│       │       ├── storage   # 存储实现,包括单版本KV、多版本KV、SQLITE3等
│       │       ├── syncer    # 同步
│       │       └── test
│       ├── sa_profile
│       └── test
└── test

2.3 分布式数据服务架构设计图

#星光计划2.0# OpenHarmony 源码解析之分布式数据库-鸿蒙开发者社区

2.4 数据同步

官方文档是这么描述的:

通过调用分布式数据服务接口实现分布式数据库创建、访问、订阅功能,服务接口通过操作服务组件提供的能力,将数据存储至存储组件,存储组件调用同步组件实现将数据同步,同步组件使用通信适配层将数据同步至远端设备,远端设备通过同步组件接收数据,并更新至本端存储组件。

2.5 分布式数据

最终一致性:是指某一设备成功增、删、改数据后,组网内设备可能读取不到本次更新数据,但在某个时间窗口之后组网内设备的数据能够达到一致状态。
强一致性对分布式数据的管理要求非常高,在服务器的分布式场景可能会遇到。因为移动终端设备的不常在线、以及无中心的特性,分布式数据服务不支持强一致,只支持最终一致性。

目前分布式数据的数据模型仅支持KV数据模型,不支持外键、触发器等关系型数据库中的技术点。虽然开源鸿蒙底层支持基于SQLITE3的关系型数据库,但是并不在分布式数据层面支持。

当前KV数据模型的限制:

  • 设备协同数据库,Key最大支持896Byte,Value最大支持4MB。
  • 单版本数据库,Key最大支持1KB,Value最大支持4MB。
  • 每个程序最多支持同时打开16个DB。
  • 当前流控机制针对KvStore的接口1秒最大访问1000次,1分钟最大访问10000次。
  • KvManager的接口1秒最大访问50次,1分钟最大访问500次。

2.6 使用前提

从开源鸿蒙的分布式数据源代码中,可以看到目前只有手机(phone)、穿戴式设备(wearable)、车载系统(ivi)会搭载,其它更轻量的设备可能暂时不支持,或者需要剪裁定制支持。

目前在两台标准设备的开源系统鸿蒙上,是默认集成了该功能,可以直接使用的。

开源鸿蒙的分布式数据如果只在单机使用,那么无需前提条件。如果需要其分布式功能,那么就需要设备之间完成组网;而组网的前提条件是完成设备认证。具体步骤,请参考OpenHarmony 源码解析之分布式任务调度

3 编程接口

3.1 导入模块

import distributedData from '@ohos.data.distributedData';

下面各个接口大多有callback和promise两种异步方式,本文均以promise方式为例,callback方式大同小异,请自行查阅文档。

3.2 创建管理器

distributedData.createKVManager
createKVManager(config: KVManagerConfig, callback: AsyncCallback<KVManager>): void
createKVManager(config: KVManagerConfig): Promise<KVManager>

创建一个KVManager对象实例,用于管理数据库对象,并通过Promise方式返回,此方法为异步方法。

示例:

let kvManager;
try {
    const kvManagerConfig = {
        bundleName : 'com.example.datamanagertest',
        userInfo : {
            userId : '0',
            userType : 0
        }
    }
    distributedData.createKVManager(kvManagerConfig).then((manager) => {
        console.log("createKVManager success");
        kvManager = manager;
    }).catch((err) => {
        console.log("createKVManager err: "  + JSON.stringify(err));
    });
} catch (e) {
    console.log("An unexpected error occurred. Error:" + e);
}

3.3 获取存储实例

kvManager.getKVStore
getKVStore<T extends KVStore>(storeId: string, options: Options): Promise<T>

通过指定Options和storeId,创建并获取KVStore数据库,并通过Promise方式返回,此方法为异步方法。

示例:

let kvStore;
try {
    const options = {
        createIfMissing : true,
        encrypt : false,
        backup : false,
        autoSync : true, //手动同步、自动同步
        kvStoreType : 1, //当前只能使用0(默认):表示多设备协同数据库,1:单版本数据库
        securityLevel : 3,
    };
    kvManager.getKVStore('storeId', options).then((store) => {
        console.log("getKVStore success");
        kvStore = store;
    }).catch((err) => {
        console.log("getKVStore err: "  + JSON.stringify(err));
    });
} catch (e) {
    console.log("An unexpected error occurred. Error:" + e);
}

3.4 存、取、删除、同步

kvStore.put(key: string, value: Uint8Array | string | number | boolean): Promise<void>
kvStore.get(key: string): Promise<Uint8Array | string | boolean | number>
kvStore.delete(key: string): Promise<void>
kvStore.sync(deviceIdList: string[], mode: SyncMode, allowedDelayMs?: number): void

3.5 注册事件通知回调

SubscribeType 描述订阅类型。

  • 0: SUBSCRIBE_TYPE_LOCAL 表示订阅本地数据变更。
  • 1: SUBSCRIBE_TYPE_REMOTE 表示订阅远端数据变更。
  • 2: SUBSCRIBE_TYPE_ALL 表示订阅远端和本地数据变更。
kvStore.on(event: 'dataChange', type: SubscribeType, observer: Callback<ChangeNotification>): void
kvStore.on(event: 'syncComplete', syncCallback: Callback<Array<[string, number]>>): void

4 小结

以上步骤,均已在DevEco Studio 3.0.0.600 x64中编写成功,并且在两台Hi3516D设备间成功运行,附代码(分布式任务调度和分布式数据测试.zip)。

再次提醒,分布式数据底层依赖ARK JS引擎,目前发现字符串处理有BUG,如运行出现问题,请先合并PR,然后重新编译全系统并刷机后再运行DEMO。

更多原创内容请关注:开鸿 HarmonyOS 学院

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2021-12-10 09:37:55修改
2
收藏 3
回复
举报
回复
    相关推荐