鸿蒙开发——键值型数据库的基本使用与跨设备同步

mxnet代码剖析之--kvstore篇 class KVStore Updater updater_; std::string type_; 1.1 kvstore节点包括worker, server, scheduler, if(role_str == 'local')节点为worker 1.2 /// ---------------------------------------------------- 阅读详情

1、简 述

❓ 什么是键值型数据库

键值型数据库(KV-Store)是一种非关系型数据库,其数据以“键值”对的形式进行组织、索引和存储,其中“键”作为唯一标识符。

键值型数据库适合很少数据关系和业务关系的业务数据存储。

另外,因键值型数据库在分布式场景中降低了解决数据库版本兼容问题的复杂度,和数据同步过程中冲突解决的复杂度而被广泛使用。相比于关系型数据库,更容易做到跨设备跨版本兼容。

当需要存储的数据没有复杂的关系模型,比如存储商品名称及对应价格、员工工号及今日是否已出勤等,由于数据复杂度低,更容易兼容不同数据库版本和设备类型,因此推荐使用键值型数据库持久化此类数据。

📢 使用键值型数据库时,需要注意以下几点:

    • 设备协同数据库,针对每条记录,Key的长度≤896 Byte,Value的长度<4 MB。

    • 单版本数据库,针对每条记录,Key的长度≤1 KB,Value的长度<4 MB。

    • 每个应用程序最多支持同时打开16个键值型分布式数据库。

    • 键值型数据库事件回调方法中不允许进行阻塞操作,例如修改UI组件。

    • 单个数据库最多支持注册8个订阅数据变化的回调。

    • 键值型数据库不支持应用程序自定义冲突解决策略。

2、键值型数据库的基本使用

键值型数据库的能力主要是由 @ohos.data.distributedKVStore 模块提供,实现不同设备间数据库的分布式协同能力。通过调用分布式键值数据库各个接口,应用程序可将数据保存到分布式键值数据库中,并可对分布式键值数据库中的数据进行增加、删除、修改、查询、同步等操作。

该模块提供以下分布式键值数据库相关的常用功能:

    • KVManager:分布式键值数据库管理实例,用于获取数据库的相关信息。

    • KVStoreResultSet:提供获取数据库结果集的相关方法,包括查询和移动数据读取位置等。

    • Query:使用谓词表示数据库查询,提供创建Query实例、查询数据库中的数据和添加谓词的方法。

    • SingleKVStore:单版本分布式键值数据库,不对数据所属设备进行区分,提供查询数据和同步数据的方法。

    • DeviceKVStore:设备协同数据库,继承自SingleKVStore,以设备维度对数据进行区分,提供查询数据和同步数据的方法。

以下是键值型数据库持久化功能的相关接口,大部分为异步接口。异步接口均有callback和Promise两种返回形式,下面均以callback形式为例:

// 创建一个KVManager对象实例,用于管理数据库对象。createKVManager(config: KVManagerConfig): KVManager// 指定options和storeId,创建并得到指定类型的KVStore数据库。getKVStore<T>(storeId: string, options: Options, callback: AsyncCallback<T>): void// 添加指定类型的键值对到数据库。put(key: string, value: Uint8Array | string | number | boolean, callback: AsyncCallback<void>): void// 获取指定键的值。get(key: string, callback: AsyncCallback<boolean | string | number | Uint8Array>): void// 从数据库中删除指定键值的数据。delete(key: string, callback: AsyncCallback<void>): void// 通过storeId的值关闭指定的分布式键值数据库。closeKVStore(appId: string, storeId: string, callback: AsyncCallback<void>): void// 通过storeId的值删除指定的分布式键值数据库。deleteKVStore(appId: string, storeId: string, callback: AsyncCallback<void>): void

使用示例

👉🏻 step 1:若要使用键值型数据库,首先要获取一个KVManager实例,用于管理数据库对象。示例代码如下所示(代码13 ~ 25行):

