不像 iOS 提供了硬件层级的加密机制,在 Android 环境里,数据加密是非常必须的。
MMKV 使用了 AES CFB-128 算法来加密/解密。我们选择 CFB 而不是常见的 CBC 算法,
主要是因为 MMKV 使用 append-only 实现插入/更新操作,流式加密算法更加合适。
- 数据有效性
MMKV 原理
- 内存准备
通过 mmap 内存映射文件,提供一段可供随时写入的内存块,App 只管往里面写数据,由操作系统负责将内存回写到文件,不必担心 crash 导致数据丢失。 - 数据组织
数据序列化方面我们选用 protobuf 协议,pb 在性能和空间占用上都有不错的表现。 - 写入优化
考虑到主要使用场景是频繁地进行写入更新,我们需要有增量更新的能力。我们考虑将增量 kv 对象序列化后,append 到内存末尾。
这样同一个 key 会有新旧若干份数据,最新的数据在最后;那么只需在程序启动第一次打开 mmkv 时,不断用后读入的 value 替换之前的值,就可以保证数据是最新有效的。 - 空间增长
使用 append 实现增量更新带来了一个新的问题,就是不断 append 的话,文件大小会增长得不可控。我们需要在性能和空间上做个折中。
以内存 pagesize 为单位申请空间,在空间用尽之前都是 append 模式;当 append 到文件末尾时,进行文件重整、key 排重,尝试序列化保存排重结果;
排重后空间还是不够用的话,将文件扩大一倍,直到空间足够。 - 数据有效性
考虑到文件系统、操作系统都有一定的不稳定性,我们另外增加了 crc 校验,对无效数据进行甄别。
更详细的设计原理参考 MMKV 原理。
快速上手
dependencies {
implementation 'com.tencent:mmkv:1.0.23'
// replace "1.0.23" with any available version
}
MMKV的使用非常简单,
所有变更立马生效,无需调用 sync、apply。
在 App 启动时初始化 MMKV,设定 MMKV 的根目录
(默认/data/data/xxx.xxx/files/mmkv/)
(sp存储在/data/data/xxx.xxx/shared_prefs/)
支持从SP迁移数据importFromSharedPreferences
MMKV 还额外实现了一遍 SharedPreferences、SharedPreferences.Editor 这两个 interface
// 可以跟SP用法一样
SharedPreferences.Editor editor = mmkv.edit();
// 无需调用 commit()
//editor.commit();
MMKV 的使用非常简单,所有变更立马生效,无需调用 sync、apply。 在 App 启动时初始化 MMKV,设定 MMKV 的根目录(files/mmkv/),例如在 MainActivity 里:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String rootDir = MMKV.initialize(this);
System.out.println("mmkv root: " + rootDir);
//……
}
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");
使用完毕的几个方法
public native void clearAll();
// MMKV's size won't reduce after deleting key-values
// call this method after lots of deleting f you care about disk usage
// note that `clearAll` has the similar effect of `trim`
public native void trim();
// call this method if the instance is no longer needed in the near future
// any subsequent call to the instance is undefined behavior
public native void close();
// call on memory warning
// any subsequent call to the instance will load all key-values from file again
public native void clearMemoryCache();
// you don't need to call this, really, I mean it
// unless you care about out of battery
public void sync() {
sync(true);
}
性能对比
我们将 MMKV 和 SharedPreferences、SQLite 进行对比, 重复读写操作 1k 次。相关测试代码在 Android/MMKV/mmkvdemo/。结果如下图表。
单进程性能

可见,MMKV 在写入性能上远远超越 SharedPreferences & SQLite,在读取性能上也有相近或超越的表现。
多进程性能

可见,MMKV 无论是在写入性能还是在读取性能,都远远超越 MultiProcessSharedPreferences & SQLite & SQLite,
MMKV 在 Android 多进程 key-value 存储组件上是不二之选。
补充适用建议
如果使用请务必做code19版本的适配,这个在github官网有说明
依赖下面这个库,然后对19区分处理
implementation ‘com.getkeepsafe.relinker:relinker:1.3.1’
if (android.os.Build.VERSION.SDK_INT == 19) {
MMKV.initialize(relativePath, new MMKV.LibLoader() {
@Override
public void loadLibrary(String libName) {
ReLinker.loadLibrary(context, libName);
}
});
} else {
MMKV.initialize(context);
}
限制
可看到,一个键会存入多分实例,最后存入的就是最新的。
MMKV 在大部分情况下都性能强劲,key/value 的数量和长度都没有限制。
然而 MMKV 在内存里缓存了所有的 key-value,在总大小比较大的情况下(例如 100M+),App 可能会爆内存,触发重整回写时,写入速度也会变慢。
支持大文件的 MMKV 正在开发中,有望在下一个大版本发布。
问题
数据变化监听 怎么获取?
// content change notification of other process
// trigger by getXXX() or setXXX() or checkContentChangedByOuterProcess()
多进程 issue
//CallStaticVoidMethod 错误写成 CallStaticIntMethod,方法匹配crash
registerOnSharedPreferenceChangeListener not support
//官方推荐使用event方式通知更新
Data-change-listener is not supported by design.
We suggest using something like event-bus to notify any interesting clients.
Doing this inside a storage framework smells really bad.
defaultMMKV 是单进程SINGLE_PROCESS_MODE
使用MULTI_PROCESS_MODE创建多进程
带来的APK尺寸增加问题
libc++_shared.so 252.5k
libmmkv.so 43.5k
implementation ‘com.tencent:mmkv:1.0.23’
// implementation ‘com.tencent:mmkv-static:1.0.23’ (无libc++_shared.so)
只打包需要的平台对应.so
ndk {
abiFilters "armeabi-v7a", 'x86'
}
.so加载问题
implementation ‘com.getkeepsafe.relinker:relinker:1.3.1’
最后
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长。而不成体系的学习效果低效漫长且无助。时间久了,付出巨大的时间成本和努力,没有看到应有的效果,会气馁是再正常不过的。
所以学习一定要找到最适合自己的方式,有一个思路方法,不然不止浪费时间,更可能把未来发展都一起耽误了。
如果你是卡在缺少学习资源的瓶颈上,那么刚刚好我能帮到你。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
本文介绍了微信的高性能持久化框架MMKV的工作原理,包括内存映射、protobuf序列化、AES加密以及增量更新策略。MMKV在读写性能上优于SharedPreferences和SQLite,并提供了简单易用的API。文章还提及了多进程支持、内存管理和限制,并给出了适用建议及注意事项。
1万+

被折叠的 条评论
为什么被折叠?



