1.前言

 

 本文将分享一个高性能通用键值组件在iOS版微信中推广使用的技术实践过程。该组件在微信中被命名为MMKV(以下简称MMKV)。

 

 MMKV是一个基于mmap内存映射的键值组件,底层的序列化/反序列化由protobuf实现,具有高性能和强稳定性。我希望拥有高性能关键价值组件或类似技术要求的即时消息同行能够通过本文得到一些启发。

 

 最新消息:微信团队于2018年9月底正式开通了该MMKV组件。源代码地址:https://github.com/Tencent/MMKV,中文描述:https://github.com/Tencent/MMKV/blob/master/readme_cn.md

 2.从MMKV源开始

 

 在iOS微信的日常运行中,会不时出现特殊字符,这将导致iOS系统崩溃。“微信团队共享:iOS版本的微信如何防止由特殊人物引起的群体爆炸和应用崩溃?本文设计的技术方案是在关键码前后加、减计数器,通过检查计数器的异常来发现引起闪回的异常词。

 

 “微信团队共享:iOS版本的微信如何防止由特殊人物引起的群体爆炸和应用崩溃?“”中设计的技术方案的一般原则是:

 

 1)在有大量小区的地方,如通话列表和通话界面,希望新增加的定时器不会影响滑动性能;

 2)这些计数器应该永久保存——因为闪回可以随时发生。

 

 这需要一个具有非常高性能的通用键值存储组件。我们调查了一些常见的组件,如NSUserDefaults和SQLite,发现它们都不能满足如此严格的性能要求。考虑到该防崩溃方案的主要需求是实时写入,而mmap内存映射文件正好满足这一需求,我们尝试通过它实现一组键值组件。

 3.MMKV原理

 

 3.1记忆准备

 

 mmap内存映射文件提供了一个可以随时写入的内存块。应用程序只向其中写入数据,iOS负责将内存写回文件,因此无需担心崩溃导致的数据丢失。

 

 3.2数据组织

 

 在数据序列化方面,我们选择了protobuf协议,pb在性能和空间占用方面都有很好的表现。考虑到我们想要提供的是一个通用kv组件,密钥可以被限制为字符串类型,并且值是多种多样的(int/bool/double等)。)。为了通用,考虑通过protobuf协议将值序列化到统一的缓冲区中,然后将这些KV对象序列化到内存中。

 

 微信团队共享:微信高性能通用关键价值组件技术实践iOS版_1.jpeg

 

 有关Protobuf的更多文章,请参见:

 

 Protobuf通信协议详细说明:代码演示、详细原理介绍等。

 强烈建议使用Protobuf作为您的即时通讯应用程序数据传输格式

 综合评估:Protobuf的性能比JSON快五倍吗?》

 基于协议缓冲区的Java代码演示

 详细解释如何在节点中使用谷歌的原型

 

 3.3写优化

 

 标准protobuf不提供增量更新功能,每次写入都必须完整写入。

 

 考虑到主要的使用场景是频繁的写更新,我们需要增量更新的能力:

 

 序列化增量kv对象,并将其直接追加到内存末尾;

 这样,相同的键将有新的和旧的数据,而最新的数据将在最后;

 然后,当程序第一次开始打开mmkv时,只需要不断地用以后读入的值替换以前的值,这样就可以保证数据是最新的和有效的。

 

 3.4空间增长

 

 使用追加实现增量更新带来了一个新问题,即如果您继续追加,文件大小将无法控制地增长。例如,如果同一密钥不断更新,可能会消耗数百m甚至g的空间,但实际上,整个kv文件只有一个密钥,可以保存在不到1k的空间中。这显然是不可取的。

 

 我们需要在性能和空间之间做出妥协:

 

 在内存页面大小中申请空间,在空间耗尽之前处于追加模式;

 当追加到达文件末尾时,重新组织文件并键入副本,并尝试序列化和保存副本结果;

 如果在移除重载后没有足够的空间,请将文件加倍,直到有足够的空间。

 

 微信团队共享:微信高性能通用关键价值组件技术实践2.jpeg的iOS版本

 

 3.5数据有效性

 

 考虑到文件系统和操作系统的不稳定性,我们增加了crc校验来区分无效数据。在iOS微信实时网络环境中,我们观察到平均约有70w的数据验证失败。

 4.MMKV的使用

 

 4.1快速开始

 

 MMKV提供了一个可直接使用的全球示例:

 微信团队共享:微信高性能通用关键价值组件技术实践iOS版_3.jpeg

 

 可以看出,MMKV的使用相对简单。如果不同的企业需要不同的存储,您也可以单独创建自己的实例:

 微信团队共享:微信高性能通用关键价值组件技术实践iOS版_4.jpeg

 

 4.2支持的数据类型

 

 支持以下基本类型的c语言:

 bool、int32、int64、uint32、uint64、float、double

 

 支持以下对象类型:

 NSString、NSData、NSDate

 5.MMKV性能

 

 编写一个简单的测试来比较MMKV和NSUserDefaults的性能(循环编写1w倍的数据,测试环境:iPhone X 256G,iOS 11.2.6,单位:毫秒)。

 

 微信团队共享:微信高性能通用关键价值组件技术实践iOS版_5.jpeg

 

 可以看出,MMKV的性能远远优于iOS的用户默认值。此外,在测试中,发现NSUserDefaults每隔2-3次测试就会有一次耗时的操作,这被怀疑会触发数据同步和重组写入。相比之下,即使MMKV触发了数据重组,它也能保持稳定高效的性能。

 

----------------------------------------------------------------------------------

哇谷im_im即时通讯_私有云_公有云-哇谷云科技官网-JM沟通

IM下载体验 - 哇谷IM-企业云办公IM即时聊天社交系统-JM 沟通下载

IM功能与价格 - 哇谷IM-提供即时通讯IM开发-APP搭建私有化-公有云-私有化云-海外云搭建

新闻动态 - 哇谷IM-即时通讯热门动态博客聊天JM沟通APP

哇谷IM-JM沟通热门动态博客短视频娱乐生活

关于哇谷-哇谷IM-提供企业即时通讯IM开发-语音通话-APP搭建私有化-公有云-私有化云-海外云搭建

联系我们 - 哇谷IM-即时通讯IM私有化搭建提供接口与SDK及哇谷云服务

即时通讯IM融云世界

IM即时通讯钉钉技术:企业IM钉钉在后端架构上的优越之处

新的市场叫板环信、融云、腾讯云!开源版IM即使聊天工具

企业IM即时通讯聊天办公APP钉钉技术分析交流

哇谷云-怎么样正确认识海外云服务器

公有云和私有云之间有什么区别?类似融云、环信云、网易云、哇谷云?