MMKV 是微信团队开源的一款高效、轻量、易用的移动端键值存储框架,最初在微信 App 内部大规模使用,后来逐步开源并扩展到多个平台。它的核心思路非常直接:用 mmap(内存映射)让一段内存与磁盘文件保持同步,再用 protobuf 做值的编解码,从而在写入时几乎不需要等待磁盘 I/O,同时把序列化开销压到最低。
与 Android 系统自带的 SharedPreferences 相比,MMKV 不需要在每次写入后手动调用 apply 或 commit,数据即刻落盘;与 SQLite 相比,它没有建表、字段、SQL 解析的负担,特别适合保存用户偏好、开关状态、简单缓存这类结构化小数据。微信内部之所以自研并长期使用 MMKV,正是因为 SharedPreferences 在跨进程、频繁写入、容量增大等场景下会出现性能与一致性问题,而 SQLite 又过于沉重。MMKV 把两者的优点结合起来:既有键值存储的简单 API,又有接近数据库的可靠性与并发能力。
目前 MMKV 已支持 Android、iOS/macOS、Windows、POSIX 以及 HarmonyOS NEXT,并提供了实验性的 Kotlin Multiplatform(KMP)支持。它的设计目标是"小而美":代码只包含进程锁、编解码辅助和 mmap 逻辑,不引入多余依赖,包体增量控制在几十 K 到几百 K 之间。在微信内部,MMKV 承担了大量用户偏好、会话草稿、开关状态、AB 实验分组等数据的存储,经受住了亿级用户的考验。开源后,MMKV 被广泛应用于各类 Android、iOS、Windows、HarmonyOS 应用中,成为替代 SharedPreferences / NSUserDefaults 的事实标准之一,也是国内移动端本地存储领域被引用最多的开源项目之一。
使用 MMKV 的一个典型场景是替代 SharedPreferences:原来每次 putString 后还要 apply(),并且在主线程偶发 I/O 抖动;换成 MMKV 后,写入接口变成一次内存追加,调用方完全感知不到延迟。另一个场景是跨进程共享数据:Android 上多进程 App 往往需要在主进程和推送进程之间同步用户登录态,MMKV 的进程锁机制让这一切变得透明。在 HarmonyOS NEXT 与 Windows 桌面端,MMKV 也提供了一致的 C++ 接口,使得同一套存储逻辑可以跨平台复用。本文基于仓库 README 逐节完整翻译整理,覆盖各平台的特性、安装方式与快速上手示例。
一、项目官方信息
| 项目 | 信息 |
|---|---|
| 项目名称 | MMKV |
| GitHub 仓库 | Tencent/MMKV |
| 出品方 | 腾讯 / 微信 |
| 最新版本 | 2.4.3(见 Releases) |
| 开源协议 | BSD 3-Clause(见 LICENSE.TXT) |
| 支持平台 | Android、iOS/macOS、Windows、POSIX、HarmonyOS NEXT、KMP |
| 中文文档 | README_CN.md |
| Wiki | MMKV Wiki |
二、官方图片与架构
MMKV 的底层数据结构是一个追加式的内存映射文件:每次写入都直接追加到 mmap 映射的内存末尾,操作系统会在合适的时机把脏页写回磁盘,因此调用方完全感知不到 I/O 延迟。这种设计的好处是写入操作只是在内存上做一次 memcpy,不需要经过用户态到内核态的系统调用,也不需要等待 fsync;坏处是文件会持续追加,需要靠 MMKV 内部的压缩与回收机制来控制大小。操作系统会在合适的时机把脏页写回磁盘,因此即使 App 崩溃,已写入的数据也基本不会丢失。
值使用 protobuf 编码,bool、int、string、bytes 等类型都有对应的编解码辅助函数。在多进程场景下,MMKV 内置进程锁,支持跨进程的并发读-读与读-写访问,这在 Android 多进程架构(例如推送服务、独立进程的 WebView)和桌面端多进程应用中尤为重要。
从工程角度看,MMKV 把键值存储的复杂度降到了最低:开发者不需要关心文件格式、不需要关心缓存失效、不需要关心序列化协议,只需要记住"写入即刻生效"。MMKV 内部会在文件过大时自动做一次压缩整理,把已被覆盖的旧值清理掉,避免文件无限膨胀。这种追加式日志结构(append-only log)的设计与 SQLite 的 WAL 模式有相似之处,但 MMKV 把它简化成了纯内存操作,没有任何后台线程。README 中给出了各平台的性能对比图:Android 上随机写入 int 类型 1000 次的基准图见 profile_android_mini.png,iOS 上随机写入 int 类型 10000 次的基准图见 profile_mini.png,更多基准数据见 Android benchmark 与 iOS benchmark。封面沿用本文既有官方仓库图,不再改动。
三、环境要求
根据 README 的说明,各平台的环境要求如下:
- Android:从 v2.0.0 起不再支持 32 位架构,也不再支持 API level 21 与 22;如果需要 32 位或 API 21~22,应使用 v1.3.x LTS 系列。这是因为新版把代码重心放在了 64 位现代设备上,32 位维护成本过高。对于仍需兼容 Android 5.0 以下的老项目,官方明确建议停留在 v1.3.x 分支,不要强行升级。v2.0 以上版本在 API 上与 v1.x 保持兼容,迁移时主要是去掉 32 位 ABI 支持。
- iOS/macOS:通过 CocoaPods 安装,需要先安装 CocoaPods;支持 iOS 与 macOS 双平台,Objective-C 与 Swift 工程均可直接使用。
- Windows:从源码编译,需要 Visual Studio(官方使用 VS2017 开发,其他版本需调整 Platform Toolset);默认以
MT/MTd运行时编译,若工程使用MD/MDd需统一运行时库设置,否则会链接报错。Windows 版本主要面向桌面端应用与编辑器插件场景,包体增量约 10K。 - POSIX:通过 CMake 集成,需要支持 C++11 以上的编译器,适用于 Linux、macOS 等类 Unix 系统,也可在嵌入式 Linux 上交叉编译。POSIX 版本包体增量约 7K,非常轻量。
- HarmonyOS NEXT:通过 OHPM 安装
@tencent/mmkv,需要 OpenHarmony 应用开发环境,目前为正式版本,API 与 Android/iOS 保持一致。 - KMP:v2.4.3 为实验性版本,目前目标平台为 Android 与 iOS,支持
iosArm64、iosSimulatorArm64、iosX64,API 与产物布局未来可能调整,不建议生产环境直接使用。KMP 版本适合希望在 Compose Multiplatform 工程中共享存储逻辑的开发者做早期尝试。
四、部署步骤
1. Kotlin Multiplatform(实验性)
在共享模块的 commonMain 中加入依赖:
kotlin {
sourceSets {
commonMain.dependencies {
implementation("com.tencent:mmkv-kmp:2.4.3")
}
}
}
初始化与打包细节见官方 KMP 指南。KMP 版本允许在 Android 与 iOS 之间共享同一份存储逻辑,适合 Compose Multiplatform 这类跨端工程。
2. Android 安装
在 app 模块的 build.gradle 中加入依赖:
dependencies {
implementation 'com.tencent:mmkv:2.4.3'
// replace "2.4.3" with any available version
}
其他安装方式见 Android Setup。Maven Central 上的坐标是 com.tencent:mmkv,版本号与 Release 对齐。加入依赖后无需额外权限声明,MMKV 只会在 App 沙箱目录内读写文件。
3. iOS/macOS 安装(CocoaPods)
- 安装 CocoaPods;
- 终端
cd到工程目录,执行pod repo update让 CocoaPods 识别最新版本; - 编辑 Podfile,在 app target 中加入
pod 'MMKV'; - 执行
pod install; - 打开 CocoaPods 生成的
.xcworkspace文件; - 在源码中
#import <MMKV/MMKV.h>即可。
其他安装方式见 iOS/macOS Setup。iOS 上也可以选择手动引入 framework 或源码编译,官方 Wiki 提供了详细步骤。
4. Windows 安装(源码)
git clone https://github.com/Tencent/MMKV.git
随后把 Core/core.vcxproj 加入解决方案,把 MMKV 工程加为依赖,在工程的 C/C++ → 常规 → 附加包含目录 加入 $(OutDir)include,在 链接器 → 常规 → 附加库目录 加入 $(OutDir),在 链接器 → 输入 → 附加依赖项 加入 mmkv.lib,最后在源码中 #include <MMKV/MMKV.h>。其他安装方式见 Windows Setup。需要特别注意运行时库一致性:MMKV 默认用 MT/MTd,若你的工程用 MD/MDd,必须把 MMKV 的运行时改成一致,反之亦然。如果使用的是不同于 VS2017 的 Visual Studio 版本,还需要在工程属性里把 Platform Toolset 切换到对应版本。
5. POSIX 安装(CMake)
克隆源码后,在 CMakeLists.txt 中加入:
add_subdirectory(mmkv/POSIX/src mmkv)
target_link_libraries(MyApp
mmkv)
其他安装方式见 POSIX Setup。这种方式适合在 Linux 服务端或嵌入式设备上使用 MMKV 做本地缓存,与 Android/iOS 端共享同一份数据格式。
6. HarmonyOS NEXT 安装(OHPM)
ohpm install @tencent/mmkv
五、使用方法
1. Android 快速上手
在 Application.onCreate() 中初始化:
public void onCreate() {
super.onCreate();
String rootDir = MMKV.initialize(this);
System.out.println("mmkv root: " + rootDir);
//……
}
initialize 返回 MMKV 的根目录,开发者可以据此确认数据落在哪个沙箱路径。在多进程场景下,建议在每个进程的 Application.onCreate 中都调用一次 initialize,因为 mmap 是进程内的映射,不同进程需要各自建立映射才能共享同一份文件。initialize 返回 MMKV 的根目录,开发者可以据此确认数据落在哪个沙箱路径。MMKV 提供全局实例,可直接使用:
import com.tencent.mmkv.MMKV;
MMKV kv = MMKV.defaultMMKV();
kv.encode("bool", true);
boolean bValue = kv.decodeBool("bool");
kv.encode("int", Integer.MIN_VALUE);
int iValue = kv.decodeInt("int");
kv.encode("string", "Hello from mmkv");
String str = kv.decodeString("string");
写入 bool、int、string 都只要一行 encode,读取用对应的 decodeXxx。所有修改即刻生效,不需要 apply。MMKV 还支持多进程访问,完整教程见 Android Tutorial。对于更复杂的数据结构,MMKV 还支持传入自定义的 MMKV 实例名,把不同业务的数据隔离到不同文件中,避免单文件过大。例如可以为用户偏好创建一个 defaultMMKV,为聊天草稿创建一个名为 draft 的实例,两者互不影响。
2. iOS/macOS 快速上手
在 -[MyApp application:didFinishLaunchingWithOptions:] 中初始化:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// init MMKV in the main thread
[MMKV initializeMMKV:nil];
//...
return YES;
}
直接使用全局实例:在主线程初始化后,MMKV 即可在任意线程读写,无需加锁。
MMKV *mmkv = [MMKV defaultMMKV];
[mmkv setBool:YES forKey:@"bool"];
BOOL bValue = [mmkv getBoolForKey:@"bool"];
[mmkv setInt32:-1024 forKey:@"int32"];
int32_t iValue = [mmkv getInt32ForKey:@"int32"];
[mmkv setString:@"hello, mmkv" forKey:@"string"];
NSString *str = [mmkv getStringForKey:@"string"];
多进程访问教程见 iOS Tutorial。iOS 上 MMKV 的包体增量不到 30K/架构,对 IPA 体积影响极小,且不需要任何额外配置即可使用。
3. Windows / POSIX 快速上手
在 main() 中初始化:Windows 与 POSIX 共用同一套 C++ API,区别仅在于初始化时传入的根目录路径。
#include "MMKV.h"
int main() {
std::string rootDir = getYourAppDocumentDir();
MMKV::initializeMMKV(rootDir);
//...
}
读写示例:
auto mmkv = MMKV::defaultMMKV();
mmkv->set(true, "bool");
std::cout << "bool = " << mmkv->getBool("bool") << std::endl;
mmkv->set(1024, "int32");
std::cout << "int32 = " << mmkv->getInt32("int32") << std::endl;
mmkv->set("Hello, MMKV for Windows", "string");
std::string result;
mmkv->getString("string", result);
std::cout << "string = " << result << std::endl;
Windows 教程见 Windows Tutorial,POSIX 教程见 POSIX Tutorial。C++ API 与 Android/iOS 风格一致,区别在于初始化需要传入应用文档目录,读取 string 时用引用参数接收结果。
4. HarmonyOS NEXT 快速上手
在 EntryAbility.onCreate() 中初始化:HarmonyOS 版本需要在 Ability 启动时传入应用上下文,才能确定 MMKV 的根目录。
import { MMKV } from '@tencent/mmkv';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
let appCtx = this.context.getApplicationContext();
let mmkvRootDir = MMKV.initialize(appCtx);
console.info('mmkv rootDir: ', mmkvRootDir);
……
}
读写示例:
import { MMKV } from '@tencent/mmkv';
let mmkv = MMKV.defaultMMKV();
mmkv.encodeBool('bool', true);
console.info('bool = ', mmkv.decodeBool('bool'));
mmkv.encodeInt32('int32', Math.pow(2, 31) - 1);
console.info('max int32 = ', mmkv.decodeInt32('int32'));
mmkv.encodeInt64('int', BigInt(2**63) - BigInt(1));
console.info('max int64 = ', mmkv.decodeInt64('int'));
let str: string = 'Hello OpenHarmony from MMKV';
mmkv.encodeString('string', str);
console.info('string = ', mmkv.decodeString('string'));
let arrayBuffer: ArrayBuffer = StringToArrayBuffer('Hello OpenHarmony from MMKV with bytes');
mmkv.encodeBytes('bytes', arrayBuffer);
let bytes = mmkv.decodeBytes('bytes');
console.info('bytes = ', ArrayBufferToString(bytes));
完整文档见 HarmonyOS NEXT Tutorial。HarmonyOS 版本支持 bool、int32、int64、string、bytes 等类型,与其他平台保持一致的 API 风格,包体增量约 600K/架构(HAR/HAP 打包后更小)。
六、核心特性
各平台的特性描述基本一致:高效——使用 mmap 保持内存与文件同步,使用 protobuf 编解码,充分利用各平台原生能力达到最佳性能;易用——随用随取,所有修改即刻保存,无需调用 sync、apply、commit 或 synchronize;轻量——只包含进程锁、编解码辅助和 mmap 逻辑,代码非常整洁,包体增量在 Android 上约 50K/架构(打包后更小),iOS/macOS 上不到 30K/架构,Windows 上约 10K,POSIX 上约 7K,HarmonyOS NEXT 上约 600K/架构(打包后更小)。
此外 Android、Windows、POSIX、HarmonyOS 均支持跨进程并发读-读与读-写访问,这对多进程应用至关重要。相比 SharedPreferences 只能在单进程内可靠工作,MMKV 的多进程能力让它能直接服务于推送进程、WebView 进程等场景。相比 Realm 或 SQLite,MMKV 没有 schema 迁移、没有查询语言、没有后台线程,学习成本几乎为零。在包体方面,MMKV 的设计哲学是"能少则少":除了核心 mmap 与 protobuf 逻辑外,不引入任何第三方依赖,因此在 Android 上每架构只增加约 50K,在 iOS 上每架构不到 30K,在 Windows 上约 10K,在 POSIX 上约 7K,在 HarmonyOS 上约 600K,打包压缩后体积更小。这种轻量性让 MMKV 几乎不会对 App 包体造成负担。
七、常见问题(FAQ)
- 如何开始使用? 按上文在 App 启动时初始化,然后直接使用
defaultMMKV()读写即可,无需任何额外配置。 - 多进程怎么用? 参考各平台 Tutorial 中的多进程章节,MMKV 已内置进程锁,跨进程并发安全。
- 历史版本兼容? 需要 32 位或 API 21~22 的 Android 项目请使用 v1.3.x LTS,新版 v2.0 以上只支持 64 位。
- 数据怎么备份? MMKV 文件就放在沙箱根目录下,直接复制整个目录即可备份;卸载重装后把文件放回原位即可恢复。
- 支持哪些数据类型? bool、int、long、float、double、string、byte[] 都有对应的 encode/decode 接口,复杂对象可序列化为 bytes 后存储。
- 文件会无限增大吗? 不会,MMKV 内部会在文件过大时自动压缩整理,把已被覆盖的旧值清理掉。
- 可以加密吗? 官方提供了基于 MMKV 的加密扩展,详见 Wiki 中的加密章节,可对敏感数据做透明加密。
- 遇到问题? 先查 FAQ,仍无法解决可提交 Issue。
- 隐私政策? MMKV 不采集、不上传任何个人信息,详见 MMKV SDK 个人信息保护规则。MMKV 采用 Contributor Covenant 行为准则,欢迎遵守公约的开发者参与贡献,共同维护这个项目,让它在更多平台上发光发热。
- 如何贡献? 见 CONTRIBUTING.md,也可加入 Tencent OpenSource Plan。MMKV 已正式加入腾讯面向设备的服务产品联盟,与其他联盟成员共建开放互利的前端技术产品生态。
八、跳转链接
- 项目主页:https://github.com/Tencent/MMKV
- 最新版本:Releases
- 更新日志:CHANGELOG.md
- 中文说明:README_CN.md
- 贡献指南:CONTRIBUTING.md
- 行为准则:CODE_OF_CONDUCT.md
- 腾讯开源共建:Tencent OpenSource Plan