随着我们IM服务规模的迅速扩张,原有基于PostgreSQL(PG)的数据库架构已难以满足日益增长的性能需求。PG的事务特性在IM系统中鲜少发挥作用,而面对海量数据的高效存储与快速访问,传统的关系型数据库渐渐力不从心。分库分表虽可提升性能,但其复杂性与成本令人望而却步。SO,更换存储组件就势在必行了。
技术选型流程优化建议
- 需求分析:明确业务预期,预估未来三年数据量级。
- 市场调研:寻找符合需求的成熟组件。
- 稳定性优先:选择有使用经验的技术组件,避免追求“最新”而引入不必要的风险,不会有人想在周末加班的。
- 经验借鉴:参考业界最佳实践,避免重复发明轮子,确保问题解决路径清晰。
IM消息的核心特征
- 海量数据:每日消息量级可达百万乃至百亿,对存储系统的扩展性和效率提出极高要求。
- 高频写入:用户间的实时交互促使数据库需处理高并发写入,确保消息的即时性及顺序性。
- 低延迟体验:实时性是IM服务的生命线,系统需保证消息传输的即时响应。
- 数据时效性:用户关注焦点在于最新消息,系统应优化对近期数据的访问。
- 消息排序:保持消息的时间顺序至关重要,确保用户对话的连贯性。
- 消息持久化:即使面临网络或硬件故障,消息仍需安全存储,保障服务连续性。
业务场景分析
- 实时推送:消息实时推送至客户端,强调即时通信的无缝体验。
- 群聊互动:群聊场景下,用户仅关注最近消息,写入频次与群活跃度成正比。
- 私聊回顾:私聊用户不频繁查询历史记录,写入需求显著高于读取。
数据库选择考量
目前我们常用的数据库包括,PGSQL/MYSQL等关系型数据库,MongoDB/Cassandra 等非关系形数据库,为什么我只列举了这么几个,因为部门现在用的就这些。要用新组件,0经验的话感觉距离出线上事故不远了
继续使用使用关系型数据库
直接单机储存
查询和写入的QPS就已经限制死了,此方案抛弃。
集群储存+分库分表(根据日期,比如按周分表)
水平扩展比较难,整个数据集群的运维有很高的要求,总之是不能直接开箱即用的,需要二次开发和高运维需求,这种上线了就等oncall吧,肯定不会少的。
使用非关系形数据库
NoSql数据库 Mongo 和Cassandra(ScyllaDB)同为NoSql数据库 这个2者都是可以水平扩展的,在存储量级上是没有问题的
Mongo和Cassandra比较大的一个区别是2者的存储引擎不同,这里小小解释下
Mongo VS Cassandra
MongoDB是B+树,而Cassandra是LSM树
LSM树(Log-Structured Merge Tree)和B+树是两种不同的数据结构,它们各自针对不同的性能需求进行了优化,主要区别如下:
-
B+树:
- B+树是一种自平衡的树数据结构,所有的数据记录都存储在叶子节点上,非叶子节点仅存储索引信息。
- B+树的节点可以包含多个键值对,每个节点之间的链接使得范围查询和顺序访问非常高效。
- 它们是高度优化的,用于最小化磁盘I/O操作次数,因为磁盘I/O是昂贵的操作。
- B+树在写入时需要保持树的平衡,可能涉及较频繁的磁盘I/O,尤其是当树需要分裂或合并节点时。
- B+树在读取性能上通常较为稳定,因为它能够提供较快的随机访问。
-
LSM树:
- LSM树不是一个单一的数据结构,而是一种设计理念,它通常包括内存中的数据结构(如跳跃表或B+树)和磁盘上的SSTable(Sorted String Table)文件。
- 数据首先被写入内存中的数据结构,然后定期批量写入到磁盘上的SSTable文件中。
- 当SSTable文件增长到一定大小时,会触发合并过程,将多个SSTable合并成一个新的更大的文件,这个过程称为compaction。
- LSM树在写入性能上通常优于B+树,因为它可以批量写入数据,减少磁盘的随机写入,而磁盘随机写入是I/O的瓶颈。
- LSM树在读取时可能需要访问多个SSTable文件,导致读放大(read amplification),但通过缓存和索引可以缓解这个问问题
二者对比,我们就能看出来Casandra是更符合我们需求的,为什么不用ScyllaDB?因为我们目前只有Cassandra的运维经验,现在集群里面跑的也是Cassandra,如果你是从0开始,建议直接使用ScyllaDB
Casandra 如何建表,如何设置更符合我们需求的索引?
太阳底下没有新鲜事,要铭记百分之99的技术需求都是前辈们做过的,我们search下Casandra储存消息有没有什么成熟的方案,走别人走过的路,至少不会碰到啥大问题,OK一下就搜出来了How Discord Stores Trillions of Messages
Discord之前的方案用Casandra存储了万亿级别的数据量,我们这边未来到达百亿级已经是绰绰有余了,我看了下他们万亿级消息换到ScyllaDB,没有遇到啥问题,我们大概到百亿级别,就会尝试切ScyllaDB了。
遵循前人的经验,我们快速完成了技术选型与迁移,确保业务平稳过渡。大概一个下午我们就完成了技术选型,在一个迭代中就迁移到了Casandra