2. 整体架构设计:分层架构图、模块职责、数据流方向

离线读写架构的核心目标是在网络不可用时,仍能从本地持久化数据中完成读取操作;在网络恢复时,再按策略同步增量或全量数据。本章从分层视角拆解整体结构,明确每一层的边界与职责,并说明主数据流如何穿越各层。

架构原则:高内聚、低耦合、数据走向单一、缓存层可替换、网络层可降级。

2.1 分层架构总览

整个 SDK 自底向上划分为四层:数据持久层、离线缓存层、接入封装层、应用调用层。各层通过预定义接口通信,不跨层直接访问内部状态。

层级 名称 核心职责
L4 应用调用层 业务方发起 API 请求,监听回调结果
L3 接入封装层 统一请求构造、签名、错误码映射、降级开关
L2 离线缓存层 本地读写、过期策略、同步队列、冲突合并
L1 数据持久层 SQLite / 文件系统 / Key-Value 存储,事务保证
离线读写分层架构图 分层架构 & 数据流方向 L4 应用调用层 API 请求入口 · 回调处理 · 降级触发 L3 接入封装层 签名 · 错误映射 · 网络就绪判断 L2 离线缓存层 缓存读写 · 过期策略 · 同步队列 L1 数据持久层 SQLite · 文件存储 · 事务保障 请求流向(读/写) 数据持久层 SQLite 事务写入,WAL 模式 离线缓存层 LRU 淘汰 · TTL 过期 · 写回队列 接入封装层 签名验证 · 错误域转化 各层通过纯接口通信,不跨层访问内部状态

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 同步读取路径

  1. 应用调用层传入请求 key。
  2. 接入封装层检查网络状态;若离线或超时,直接转本地缓存。
  3. 离线缓存层查询内存 cache;命中直接返回;未命中查磁盘缓存。
  4. 数据持久层从 SQLite 中读取;结果反序列化后逐层返回。
  5. 若内存 cache 未命中,在返回结果时异步更新内存 cache。

2.3.2 异步写回路径

  1. 应用在离线状态下调用写接口。
  2. 接入封装层判断不可在线写入,将写操作封装为 SyncTask 对象。
  3. 离线缓存层将 SyncTask 追加到 Sync Queue(本地 SQLite 或本地文件)。
  4. 同时将数据写入本地缓存(内存 + 磁盘),保证业务方能立即读到最新值。
  5. 网络恢复时,接入封装层 逐条 从 Sync Queue 读取任务,发起 HTTP 请求。
  6. 请求成功后从队列删除;若失败则保留并根据重试策略延期重试。
注意:离线缓存的写操作必须保证 原子性 — 要么本地缓存与 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),以保证各层可独立进行单元测试。