第四章:分布式数据库创建
好,咱们进入正题。分布式数据库的创建,说白了就是给跨设备的数据找个「家」。这个家得能自己搬家、自己备份、自己同步——嗯,听起来挺智能的,但配置起来其实有套路。
4.1 创建分布式数据库
在鸿蒙里,分布式数据库不是传统的关系型数据库,而是基于键值对(KV Store)的。我个人习惯用 distributedKVStore 这个 API,它天然支持跨设备同步。
先看一个最基础的创建流程:
// 获取分布式数据库管理器
DistributedKVStoreManager kvManager =
DistributedKVStoreManager.getInstance(context);
// 配置数据库参数
KVStoreConfig config = new KVStoreConfig("my_app_db", "user_data");
config.setSecurityLevel(SecurityLevel.S2); // 安全等级
// 创建数据库(异步)
kvManager.createKVStore(config, new CreateCallback() {
@Override
public void onSuccess(DistributedKVStore kvStore) {
// 数据库创建成功
Log.i("DB", "分布式数据库创建成功");
}
@Override
public void onFailure(int errorCode, String errorMsg) {
Log.e("DB", "创建失败: " + errorMsg);
}
});
这里有个坑——SecurityLevel 别乱设。S2 是默认等级,适合大多数场景。我曾经有个项目为了省事设了 S1,结果数据在传输过程中被截获了...嗯,后来老老实实改回 S2。
4.2 配置同步策略
同步策略是分布式数据库的灵魂。你想想看,两个设备同时修改同一条数据,听谁的?
鸿蒙提供了三种同步模式:
| 同步模式 | 说明 | 适用场景 |
|---|---|---|
| PULL_ONLY | 只拉取远端数据 | 设备只读场景 |
| PUSH_ONLY | 只推送本地数据 | 传感器上报 |
| PUSH_PULL | 双向同步 | 大多数业务场景 |
我个人建议:除非你有特殊需求,否则用 PUSH_PULL。但要注意冲突处理——鸿蒙默认是「最后写入者胜出」。如果你需要更精细的控制,可以自定义冲突解决器:
KVStoreSyncStrategy strategy = new KVStoreSyncStrategy();
strategy.setSyncMode(SyncMode.PUSH_PULL);
strategy.setConflictResolver(new ConflictResolver() {
@Override
public byte[] resolve(byte[] localValue, byte[] remoteValue,
long localTimestamp, long remoteTimestamp) {
// 自定义规则:取时间戳较新的
return localTimestamp > remoteTimestamp ? localValue : remoteValue;
}
});
避坑指南:我曾经在智能家居项目里,两个设备同时修改了灯光的亮度值。因为没配冲突策略,结果灯一会儿亮一会儿暗...后来加了时间戳比较才解决。
4.3 数据表与字段设计
分布式数据库虽然是 KV 结构,但「表」的概念依然存在。每个 DistributedKVStore 可以理解为一个表,而键值对就是行记录。
设计时我建议遵循三个原则:
- 键要带前缀:比如
user_001、device_002,方便按类型查询 - 值用 JSON:结构化数据用 JSON 序列化,别用纯字符串
- 字段精简:只存需要同步的字段,本地缓存放本地数据库
举个例子,一个跨设备待办事项的数据结构:
// 键设计
String key = "todo_" + UUID.randomUUID().toString();
// 值设计(JSON格式)
{
"title": "买牛奶",
"status": 0, // 0:未完成 1:已完成
"createTime": 1700000000,
"updateTime": 1700000100,
"deviceId": "phone_01"
}
这里有个细节:deviceId 字段很重要。为什么?因为分布式环境下,你得知道这条数据是从哪个设备来的。我遇到过一个问题:手机和手表同步待办,手表删了一条,手机也删了一条,结果同步后两条都消失了——加上设备 ID 后,就能区分是谁删的。
4.4 实战:创建待办事项数据库
好,咱们把上面讲的串起来,写一个完整的创建流程:
public class TodoDatabaseManager {
private DistributedKVStore kvStore;
public void init(Context context) {
DistributedKVStoreManager manager =
DistributedKVStoreManager.getInstance(context);
KVStoreConfig config = new KVStoreConfig("todo_db", "todos");
config.setSecurityLevel(SecurityLevel.S2);
manager.createKVStore(config, new CreateCallback() {
@Override
public void onSuccess(DistributedKVStore store) {
kvStore = store;
// 配置同步策略
KVStoreSyncStrategy strategy = new KVStoreSyncStrategy();
strategy.setSyncMode(SyncMode.PUSH_PULL);
strategy.setAutoSync(true); // 自动同步
kvStore.setSyncStrategy(strategy);
Log.i("DB", "待办数据库创建成功,已开启自动同步");
}
});
}
// 添加待办
public void addTodo(String title) {
String key = "todo_" + System.currentTimeMillis();
String value = String.format(
"{\"title\":\"%s\",\"status\":0,\"createTime\":%d}",
title, System.currentTimeMillis()
);
kvStore.put(key, value.getBytes());
}
}
setAutoSync(true) 开启后,数据变更会自动同步到其他设备。但要注意网络状态——没网时数据会暂存本地,等网络恢复再同步。
4.5 避坑总结
做分布式数据库,我踩过的坑不少。给你列几个重点:
- 键名冲突:不同模块用相同前缀,数据会乱。建议按模块划分前缀
- 同步延迟:分布式不是实时的,别指望毫秒级同步。我一般加个 500ms 的缓冲
- 数据膨胀:KV 数据库没有自动清理机制。记得定期删除过期数据
嗯,创建分布式数据库其实不难。难的是想清楚「哪些数据需要同步」「冲突了怎么办」。我建议你从一个小功能开始,比如跨设备同步一个计数器,跑通了再上复杂业务。
下一章咱们聊聊数据同步的底层原理——为什么有时候同步会失败?怎么监控同步状态?到时候见。