// 导入模块import { distributedKVStore } from '@kit.ArkData';import { window } from '@kit.ArkUI';import { UIAbility } from '@kit.AbilityKit';import { BusinessError } from '@kit.BasicServicesKit';let kvManager: distributedKVStore.KVManager | undefined = undefined;export default class EntryAbility extends UIAbility {  onCreate() {    let context = this.context;    const kvManagerConfig: distributedKVStore.KVManagerConfig = {      context: context,      bundleName: 'com.example.datamanagertest'    };    try {      // 创建KVManager实例      kvManager = distributedKVStore.createKVManager(kvManagerConfig);      console.info('Succeeded in creating KVManager.');      // 继续创建获取数据库    } catch (e) {      let error = e as BusinessError;      console.error(`Failed to create KVManager. Code:${error.code},message:${error.message}`);    }  }}if (kvManager !== undefined) {   kvManager = kvManager as distributedKVStore.KVManager;  //进行后续操作  //...}

👉🏻 step 2:基于step 1创建的kvManager,我们可以创建并获取键值数据库。示例代码如下所示:​​​​​​​

let kvStore: distributedKVStore.SingleKVStore | undefined = undefined;try {  const options: distributedKVStore.Options = {    createIfMissing: true,    encrypt: false,    backup: false,    autoSync: false,    // kvStoreType不填时,默认创建多设备协同数据库    kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,    // 多设备协同数据库:kvStoreType: distributedKVStore.KVStoreType.DEVICE_COLLABORATION,    securityLevel: distributedKVStore.SecurityLevel.S1  };  kvManager.getKVStore<distributedKVStore.SingleKVStore>('storeId', options, (err, store: distributedKVStore.SingleKVStore) => {    if (err) {      console.error(`Failed to get KVStore: Code:${err.code},message:${err.message}`);      return;    }    console.info('Succeeded in getting KVStore.');    kvStore = store;    // 请确保获取到键值数据库实例后,再进行相关数据操作  });} catch (e) {  let error = e as BusinessError;  console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);}if (kvStore !== undefined) {  kvStore = kvStore as distributedKVStore.SingleKVStore;    //进行后续操作    //...}

👉🏻 基于step 2创建的kvStore对象,我们可以调用put()方法向键值数据库中插入数据。示例代码如下所示:​​​​​​​

const KEY_TEST_STRING_ELEMENT = 'key_test_string';const VALUE_TEST_STRING_ELEMENT = 'value_test_string';try {  kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {    if (err !== undefined) {      console.error(`Failed to put data. Code:${err.code},message:${err.message}`);      return;    }    console.info('Succeeded in putting data.');  });} catch (e) {  let error = e as BusinessError;  console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);}

👉🏻 基于step 2创建的kvStore对象,我们调用get()方法获取指定键的值。示例代码如下所示:​​​​​​​

try {  kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {    if (err !== undefined) {      console.error(`Failed to put data. Code:${err.code},message:${err.message}`);      return;    }    console.info('Succeeded in putting data.');    kvStore = kvStore as distributedKVStore.SingleKVStore;    kvStore.get(KEY_TEST_STRING_ELEMENT, (err, data) => {      if (err != undefined) {        console.error(`Failed to get data. Code:${err.code},message:${err.message}`);        return;      }      console.info(`Succeeded in getting data. Data:${data}`);    });  });} catch (e) {  let error = e as BusinessError;  console.error(`Failed to get data. Code:${error.code},message:${error.message}`);}

👉🏻 基于step 2创建的kvStore对象,我们调用delete()方法删除指定键值的数据。示例代码如下所示:​​​​​​​

try {  kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {    if (err !== undefined) {      console.error(`Failed to put data. Code:${err.code},message:${err.message}`);      return;    }    console.info('Succeeded in putting data.');    kvStore = kvStore as distributedKVStore.SingleKVStore;    kvStore.delete(KEY_TEST_STRING_ELEMENT, (err) => {      if (err !== undefined) {        console.error(`Failed to delete data. Code:${err.code},message:${err.message}`);        return;      }      console.info('Succeeded in deleting data.');    });  });} catch (e) {  let error = e as BusinessError;  console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);}

👉🏻 基于step 1创建的kvManager对象,我们通过storeId的值关闭指定的分布式键值数据库。示例代码如下所示:​​​​​​​

try {  kvStore = undefined;  kvManager.closeKVStore('appId', 'storeId', (err: BusinessError)=> {    if (err) {      console.error(`Failed to close KVStore.code is ${err.code},message is ${err.message}`);      return;    }    console.info('Succeeded in closing KVStore');  });} catch (e) {  let error = e as BusinessError;  console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);}

