分布式数据服务(Distributed Data Service,DDS) 为应用程序提供不同设备间数据库数据分布式的能力。通过调用分布式数据接口,应用程序将数据保存到分布式数据库中。通过结合帐号、应用和数据库三元组,分布式数据服务对属于不同应用的数据进行隔离,保证不同应用之间的数据不能通过分布式数据服务互相访问。在通过可信认证的设备间,分布式数据服务支持应用数据相互同步,为用户提供在多种终端设备上最终一致的数据访问体验。
强一致性对分布式数据的管理要求非常高,在服务器的分布式场景可能会遇到。因为移动终端设备的不常在线、以及无中心的特性,分布式数据服务不支持强一致性,只支持最终一致性。
分布式数据服务支撑HarmonyOS系统上应用程序数据库数据分布式管理,支持数据在相同帐号的多端设备之间相互同步,为用户在多端设备上提供一致的用户体验,分布式数据服务包含五部分:
应用程序通过调用分布式数据服务接口实现分布式数据库创建、访问、订阅功能,服务接口通过操作服务组件提供的能力,将数据存储至存储组件,存储组件调用同步组件实现将数据同步,同步组件使用通信适配层将数据同步至远端设备,远端设备通过同步组件接收数据,并更新至本端存储组件,通过服务接口提供给应用程序使用。
图1 数据分布式运作示意图
分布式数据服务主要实现用户设备中应用程序的数据内容的分布式同步。当设备1上的应用A在分布式数据库中增、删、改数据后,设备2上的应用A也可以获取到该数据库变化。可在分布式图库、信息、通讯录、文件管理器等场景中使用。
HarmonyOS系统中的分布式数据服务模块为开发者提供下面几种功能:
功能分类 | 接口名称 | 描述 |
---|---|---|
分布式数据库创建、打开、关闭和删除。 | 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) | 删除分布式数据库。 | |
分布式数据增、删、改、查。 | getStoreId() | 获取分布式数据库实例的标识符。 |
putBoolean(String key, boolean value) putInt(String key, int value) putFloat(String key, float value) putDouble(String key, double value) putString(String key, String value) putByteArray(String key, byte[] value) putBatch(List<Entry> entries) | 插入和更新数据。 | |
delete(String key) deleteBatch(List<String> keys) | 删除数据。 | |
getInt(String key) getFloat(String key) getDouble(String key) getString(String key) getByteArray(String key) getEntries(String keyPrefix) | 查询数据。 | |
分布式数据谓词查询。 | select() reset() equalTo(String field, int 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) 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) greaterThan(String field, long value) greaterThan(String field, double value) greaterThan(String field, String value) lessThan(String field, int value) lessThan(String field, long value) lessThan(String field, double value) lessThan(String field, String value) greaterThanOrEqualTo(String field, int value) greaterThanOrEqualTo(String field, long value) greaterThanOrEqualTo(String field, double value) greaterThanOrEqualTo(String field, String value) lessThanOrEqualTo(String field, int value) lessThanOrEqualTo(String field, long value) lessThanOrEqualTo(String field, double value) lessThanOrEqualTo(String field, String value) isNull(String 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<Integer> valueList) inLong(String field, List<Long> valueList) inDouble(String field, List<Double> valueList) inString(String field, List<String> valueList) notInInt(String field, List<Integer> valueList) notInLong(String field, List<Long> valueList) notInDouble(String field, List<Double> valueList) notInString(String field, List<String> valueList) and() or() | 对于Schema数据库谓词查询数据。 |
订阅分布式数据变化。 | subscribe(SubscribeType subscribeType, KvStoreObserver observer) | 订阅数据库中数据的变化。 |
分布式数据同步。 | sync(List<String> deviceIdList, SyncMode mode) | 在手动模式下,触发数据库同步。 |
以单版本分布式数据库为例,说明开发步骤。
在config.json中添加permisssion权限。
// 添加在abilities同一目录层级
"reqPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC"
}
]
应用启动时,需要弹出授权提示框,请求用户进行授权。
根据配置构造分布式数据库管理类实例。
以下为创建分布式数据库管理器的代码示例:
Context context = getApplicationContext();
...
KvManagerConfig config = new KvManagerConfig(context);
KvManager kvManager = KvManagerFactory.getInstance().createKvManager(config);
获取/创建单版本分布式数据库。
以下为创建单版本分布式数据库的代码示例:
try {
Options options = new Options();
options.setCreateIfMissing(true).setEncrypt(false).setKvStoreType(KvStoreType.SINGLE_VERSION);
String storeId = "testApp";
SingleKvStore singleKvStore = kvManager.getKvStore(options, storeId);
} catch (KvStoreException e) {
HiLog.warn(LABEL_LOG, "getKvStore:" + e.getKvStoreErrorCode());
}
订阅分布式数据变化。
1. 客户端需要实现KvStoreObserver接口。
2. 构造并注册KvStoreObserver实例。
以下为订阅单版本分布式数据库所有(本地及远端)数据变化通知的代码示例:
class KvStoreObserverClient implements KvStoreObserver {
@Override
public void onChange(ChangeNotification notification) {
List<Entry> insertEntries = notification.getInsertEntries();
List<Entry> updateEntries = notification.getUpdateEntries();
List<Entry> deleteEntries = notification.getDeleteEntries();
}
}
KvStoreObserver kvStoreObserverClient = new KvStoreObserverClient();
singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, kvStoreObserverClient);
将数据写入单版本分布式数据库。
以下为将字符串类型键值数据写入单版本分布式数据库的代码示例:
try {
String key = "todayWeather";
String value = "Sunny";
singleKvStore.putString(key, value);
} catch (KvStoreException e) {
HiLog.warn(LABEL_LOG, "putString:" + e.getKvStoreErrorCode());
}
如果应用对性能比较敏感,建议使用批量写入接口putBatch。查询单版本分布式数据库数据。
以下为从单版本分布式数据库中查询字符串类型数据的代码示例:
try {
String key = "todayWeather";
String value = singleKvStore.getString(key);
} catch (KvStoreException e) {
HiLog.warn(LABEL_LOG, "getString:" + e.getKvStoreErrorCode());
}
同步数据到其他设备。
1. 获取已连接的设备列表。
2. 选择同步方式进行数据同步。
以下为单版本分布式数据库进行数据同步的代码示例,其中同步方式为PUSH_ONLY:
List<DeviceInfo> deviceInfoList = kvManager.getConnectedDevicesInfo(DeviceFilterStrategy.NO_FILTER);
List<String> deviceIdList = new ArrayList<>();
for (DeviceInfo deviceInfo : deviceInfoList) {
deviceIdList.add(deviceInfo.getId());
}
singleKvStore.sync(deviceIdList, SyncMode.PUSH_ONLY);
关闭单版本分布式数据库。如果组网设备间不再需要同步数据并且本地也不再访问,就可以执行关闭数据库的操作。以下为关闭单版本分布式数据库的代码示例:
try {
kvManager.closeKvStore(singleKvStore);
} catch (KvStoreException e) {
HiLog.warn(LABEL_LOG, "closeKvStore:" + e.getKvStoreErrorCode());
}
删除单版本分布式数据库。以下为删除单版本分布式数据库的代码示例:
try {
kvManager.deleteKvStore(storeId);
} catch (KvStoreException e) {
HiLog.warn(LABEL_LOG, "deleteKvStore:" + e.getKvStoreErrorCode());
}