2. 整体架构设计:分层架构图、模块职责、数据流方向
离线读写架构的核心目标是在网络不可用时,仍能从本地持久化数据中完成读取操作;在网络恢复时,再按策略同步增量或全量数据。本章从分层视角拆解整体结构,明确每一层的边界与职责,并说明主数据流如何穿越各层。
架构原则:高内聚、低耦合、数据走向单一、缓存层可替换、网络层可降级。
2.1 分层架构总览
整个 SDK 自底向上划分为四层:数据持久层、离线缓存层、接入封装层、应用调用层。各层通过预定义接口通信,不跨层直接访问内部状态。
| 层级 | 名称 | 核心职责 |
|---|---|---|
| L4 | 应用调用层 | 业务方发起 API 请求,监听回调结果 |
| L3 | 接入封装层 | 统一请求构造、签名、错误码映射、降级开关 |
| L2 | 离线缓存层 | 本地读写、过期策略、同步队列、冲突合并 |
| L1 | 数据持久层 | SQLite / 文件系统 / Key-Value 存储,事务保证 |
2.2 主要模块及其职责
- API Router(接入封装层):根据网络状态判断走在线还是离线路径;在线时构造请求并发送,网络失败或超时自动降级。
- Cache Manager(离线缓存层):管理内存缓存与磁盘缓存的映射;提供
get()/put()/delete()接口;内部维护 TTL 与过期清理。 - Sync Queue(离线缓存层):当写入发生在离线状态时,将写操作用顺序队列持久化;网络恢复后按 FIFO 回放。
- Conflict Resolver(离线缓存层):在同步过程中检测版本冲突,按用户配置的策略(本地优先、服务端优先、合并)解决。
- Persistence Engine(数据持久层):基于 SQLite 的 ORM 封装,支持事务、批量写入、WAL 模式读优化。
设计决策:将冲突解析放在离线缓存层而非持久层,是因为冲突策略需要感知业务上下文(如时间戳、版本号、优先级),而持久层只关心原子写入。
2.3 数据流方向
数据流分为 同步路径 和 异步路径。同步路径指业务方直接调用本地缓存读取数据;异步路径指离线期间累积的写操作在网络恢复后统一同步到服务端。
2.3.1 同步读取路径
- 应用调用层传入请求 key。
- 接入封装层检查网络状态;若离线或超时,直接转本地缓存。
- 离线缓存层查询内存 cache;命中直接返回;未命中查磁盘缓存。
- 数据持久层从 SQLite 中读取;结果反序列化后逐层返回。
- 若内存 cache 未命中,在返回结果时异步更新内存 cache。
2.3.2 异步写回路径
- 应用在离线状态下调用写接口。
- 接入封装层判断不可在线写入,将写操作封装为
SyncTask对象。 - 离线缓存层将
SyncTask追加到 Sync Queue(本地 SQLite 或本地文件)。 - 同时将数据写入本地缓存(内存 + 磁盘),保证业务方能立即读到最新值。
- 网络恢复时,接入封装层 逐条 从 Sync Queue 读取任务,发起 HTTP 请求。
- 请求成功后从队列删除;若失败则保留并根据重试策略延期重试。
注意:离线缓存的写操作必须保证 原子性 — 要么本地缓存与 Sync Queue 同时更新成功,要么两者都回滚。推荐在离线缓存层使用本地事务包装这两个步骤。
2.4 关键数据结构示例
离线缓存层使用的核心数据结构是缓存记录与同步任务。下面分别展示其 JSON 形态:
缓存记录(CachedEntry)
{
"key": "user:1001",
"value": "{...业务数据...}",
"version": 3,
"expires_at": "2027-05-20T12:00:00Z",
"created_at": "2027-05-19T10:00:00Z",
"updated_at": "2027-05-19T14:00:00Z"
}
同步任务(SyncTask)
{
"task_id": "uuid-abc-123",
"type": "PUT",
"endpoint": "/api/v1/user",
"headers": {"X-Idempotency-Key": "uuid-abc-123"},
"body": "{\"name\":\"Alice\"}",
"retry_count": 0,
"max_retries": 5,
"status": "pending"
}
实践要点:同步任务必须携带幂等键(idempotency key),防止服务端重复处理。重试次数上限与指数退避(exponential backoff)一起在接入封装层配置。
2.5 模块间接口约定
| 调用方 | 被调方 | 接口方法 | 主要参数 |
|---|---|---|---|
| 接入封装层 | 离线缓存层 | get(key) |
字符串 key / 返回 Optional |
| 接入封装层 | 离线缓存层 | put(key, entry) |
key + CacheEntry / 返回布尔 |
| 离线缓存层 | 数据持久层 | readRow(sql, params) |
SQL 语句 + 参数列表 / 返回 Row |
| 离线缓存层 | 数据持久层 | writeBatch(tx, ops) |
事务对象 + 操作列表 / 返回布尔 |
| 接入封装层 | Sync Queue | enqueue(task) |
SyncTask / 返回 task_id |
所有接口均使用纯数据对象传递,禁止在模块间传递框架级上下文(如 Android Context 或 iOS NSManagedObjectContext),以保证各层可独立进行单元测试。