👉🏻 基于step 1创建的kvManager对象,我们通过storeId的值删除指定的分布式键值数据库。示例代码如下所示:​​​​​​​

try {  kvStore = undefined;  kvManager.deleteKVStore('appId', 'storeId', (err: BusinessError)=> {    if (err) {      console.error(`Failed to close KVStore.code is ${err.code},message is ${err.message}`);      return;    }    console.info('Succeeded in closing KVStore');  });} catch (e) {  let error = e as BusinessError;  console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);}

3、键值型数据库跨设备数据同步

数据管理服务提供了两种同步方式:手动同步和自动同步。键值型数据库可选择其中一种方式实现同应用跨设备数据同步。

手动同步

由应用程序调用sync接口来触发,需要指定同步的设备列表和同步模式。同步模式分为:

  • PULL_ONLY(将远端数据拉取到本端);

  • PUSH_ONLY(将本端数据推送到远端);

  • PUSH_PULL(将本端数据推送到远端同时也将远端数据拉取到本端)。

自动同步

在跨设备Call调用实现的多端协同场景中,在应用程序更新数据后,由分布式数据库自动将本端数据推送到远端,同时也将远端数据拉取到本端来完成数据同步,应用不需要主动调用sync接口。

键值型数据库分为两种类型:单版本数据库、多设备协同分布式数据库。两种类型介绍如下:

  • 单版本数据库

单版本是指数据在本地是以单个条目为单位的方式保存,当数据在本地被用户修改时,不管它是否已经被同步出去,均直接在这个条目上进行修改。

多个设备全局只保留一份数据,多个设备的相同记录(主码相同)会按时间最新保留一条记录,数据不分设备,设备之间修改相同的key会覆盖。同步也以此为基础,按照它在本地被写入或更改的顺序将当前最新一次修改逐条同步至远端设备,常用于联系人、天气等应用存储场景。

图片

  • 多设备协同分布式数据库

多设备协同分布式数据库建立在单版本数据库之上,对应用程序存入的键值型数据中的Key前面拼接了本设备的DeviceID标识符,这样能保证每个设备产生的数据严格隔离。数据以设备的维度管理,不存在冲突;支持按照设备的维度查询数据。

底层按照设备的维度管理这些数据,多设备协同数据库支持以设备的维度查询分布式数据,但是不支持修改远端设备同步过来的数据。需要分开查询各设备数据的可以使用设备协同版本数据库。常用于图库缩略图存储场景。

图片

以下是单版本键值型分布式数据库跨设备数据同步功能的相关接口,大部分为异步接口。异步接口均有callback和Promise两种返回形式,下面均以callback形式为例。​​​​​​​

// 创建一个KVManager对象实例,用于管理数据库对象。createKVManager(config: KVManagerConfig): KVManager// 指定options和storeId,创建并得到指定类型的KVStore数据库。getKVStore<T>(storeId: string, options: Options, callback: AsyncCallback<T>): void// 插入和更新数据。put(key: string, value: Uint8Array | string | number | boolean, callback: AsyncCallback<void>): void// 订阅数据库中数据的变化。on(event: 'dataChange', type: SubscribeType, listener: Callback<ChangeNotification>): void// 查询指定Key键的值。get(key: string, callback: AsyncCallback<boolean | string | number | Uint8Array>): void// 在手动模式下,触发数据库同步。sync(deviceIds: string[], mode: SyncMode, delayMs?: number): void

使用分布式键值数据库需要申明权限:ohos.permission.DISTRIBUTED_DATASYNC,同时需要在应用首次启动时弹窗向用户申请授权

👉🏻 step 1:根据配置构造分布式数据库管理实例​​​​​​​

