HarmonyOS分布式数据服务的了解和使用
前言
已经很久没写HarmonyOS的内容了,今天我又回来更新了。。。。
HarmonyOS提供了我们在不同设备之间可以获取相同的数据,称之为分布式数据库,只要是信任的设备就都可以获取到保存在分布式数据库里面的数据。所以一般都是在不同设备之间要获取相同数据的场景下使用该数据库。
在使用HarmonyOS分布式数据服务之前,首先要了解一下分布式服务的一些概念以及API。
分布式数据服务(Distributed Data Service,DDS) 为应用程序提供不同设备间数据库数据分布式的能力。通过调用分布式数据接口,应用程序将数据保存到分布式数据库中。通过结合帐号、应用和数据库三元组,分布式数据服务对属于不同应用的数据进行隔离,保证不同应用之间的数据不能通过分布式数据服务互相访问。在通过可信认证的设备间,分布式数据服务支持应用数据相互同步,为用户提供在多种终端设备上最终一致的数据访问体验。
简单来说就是在使用分布式数据服务之后,保存在分布式服务里面的数据,在可信任的设备之间,这些数据是共享的。
可以通过以下图片来查看具体的操作流程,在设备A对数据库进行增删改,那么设备B会同步这些数据,反之也是一样的。
分布式数据库的版本
在HarmonyOS系统里面,分布式数据库又被分成了两个版本,可以理解为两个模式;分别是单版本分布式数据库和设备协同分布式数据库;两个数据库分别实现不同操作。
单版本分布式数据库
单版本是指数据在本地保存是以单个KV条目为单位的方式保存,对每个Key最多只保存一个条目项,当数据在本地被用户修改时,不管它是否已经被同步出去,均直接在这个条目上进行修改。同步也以此为基础,按照它在本地被写入或更改的顺序将当前最新一次修改逐条同步至远端设备。
简单来说单版本分布式数据库是通过键值对(Key、Value)的形式保存数据,只能有一个key不能重复,当本地key数据被修改的时候会被直接修改,然后将最新的数据再同步出去。
设备协同分布式数据库
设备协同分布式数据库建立在单版本分布式数据库之上,对应用程序存入的KV数据中的Key前面拼接了本设备的DeviceID标识符,这样能保证每个设备产生的数据严格隔离,底层按照设备的维度管理这些数据,设备协同分布式数据库支持以设备的维度查询分布式数据,但是不支持修改远端设备同步过来的数据。
简单来说就是在单版本分布式数据库的key前面拼接上本设备的设备id,保证每个设备的数据库能够区分,知道是哪个设备添加进去的数据;但是不能修改远端设备同步过来的数据,就是在A设备添加的键值对数据推送到B设备,B设备只能读取该数据,不能对该数据进行修改。
约束与限制
HarmonyOS的分布式数据库有着一定的约束和限制,在使用分布式数据库之前要了解这些约束和现房方便在后面的开发中使用。
- 应用程序如需使用分布式数据服务完整功能,需要申请ohos.permission.DISTRIBUTED_DATASYNC权限。
- 分布式数据服务的数据模型仅支持KV数据模型,不支持外键、触发器等关系型数据库中的功能。分布式数据服务支持的KV数据模型规格:
1. 设备协同数据库,针对每条记录,Key的长度≤896 Byte,Value的长度<4 MB。
2. 单版本数据库,针对每条记录,Key的长度≤1 KB,Value的度<4 MB。
3. 每个应用程序最多支持同时打开16个分布式数据库。 - 分布式数据库与本地数据库的使用场景不同,因此开发者应识别需要在设备间进行同步的数据,并将这些数据保存到分布式数据库中。简单来说就是在业务中将要保存到分布式数据库的数据和要保存到关系型数据库或者其他数据库的数据区分开来,保存到自己对应的数据库当中。
- 分布式数据服务当前不支持应用程序自定义冲突解决策略。在HarmonyOS内部有默认的冲突解决策略。冲突一般发生在多设备同时修改一个Key的数据时。
- 分布式数据服务针对每个应用程序当前的流控机制:KvStore的接口1秒最大访问1000次,1分钟最大访问10000次;KvManager的接口1秒最大访问50次,1分钟最大访问500次。
相关API接口
在使用分布式数据库之前还要了解官方给我们提供了哪些api接口,然后根据api接口进行开发。
首先是对应分布式数据库创建、打开、关闭和删除的接口
- isCreateIfMissing() 检查数据库不存在时是否创建。
- setCreateIfMissing(boolean isCreateIfMissing) 设置数据库不存在时是否创建。
- isEncrypt() 获取数据库是否加密。
- setEncrypt(boolean isEncrypt) 设置数据库是否加密。
- getStoreType() 获取分布式数据库的类型。
- setStoreType(KvStoreType storeType) 设置分布式数据库的类型。
- KvStoreType.DEVICE_COLLABORATION 设备协同分布式数据库类型。
- KvStoreType.SINGLE_VERSION 单版本分布式数据库类型
- getKvStore(Options options, String storeId) 根据Options配置创建和打开标识符为storeId的分布式数据库。
- closeKvStore(KvStore kvStore) 关闭分布式数据库。
- deleteKvStore(String storeId) 删除分布式数据库。
然后是对应分布式数据增删改查的接口
在对数据库执行增删改查。
-
插入和更新数据
- putBoolean(String key, boolean value) 插入和更新Boolea类型数据
- putInt(String key, int value) 插入和更新Int类型数据
- putFloat(String key, float value) 插入和更新Float类型数据
- putDouble(String key, double value) 插入和更新Double类型数据
- putString(String key, String value) 插入和更新String类型数据
- putByteArray(String key, byte[] value) 插入和更新ByteArray类型数据
- putBatch(List entries) 插入和更新Batch类型数据 -
删除数据
- delete(String key) 删除指定key数据
- deleteBatch(List keys) 删除指定keys数据 -
查询数据
- getInt(String key) 查询指定key数据
- getFloat(String key)
- getDouble(String key)
- getString(String key)
- getByteArray(String key)
- getEntries(String keyPrefix)
谓词查询的接口
对于Schema数据库谓词查询数据,使用Query构建查询条件。
- select() 查询条件
- reset()
- equalTo(String field, int value) 等于 field 字段名 value 值
- equalTo(String field, long value)
- equalTo(String field, double value)
- equalTo(String field, String value)
- equalTo(String field, boolean value)
- notEqualTo(String field, int value) 不等于 field 字段名 value 值
- notEqualTo(String field, long value)
- notEqualTo(String field, boolean value)
- notEqualTo(String field, String value)
- notEqualTo(String field, double value)
- greaterThan(String field, int value) 大于field 字段名 value 值
- greaterThan(String field, long value)
- greaterThan(String field, double value)
- greaterThan(String field, String value)
- lessThan(String field, int value) 小于field 字段名 value 值
- lessThan(String field, long value)
- lessThan(String field, double value)
- lessThan(String field, String value)
- greaterThanOrEqualTo(String field, int value) 大于等于 field 字段名 value 值
- greaterThanOrEqualTo(String field, long value)
- greaterThanOrEqualTo(String field, double value)
- greaterThanOrEqualTo(String field, String value)
- lessThanOrEqualTo(String field, int value) 小于等于 field 字段名 value 值
- lessThanOrEqualTo(String field, long value)
- lessThanOrEqualTo(String field, double value)
- lessThanOrEqualTo(String field, String value)
- isNull(String field) 不为空field 字段名
- orderByDesc(String field) 排序
- orderByAsc(String field)
- limit(int number, int offset)
- like(String field, String value)
- unlike(String field, String value)
- inInt(String field, List valueList)
- inLong(String field, List valueList)
- inDouble(String field, List valueList)
- inString(String field, List valueList)
- notInInt(String field, List valueList)
- notInLong(String field, List valueList)
- notInDouble(String field, List valueList)
- notInString(String field, List valueList)
- and()
- or()
订阅分布式数据变化
订阅数据库中数据的变化。
- subscribe(SubscribeType subscribeType, KvStoreObserver observer)
分布式数据同步
在手动模式下,触发数据库同步。
- sync(List deviceIdList, SyncMode mode)
分布式数据库的使用
在了解分布式数据库的版本、约束以及相关API接口之后就是对分布式数据库的使用实操了;虽然HarmonyOS将分布式数据库的版本区分成了单版本分布式数据库和设备协同分布式数据库两种,但是用法都是一样的,这里就以单版本分布式数据库来进行操作。
添加权限并初始化
在使用分布式数据库之前要先添加分布式数据同步权限,并且初始化。
首先在module下添加权限:
"reqPermissions": [{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
}]
然后在MainAbility中初始化:
public class MainAbility extends Ability {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
//初始化分布式数据同步权限
requestPermissionsFromUser(new String[]{
"ohos.permission.DISTRIBUTED_DATASYNC"},0);
}
}
初始化分布式数据库
初始化分布式数据库和初始化关系型数据库差不多,同样是三个步骤先获取KvManagerConfig,然后获取KvManager,最后再获取KvStore就拿到数据库了。
1.获取KvManagerConfig
直接在onStart方法里面进行获取,传入当前abilitySlice的上下文对象:
private KvManagerConfig kvManagerConfig;
kvManagerConfig = new KvManagerConfig(this);
2.获取KvManager数据库管理器
通过KvManagerFactory去获取数据库管理器,传入上面的数据库配置管理器:
private KvManager kvManager;
kvManager = KvManagerFactory.getInstance().createKvManager(kvManagerConfig);
3.获取KvStore分布式数据库
通过kvManager的getKvStore方法获取,需要传入Options和一个String类型的数据库标识:
private String dbStoreId = "testStoreDemo";
private KvStore kvStore;
Options options = new Options();
kvStore = kvManager.getKvStore(options, dbStoreId);
以上操作都在onStart方法中完成。
Options 参数解析,这里的Options是在ohos.data.distributed.common这个包下面的,里面包含的方法就是上面api上提到的对应分布式数据库创建、打开、关闭和删除的接口:
public class Options {
public Options() {
throw new RuntimeException("Stub!");
}
//检查数据库不存在时是否创建。 默认是false
public boolean isCreateIfMissing() {
throw new RuntimeException("Stub!");
}
//setCreateIfMissing(boolean isCreateIfMissing) 默认是true
public Options setCreateIfMissing(boolean isCreateIfMissing) {
throw new RuntimeException("Stub!");
}
//isEncrypt() 获取数据库是否加密。
public boolean isEncrypt() {
throw new RuntimeException("Stub!");
}
//设置数据库是否加密。
public Options setEncrypt(boolean isEncrypt) {
throw new RuntimeException("Stub!");
}
public boolean isBackup() {
throw new RuntimeException("Stub!");
}
public Options setBackup(boolean isBackup) {
throw new RuntimeException("Stub!");
}
public boolean isAutoSync() {
throw new RuntimeException("Stub!");
}
//是否设置自动同步 true
public Options setAutoSync(boolean isAutoSync) {
throw new RuntimeException("Stub!");
}
//数据库类型 默认是设备协同分布式数据库
public KvStoreType getKvStoreType() {
throw new RuntimeException("Stub!");
}
public Options setKvStoreType(KvStoreType kvStoreType) {
throw new RuntimeException("Stub!");
}
public Schema getSchema() {
throw new RuntimeException("Stub!");
}
public Options setSchema(Schema schema) {
throw new RuntimeException("Stub!");
}
public SecurityLevel getSecurityLevel() {
throw new RuntimeException("Stub!");
}
public Options setSecurityLevel(SecurityLevel securityLevel) {
throw new RuntimeException("Stub!");
}
}
这里有几个参数需要注意:
- isCreateIfMissing 没有数据库是否创建,默认是false,所以要设置成true
- getKvStoreType 数据库类型,默认是设备协同分布式数据库
可以根据自己的需求配置Options。
通过以上步骤就可以将单版本分布式数据库创建并初始化成功了。
分布式数据库的增删改查
对分布式数据库进行增删改查。
前面有介绍到分布式数据库的增删改查API,这里就使用API进行数据库操作就行了,写入用put,读取用get,删除用delete;因为后面都是根据数据类型区分,获取的时候也要通过对应的数据类型去获取,这里就使用string来进行举例。
使用单版本分布式数据库写入String类型的数据:
singleKvStore.putString("stringKey","hello word");
读取单版本分布式数据库中String类型的数据:
String stringValue = singleKvStore.getString("stringKey");
删除单版本分布式数据库中指定key的数据:
singleKvStore