MMKV全解

3 阅读3分钟

一、MMKV 是什么?

  • 腾讯开源的高性能通用 key-value 存储组件GitHub: Tencent/MMKV)。
  • 底层基于 mmap + protobuf,替代 SharedPreferences 解决性能和多进程一致性问题。
  • 支持多平台(Android、iOS、Windows、macOS、Linux)。

二、核心原理

1. mmap(内存映射)

  • 使用 mmap 将文件映射到内存,读写直接操作内存区域。

  • 内存变更自动映射到文件,减少频繁磁盘 I/O。

  • 优势

    • 避免整文件序列化/反序列化。
    • 数据直接在内存读写,速度接近内存访问。

2. protobuf 序列化

  • key/value 序列化存储在 mmap 区域。
  • 新增/更新数据是追加写,不必全量覆盖旧数据。
  • 定期触发一次“回收/重整”(类似 log compaction)释放空间。

3. 多进程一致性

  • mmap 文件在多个进程间共享。
  • 每个进程有文件锁/读写锁机制,保证数据一致性。
  • 修改后可通过 mmkv.sync()mmkv.reloadFromFile() 及时更新内存。

三、MMKV vs SharedPreferences

特性SharedPreferencesMMKV
存储格式XMLProtobuf(二进制)
写入方式全量重写 XML追加写
底层 I/O文件流mmap
多进程一致性默认不支持原生支持
性能频繁写入慢读写接近内存速度
类型支持基本类型 + Set基本类型 + Set + 自定义字节数组

四、常见面试题

Q1:MMKV 为什么比 SharedPreferences 快?

  • 读写都在内存(mmap)中完成,不需要频繁磁盘 I/O。
  • protobuf 序列化高效,更新是增量写,不用全量重写文件。
  • SP 每次写都重新生成整个 XML 文件,MMKV 只修改变化部分。

Q2:MMKV 会丢数据吗?

  • 理论上可能:mmap 变更延迟刷盘,极端情况下(崩溃/断电)可能丢最后几毫秒的写入。
  • 可调用 mmkv.sync() 主动刷盘降低风险。

Q3:MMKV 如何实现多进程读写一致性?

  • 通过 mmap 映射同一个文件到不同进程,数据天然共享。
  • 写操作加文件锁,防止并发冲突。
  • 其他进程可 mmkv.reloadFromFile() 同步最新数据。

Q4:MMKV 有大小限制吗?

  • 单个 mmap 文件默认最大 1MB,空间不足会自动扩容(翻倍策略)。
  • 实际存储受设备文件系统限制(一般几百 MB 以上没问题)。

Q5:MMKV 支持事务吗?

  • 不支持像数据库那样的事务机制,但单次写入是原子的(protobuf 完整性校验)。
  • 多条数据更新可以批量操作后 sync()

Q6:MMKV 何时需要调用 sync()

  • 默认依赖系统定时刷盘。
  • 关键数据(支付状态、敏感标志)更新后建议立即 sync()

Q7:MMKV 跨进程实时性如何?

  • 进程 A 写入后,进程 B 不会立即感知,需要主动调用 reloadFromFile() 或注册文件变更监听(自己实现)。

Q8:MMKV 替代 SP 时有哪些坑?

  1. 加密版本:初始化时要指定密钥,密钥丢失文件不可读。
  2. Set 线程安全:返回的是副本,和 SP 一样,不能直接改内部集合。
  3. 多进程同步:必须主动 reload。
  4. 数据迁移:第一次使用需从 SP 迁移数据(MMKV.importFromSharedPreferences())。

五、常见追问

  • Q:MMKV 为啥用 mmap,不直接读写文件?
    直接读写文件每次都要系统调用 + 拷贝数据;mmap 让文件和内存共享同一块地址,减少数据复制。
  • Q:MMKV 为什么用 protobuf 而不是 JSON/XML?
    protobuf 二进制格式更紧凑,解析速度快,适合频繁读写。
  • Q:MMKV 如何扩容?
    检测到剩余空间不足 → 分配更大 mmap 文件 → 拷贝旧数据 → 指针切换到新映射。

六、总结面试答法

MMKV 是腾讯开源的高性能 key-value 存储,基于 mmap + protobuf 实现,读写几乎是内存速度,支持多进程数据一致性。相比 SharedPreferences 不用全量重写文件,支持更多数据类型。适合高频、小数据量的配置存储,重要数据可配合 sync(),多进程需 reloadFromFile 保证一致性。