import { distributedKVStore } from '@kit.ArkData';import { window } from '@kit.ArkUI';import { UIAbility } from '@kit.AbilityKit';import { BusinessError } from '@kit.BasicServicesKit';let kvManager: distributedKVStore.KVManager | undefined = undefined;class EntryAbility extends UIAbility {  onWindowStageCreate(windowStage:window.WindowStage) {    let context = this.context;  }} // .... // 获取context之后,构造分布式数据库管理类实例try {  const kvManagerConfig: distributedKVStore.KVManagerConfig = {    bundleName: 'com.harmonyclassroom.datamanagertest',    context: context  }  kvManager = distributedKVStore.createKVManager(kvManagerConfig);  console.info('Succeeded in creating KVManager.');  // todo 继续创建获取数据库} catch (e) {  let error = e as BusinessError;  console.error(`Failed to create KVManager. Code:${error.code},message:${error.message}`);}if (kvManager !== undefined) {  kvManager = kvManager as distributedKVStore.KVManager;  // 进行后续创建数据库等相关操作  // ...}

👉🏻 step 2:获取并得到指定类型的键值型数据库。

    1. 声明需要创建的分布式数据库ID描述(例如示例代码中的'storeId')。

    2. 创建分布式数据库,建议关闭自动同步功能(autoSync:false),方便后续对同步功能进行验证,需要同步时主动调用sync接口

let kvStore: distributedKVStore.SingleKVStore | undefined = undefined;try {  let child1 = new distributedKVStore.FieldNode('id');  child1.type = distributedKVStore.ValueType.INTEGER;  child1.nullable = false;  child1.default = '1';  let child2 = new distributedKVStore.FieldNode('name');  child2.type = distributedKVStore.ValueType.STRING;  child2.nullable = false;  child2.default = 'zhangsan';  let schema = new distributedKVStore.Schema();  schema.root.appendChild(child1);  schema.root.appendChild(child2);  schema.indexes = ['$.id', '$.name'];  // 0表示COMPATIBLE模式,1表示STRICT模式。  schema.mode = 1;  // 支持在检查Value时,跳过skip指定的字节数,且取值范围为[0,4M-2]。  schema.skip = 0;  const options: distributedKVStore.Options = {    createIfMissing: true,    encrypt: false,    backup: false,    autoSync: false,    // kvStoreType不填时,默认创建多设备协同数据库    // 多设备协同数据库:kvStoreType: distributedKVStore.KVStoreType.DEVICE_COLLABORATION,    kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,    // schema 可以不填,在需要使用schema功能时可以构造此参数,例如:使用谓词查询等。    schema: schema,    securityLevel: distributedKVStore.SecurityLevel.S1  };  kvManager.getKVStore<distributedKVStore.SingleKVStore>('storeId', options, (err, store: distributedKVStore.SingleKVStore) => {    if (err) {      console.error(`Failed to get KVStore: Code:${err.code},message:${err.message}`);      return;    }    console.info('Succeeded in getting KVStore.');    kvStore = store;    // 请确保获取到键值数据库实例后,再进行相关数据操作  });} catch (e) {  let error = e as BusinessError;  console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);}if (kvStore !== undefined) {  kvStore = kvStore as distributedKVStore.SingleKVStore;    // 进行后续相关数据操作,包括数据的增、删、改、查、订阅数据变化等操作    // ...}

👉🏻 step 3:订阅分布式数据变化

如需关闭订阅分布式数据变化,调用off('dataChange')关闭。​​​​​​​

try {  kvStore.on('dataChange', distributedKVStore.SubscribeType.SUBSCRIBE_TYPE_ALL, (data) => {    console.info(`dataChange callback call data: ${data}`);  });} catch (e) {  let error = e as BusinessError;  console.error(`An unexpected error occurred. code:${error.code},message:${error.message}`);}

👉🏻 step 4:将数据写入分布式数据库。

    1. 构造需要写入分布式数据库的Key(键)和Value(值)。

    2. 将键值数据写入分布式数据库

const KEY_TEST_STRING_ELEMENT = 'key_test_string';// 如果未定义Schema则Value可以传其他符合要求的值。const VALUE_TEST_STRING_ELEMENT = '{"id":0, "name":"lisi"}';try {  kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {    if (err !== undefined) {      console.error(`Failed to put data. Code:${err.code},message:${err.message}`);      return;    }    console.info('Succeeded in putting data.');  });} catch (e) {  let error = e as BusinessError;  console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);}

👉🏻 step 5:查询分布式数据库数据。

    1. 构造需要从单版本分布式数据库中查询的Key(键)。

    2. 从单版本分布式数据库中获取数据

try {  kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {    if (err !== undefined) {      console.error(`Failed to put data. Code:${err.code},message:${err.message}`);      return;    }    console.info('Succeeded in putting data.');    kvStore = kvStore as distributedKVStore.SingleKVStore;    kvStore.get(KEY_TEST_STRING_ELEMENT, (err, data) => {      if (err != undefined) {        console.error(`Failed to get data. Code:${err.code},message:${err.message}`);        return;      }      console.info(`Succeeded in getting data. Data:${data}`);    });  });} catch (e) {  let error = e as BusinessError;  console.error(`Failed to get data. Code:${error.code},message:${error.message}`);}

