聊天软件是如何存储聊天记录的?

聊天软件是如何存储聊天记录的?

🤔 聊天软件是如何存储聊天记录的?

假如让你想个办法保存聊天记录的话,你会怎么保存呢?

最简单的,向下面这样。

当然,问题也是显而易见的。

效率低,由于聊天消息是后延展的,写入并不存在太大的瓶颈;但查询起来,需要将整个文件完整读入,再按行分割,再识别是发送的消息还是接收的消息,渲染到屏幕上。并且,聊天记录的读取还是个高频的操作,使用这种策略,确实低效。

不安全,明文存储。

扩展性差,比如收到了一个表情包,要怎么存储?

Untitled/Untitled%201.png

更加常见的方法是使用数据库来保存聊天记录。

数据库的结构比较像 Excel ,一个 xls 文件中可以有许多 Sheet

同样的,一个数据库 Database 中,也可以有许多表 Table

每个表中有固定的表头 (或者叫模式, Schema),以及若干行的数据(称之为 记录 Record )。

模式固定的,称之为关系型数据库。在服务器上,比较常见的数据库有 MySQL, PostgreSQL 等。但在移动端上,最广泛使用的、名气最大的是 SQLite,这个软件还是开源的 👏

区别于 MySQL 等大型数据库使用的 CS ( Client-Server ) 架构模式,SQLite 需要嵌入到应用程序的进程当中,因此也被称为嵌入式数据库。这两者的区别是,前者至少需要两个进程,一个进程扮演数据库服务端的角色,另一个进程扮演客户端的角色;而后者,只有一个进程,两种角色合二为一。

我们平时网上冲浪,应用的就是 CS 架构模式。运行在电脑上的浏览器即客户端进程,而网站的服务器上运行的程序,便是服务端进程。

下面以我国最广泛使用的聊天软件为例。

IOS

经过一番操作,把手机聊天软件中的数据复制了出来,竟然没加密。要知道,我可是耗费了很长时间,才解密了安卓版微信数据库。

可能是大家公认苹果的沙箱机制比较安全,所以不加密也无妨。不过我提取上述文件时,并没有对IPhone 进行越狱操作。不过大家放心,如果不解锁 IPhone,什么都做不了,苹果手机依旧安全。

Untitled/Untitled%202.png

比较容易看到,这里有许多的数据库文件,这个叫做分库

打开 MM.sqlite 数据库,发现许多 Chat_*** 的表,他们拥有一样的表结构,这个叫做分表

Untitled/Untitled%203.png

Untitled/Untitled%204.png

得出结果,IOS版微信客户端做了分库和分表。

为什么要分库?

为了提高性能和稳定性。

众所周知,数据库可以提供跨表关联查询 ( JOIN ),其事务特性保证了跨表写入的原子性、一致性、隔离性和持久性。

但如果两个表之间,毫无关联的话,比如聊天记录和新闻,既不需要跨表查询,也不需要跨表事务。

并且如果这俩个表都存在高频的读写操作的话,显而易见,放弃上述特性,分成两个库,会获得更好的效率。

即便 SQLite 的锁粒度是表级的,但这并不妨碍分库带来的性能提升。

除了提高效率,还能提高稳定性。分库后,这两个数据库相互独立,互不干扰,降低数据库出错的风险。

为什么要分表?

为了提高性能。

有得便有失,分表后,又会失去些什么?

唯一约束。在设计数据库表模式时,针对用户ID、用户邮箱等列,大多数人往往都会在该列上增加唯一性约束,即一个账户系统中,不能有重名的用户。分表后,数据库便无法提供这种保证,因为跨表了。

维护性。分表后,需要动态创建表、创建索引,如果再将 Migration 考虑在内的话,系统复杂度陡升。

系统设计是个权衡利弊的过程,有得有失,取决于更加看重哪些特性了。

语音消息是怎么存储的?

Untitled/Untitled%205.png

语音消息的存储很枯燥,似乎和咱最初的设计有异曲同工之妙,每段语音是一个 aud 文件,如果曾使用了语音转文字功能,会用一个 txt 文件保存转换完的内容。

到了安卓手机了

第一步,解锁 BootLoader。

第二步,获得 root 权限。

第三步,把数据文件复制出来。

第四步,解密数据库文件。

第五步,解密失败,使用新的密钥,重新进行第四步。

第六步,…..

Untitled/Untitled%206.png

安卓版跟 IOS 版差异还是比较大的

  • 安卓版数据库是加密存储的
  • 目录结构、数据库结构、表结构不是一样的

相似之处也很多

  • 同样都是使用 SQLite 数据库
  • 同样都是使用 WAL 模式
  • 同样都是使用 FTS 做的全文搜索索引

加密 —— SQLCipher

SQLCipher 是 SQLite 的一个插件,用于提供数据库加密功能,也是开源的 👏

那么要如何使用呢?

当我们尝试访问一个加密过的数据库的时候,发现并不难使用。

Untitled/Untitled%207.png

这时我们需要输入密码 (key),和加密方式。

Untitled/Untitled%208.png

之后就可以愉快的使用了 👏

那么 key 是什么呢?互联网告诉我们👇

key = md5(imei + uin)[:7]

关于加密的原理和这些参数都代表着什么,我不知道。

附上部分安卓端数据库的模式定义👇

Untitled/Untitled%209.png

到这里这篇文字就结束了,有没有感觉又增加了一些奇怪的知识。

全文索引,想必大家都听说过鼎鼎大名的 ElasticSearch。对于 Sqlite 这种嵌入式数据库来说,FTS 这个插件,提供了还算可以的全文搜索功能支持。

参考资料:

Comments

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×