👉🏻 step 6:同步数据到其他设备。

选择同一组网环境下的设备以及同步模式(需用户在应用首次启动的弹窗中确认选择同步模式),进行数据同步。​​​​​​​

import { distributedDeviceManager } from '@kit.DistributedServiceKit'; let devManager: distributedDeviceManager.DeviceManager;try {  // create deviceManager  devManager = distributedDeviceManager.createDeviceManager(context.applicationInfo.name);  // deviceIds由deviceManager调用getAvailableDeviceListSync方法得到  let deviceIds: string[] = [];  if (devManager != null) {    let devices = devManager.getAvailableDeviceListSync();    for (let i = 0; i < devices.length; i++) {      deviceIds[i] = devices[i].networkId as string;    }  }  try {    // 1000表示最大延迟时间为1000ms    kvStore.sync(deviceIds, distributedKVStore.SyncMode.PUSH_ONLY, 1000);  } catch (e) {    let error = e as BusinessError;    console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);  }} catch (err) {  let error = err as BusinessError;  console.error("createDeviceManager errCode:" + error.code + ",errMessage:" + error.message);}
在手动同步的方式下,其中的deviceIds通过调用devManager.getAvailableDeviceListSync方法得到。

鸿蒙开发基础 —— 键值型数据库跨设备数据同步 跨设备数据同步功能(即分布式功能),指将数据同步到一个组网环境中的其他设备。常用于用户应用程序数据内容在可信认证的不同设备间,进行自由同步、修改和查询。例如:当设备1上的应用A在分布式数据库中增、删、改数据后,设备2上的应用A也可以获取到该数据库变化。可在分布式图库、备忘录、联系人、文件管理器等场景中使用。不同应用间订阅数据库变化通知,则请参考 跨应用数据共享 实现。临时数据生命周期较短,通常保存到内存中。比如游戏应用产生的过程数据,建议使用分布式数据对象。 阅读详情

相关推荐

鸿蒙NEXT(开发进阶)键值型数据库跨设备数据同步

键值型数据库适合不涉及过多数据关系和业务关系的业务数据存储,比SQL数据库存储拥有更好的读写性能,同时因其在分布式场景中降低了解决数据库版本兼容问题的复杂度,和数据同步过程中冲突解决的复杂度而被广泛使用。

wea22984984的博客 1014

【HarmonyOS开发】ArkTs关系型和非关系型数据库的存储封装

前面使用了首选项的存储方式,因此将其他的两种存储方式()也学习一下,简单记录一下,并进行封装,方便后续使用。

qq_23334071的博客 5154

HarmonyOS NEXT开发:键值型数据库跨设备数据同步

键值型数据库适合不涉及过多数据关系和业务关系的业务数据存储,比SQL数据库存储拥有更好的读写性能,同时因其在分布式场景中降低了解决数据库版本兼容问题的复杂度,和数据同步过程中冲突解决的复杂度而被广泛使用。

wewq2882的博客 1046

HarmonyOS开发实例:【分布式手写板】

本篇Codelab使用设备管理及分布式键值数据库能力,实现多设备之间手写板应用拉起及同步书写内容的功能。设备连接同一无线网络,安装分布式手写板应用。进入应用,点击允许使用多设备协同,点击主页上查询设备按钮,显示附近设备。选择设备确认,若已建立连接,启动对方设备上的手写板应用,否则提示建立连接。输入PIN码建立连接后再次点击查询设备按钮,选择设备提交,启动对方设备应用。建立连接前绘制的内容在启动对方设备后同步,此时设备上绘制的内容会在另一端同步绘制。点击撤销按钮,两侧设备绘制内容同步撤销。

鸿蒙的技术博客 1657

【鸿蒙基于API 13实战开发】—— 键值型数据库跨设备数据同步

跨设备数据同步功能(即分布式功能),指将数据同步到一个组网环境中的其他设备。常用于用户应用程序数据内容在可信认证的不同设备间,进行自由同步、修改和查询。例如:当设备1上的应用A在分布式数据库中增、删、改数据后,设备2上的应用A也可以获取到该数据库变化。可在分布式图库、备忘录、联系人、文件管理器等场景中使用。不同应用间订阅数据库变化通知,则请参考 跨应用数据共享 实现。临时数据生命周期较短,通常保存到内存中。比如游戏应用产生的过程数据,建议使用分布式数据对象。

shangkangba的博客 903

鸿蒙OpenHarmony【键值型数据库跨设备数据同步】同应用跨设备数据同步

跨设备数据同步功能(即分布式功能),指将数据同步到一个组网环境中的其他设备。常用于用户应用程序数据内容在可信认证的不同设备间,进行自由同步、修改和查询。

adsjgfjha123123的博客 1020

KVstore :键值映射存储服务器

使用hash表实现存储服务kvstore

欢迎指正、交流 1599

HarmonyOS 应用开发之同应用跨设备数据同步

键值型数据库适合不涉及过多数据关系和业务关系的业务数据存储,比SQL数据库存储拥有更好的读写性能,同时因其在分布式场景中降低了解决数据库版本兼容问题的复杂度,和数据同步过程中冲突解决的复杂度而被广泛使用。

1 1754

鸿蒙应用开发 键值型数据库跨设备数据同步

跨设备数据同步功能实现应用数据在可信设备间的共享与协作,分为键值型和关系型两种数据库类型,支持最终一致性同步。系统提供手动和自动两种同步方式,通过加密通道传输数据,并基于设备安全等级实施访问控制。开发流程包括:导入模块、申请权限、创建数据库实例、数据操作和同步触发。单版本数据库每条记录限制为Key≤1KB、Value<4MB,最多同时打开16个数据库。该功能适用于联系人、图库等需要多设备协同的场景,通过订阅机制实现数据变更通知,确保组网设备间的数据最终一致。

sy7748的博客 1076

鸿蒙开发——关系型数据库的基本使用与跨设备同步

关系型数据库基于SQLite组件,适用于存储包含复杂关系数据的场景,比如一个班级的学生信息,需要包括姓名、学号、各科成绩等,又或者公司的雇员信息,需要包括姓名、工号、职位等,由于数据之间有较强的对应关系,复杂程度比键值型数据更高,此时需要使用关系型数据库来持续化保存数据。大数据量场景下查询数据可能会导致耗时长甚至应用卡死,有建议如下:单次查询数据量不超过5000条。在TaskPool中查询。拼接SQL语句尽量简洁。合理地分批次查询。

duoduola666的博客 989

鸿蒙应用开发—同应用跨设备数据同步

键值型数据库适合不涉及过多数据关系和业务关系的业务数据存储,比SQL数据库存储拥有更好的读写性能,同时因其在分布式场景中降低了解决数据库版本兼容问题的复杂度,和数据同步过程中冲突解决的复杂度而被广泛使用。

duolala888的博客 864

鸿蒙NEXT开发键值型数据工具类KvUtil(ArkTs)

鸿蒙NEXT开发键值型数据工具类(ArkTs)

鸿蒙布道师 5325

distributedKVstore:一个简单的基于Kompics的分布式KV商店

ID2203 2021年Kompics Scala启动程序代码 概述 主要模块: 顺序Paxos 领导人选举 GET / PUT / CAS kvstore 最终完美的故障检测仪 叠加层管理器 测试 主要结构: 入门 git clone将存储库的git clone (您的分支) git clone到本地计算机,并将其cd到该文件夹​​中。 确保已安装 。 建筑 从开始sbt sbt 在sbt REPL中,使用 compile 您可以使用以下命令运行测试套件(包括模拟) test 在运行项目之前,您需要为服务器和客户端创建程序集文件: server/assembly client/assembly 跑步 使用脚本设置集群 设置服务器号为3的集群(默认为3或4、5 ...,但至少不小于您设置的reference.conf中的bootThreshold) ./clus

鸿蒙应用开发之实现键值型数据库跨设备数据同步

键值型数据库适合不涉及过多数据关系和业务关系的业务数据存储,比SQL数据库存储拥有更好的读写性能,同时因其在分布式场景中降低了解决数据库版本兼容问题的复杂度,和数据同步过程中冲突解决的复杂度而被广泛使用。

风中追风 1138

LilyPad三色LED共阳极控制:从原理到Arduino编程实战

RGB LED作为可编程光源的核心组件,通过红、绿、蓝三原色的加色混合原理,能够生成丰富的色彩。其内部结构主要分为共阳极和共阴极两种类型,这决定了驱动电路的设计和编程逻辑。在电子织物和可穿戴设备领域,掌握RGB LED的控制技术对于实现动态光效和交互反馈至关重要。本文以LilyPad三色LED为例,深入解析其共阳极特性,并详细演示如何结合Arduino进行PWM编程,从而精准控制颜色与亮度,为智能服装、互动艺术装置等项目提供可靠的照明解决方案。

weixin_30237719的博客 610

图相似度模型(论文篇)

图相似度模型

weixin_43702653的博客 5748

鸿蒙开发0基础【键值型数据库跨设备数据同步】方舟数据管理

键值型数据库适合不涉及过多数据关系和业务关系的业务数据存储,比SQL数据库存储拥有更好的读写性能,同时因其在分布式场景中降低了解决数据库版本兼容问题的复杂度,和数据同步过程中冲突解决的复杂度而被广泛使用。

zhenggaoxiao232的博客 859

村田电感模型选型指南:.s2p和SPICE netlist在ADS中的表现差异

本文深度解析了村田电感在ADS仿真中.s2p与SPICE netlist两种模型的表现差异。通过对比模型本质、仿真设置及高低频段精度,揭示了.s2p文件基于实测插值而SPICE netlist基于等效电路外推的特性。文章提供了明确的选型策略,帮助工程师根据项目频段、仿真类型和精度需求,在射频与微波电路设计中做出最优模型选择。

k9l0m1的博客 452

鸿蒙开发实践案例分析——同应用跨设备数据同步

跨设备数据同步功能(即分布式功能),指将数据同步到一个组网环境中的其他设备。常用于用户应用程序数据内容在可信认证的不同设备间,进行自由同步、修改和查询。例如:当设备1上的应用A在分布式数据库中增、删、改数据后,设备2上的应用A也可以获取到该数据库变化。可在分布式图库、备忘录、联系人、文件管理器等场景中使用。根据跨设备同步数据生命周期的不同,可以分为:临时数据生命周期较短,通常保存到内存中。比如游戏应用产生的过程数据,建议使用分布式数据对象。

2501_91726491的博客 887

ScanNet数据集下载全攻略:从申请到解析的保姆级教程(含常见问题解决)

本文提供了ScanNet数据集从申请授权到下载、解析的完整实战指南。针对这个大规模室内RGB-D数据集,详细介绍了官方申请流程、优化下载策略、数据验证方法,并重点解决了深度图解析等常见问题,帮助三维视觉研究者高效获取和使用这一宝贵资源。

5f4d3s2a1q的博客 619

非球面检测

摘要:非球面镜检测主要采用干涉法,包括零位补偿和非零位补偿两种方式。零位补偿通过透镜组完全校正像差,精度达1%波长,但设计复杂成本高;非零位补偿利用部分像差补偿降低波前斜率,适用于规则非球面。折射-衍射混合补偿镜能同时校正多种像差。实际检测中可采用物理补偿镜或动态CGH加载方案,光路设计需运用坐标断点和多重结构技术实现复杂光路建模。不同方法各具优势,需根据检测需求选择合适方案。

Zhaxibamao的博客 2109
上一篇: 鸿蒙开发实战——使用Canvas绘制环形文字
下一篇: 鸿蒙UI开发——渐变色效果
鸿蒙自习室
博客等级 码龄2年 2083粉丝 144原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值