公司要开发运营聊天功能,估计用户 10w 左右,在线 1w 人,消息每天 100w 以上,需要存储 6 个月左右的消息,差不多 2 亿条,而且考虑到不同终端之间的消息同步,客户端需要频繁的查询聊天数据。 请问针对这样的场景应该选择哪种数据库? 目前考虑 Mongodb 或 Clickhouse ;考虑 mongodb 主要是 mongodb 的分片模式适合存储大量数据、查询也比较快,考虑 clickhouse 主要是其能存储大数据并且查询性能也比较好(但是听说并发不太好,不知道是否适合并发查询要求)。
1
liuhan907 2022-09-29 10:09:26 +08:00 via Android
要查询聊天这种东西,第一反应应该是 es 吧。
|
2
Smilencer 2022-09-29 10:11:51 +08:00
学微信,聊天记录全部 sqllite 存在客户端本地,查询全部在本地
|
3
superbai 2022-09-29 10:12:10 +08:00
有没有考虑过直接用云服务厂商提供的 IM 功能
|
6
coderxy 2022-09-29 10:22:33 +08:00
2 亿条不算多,mongodb 的分片集群可以搞定。 如果量再大,可以考虑 hbase 这一类的分布式数据库,我们用 hbase 存的,一天都不止 1 亿条,稳得很。
|
7
tramm 2022-09-29 10:25:21 +08:00
查询的话都是查本地的吧.
|
8
monkeydream OP @Smilencer 主要是要考虑消息同步,不同终端之间要保证消息一致性,还有离线消息存储,所以消息必须存在服务器。本地查询会存在 Sqlite 中。
|
9
julyclyde 2022-09-29 10:31:25 +08:00
首先 10w 用户就不可能,想多了
|
10
monkeydream OP @coderxy 因为需要走消息同步,获取用户最近消息这个操作也很频繁;不知道 Mongodb 和 Hbase 针对这种并发查询的性能咋样?
|
11
awanganddong 2022-09-29 10:34:28 +08:00
热数据放 redis, 冷数据存 mysql ,定时归档。一般查询的话,都是查本地,如果想实现云端检索类似功能,直接异步走一份到 es 。
推荐个网站 http://www.52im.net/ 即时通讯网 im 这块是天坑。单纯存储的不复杂。 |
12
monkeydream OP @awanganddong 多谢。
|
13
tairan2006 2022-09-29 10:36:23 +08:00
你要做线上查询的话,肯定推荐 es 吧。
不然的话推荐用时序数据库,或者 hbase 这些方案也能用。 |
14
coderxy 2022-09-29 10:37:26 +08:00
@monkeydream 我们是仿照钉钉走的拉模式,全部都是走数据库,反正 hbase 稳得很(请求量大了或者数据量大了都会自动分片)。mongodb 的话,如果你用分片集群,提前做好压测,应该也没啥问题。
|
15
masterclock 2022-09-29 10:41:08 +08:00
公司有 10 万人?买一套不好吗?为啥要浪费时间开发?
|
16
monkeydream OP @coderxy 多谢;那我们估计优先考虑 mongodb ,因为目前项目中已经有些应用在尝试使用 mongodb 数据库。
|
17
monkeydream OP @masterclock IM 聊天是我们 SAAS 产品的一部分;不只是我们公司自己用。
|
18
coderxy 2022-09-29 10:45:19 +08:00
@monkeydream 可以的,符合自己需求的才是最好的。 毕竟 hbase 这一类数据库用的人少,维护起来也比较麻烦。IM 领域真正麻烦的是超大群,其它都还好。
|
19
coderxy 2022-09-29 10:45:50 +08:00
@masterclock 第三方的各种限制,而且也不便宜。 有能力的话自研一下其实成本不高的。
|
20
monkeydream OP @tairan2006 ES 可以考虑下;时序数据库没接触过,不太敢用。
|
21
di1012 2022-09-29 10:48:42 +08:00
要不试试时序数据库?
|
22
onlyhuiyi 2022-09-29 10:48:45 +08:00
为什么要用 mongo 呢,我们公司 mongo 都不再支持新的接入了
|
23
monkeydream OP @di1012 你们实际项目生产上有使用过吗?我们没接触过这块,怕坑太多。
|
24
monkeydream OP @onlyhuiyi 为啥不接入了? mongo 写入查询效率还可以吧?这么多年了也比较成熟,也可以进行分片存储大数据。比存 mysql 肯定要强不少吧。
|
25
Singular 2022-09-29 11:01:29 +08:00
System Design 的书介绍设计 Facebook Messenger 用的是 Hbase 这类宽表存储 DB
F.Y.I.: https://akshay-iyangar.github.io/system-design/grokking-system-design/system-design-problems/facebook-messenger.html |
26
wxf666 2022-09-29 11:02:20 +08:00
@monkeydream 3 天前的 [这个帖子]( https://www.v2ex.com/t/882773 ) 里,有很多人反映,MySQL 单表存 1~2 亿(#11 楼 #16 #18 #19 #21 #35 )、4 亿(#27 )、10 亿(#35 )、20 亿(#28 )都没问题诶,查询也很快(几十 ms ,#27 #28 )
MySQL 真的不行吗? |
27
liuhan907 2022-09-29 11:12:46 +08:00
@monkeydream 聊天数据,你要搜索要全文搜索,除了 ES 你还想自己实现倒排索引?
|
28
monkeydream OP @wxf666 主要考虑不仅仅是数据量存的问题,还有并发读。最终还是要做个压测对比下。
|
29
b123405060 2022-09-29 11:13:19 +08:00
@wxf666 mysql 单表一般不超过 500w, 单表上亿的数据? mysql 这么强大吗
|
30
monkeydream OP @liuhan907 不是全文检索,是多端数据同步,要实现消息拉取。
|
31
joesonw 2022-09-29 11:15:29 +08:00 via iPhone 1
时序是存数字的,每条记录存的是差值来优化空间和统计。聊天记录这种文本的完全和时序没半毛钱关系。一般查询是本地的,服务器只是留档不检索的话,按时间存对象存储就好了。用户同步到本地 sqlite 再查询。
|
32
Yada 2022-09-29 11:17:10 +08:00 1
某办公 IM 大厂早期用的是 mysql 写扩散。 后面量大了。就扛不住了。 架构升级成 类 Hbase 的 OTS ( tableStore ) IM 业务核心特性之一是,基本上很少修改数据(撤回,删除等)。另外要核心关注一下 读写扩散模型的问题。 大群治理。 现代的 IM 都不是单纯的读扩散或者写扩散了。
MongoDB 不太建议。MongoDB 最贴合的应该是数据 schema 多变的这种业务类型 。IM 业务的表基本不会有啥变化。不适合。clickHouse 不了解。 |
33
realrojeralone 2022-09-29 11:17:43 +08:00
|
34
pengtdyd 2022-09-29 11:22:30 +08:00
就没人推荐 postgresql 吗?
首先是场景:聊天记录需要频繁查询吗?拿微信来说,本地先有一份,同时同步多端消息,但是需要发送查询到服务器本身并不是一个高频的场景,聊天应用本地需要一个数据库,查询不到本地或者轮询同步的时候才需要和服务器进行交互。 |
35
lmshl 2022-09-29 11:22:51 +08:00 1
聊天场景的话,主要是写多读少,几乎不修改,而且顺序性明显
那我推荐 Cassandra ,以 Channel/Group 为 partition key ,timeuuid 为 clustering key ,写入每 key 几万且支持水平线性扩展,以 partition key 读取也是顺序读,速度不需要担心。 |
36
wxf666 2022-09-29 11:25:20 +08:00
@b123405060 超过 500w 会怎样? B+ 树从 3 层 变为 4 层?
然后由于内存只能完整缓存前两层(前两层代价是 20~30 MB 内存,前三层代价是 20~30 GB ),所以 3 层变为 4 层,会导致实际 IO 由 1 次 变为 2 次,即速度下降 50%? 还是怎么个逻辑? 数据库新人,求指教 |
37
lmshl 2022-09-29 11:28:44 +08:00
接 #35 Cassandra 还支持过期时间 (TTL).
你想存储几个月就存储几个月,过期后不需要手动清理 |
38
wxf666 2022-09-29 11:30:03 +08:00
|
39
demon1991yl 2022-09-29 11:31:24 +08:00
mongodb 吧,我们的私信、im 消息目前都是存在 monodb 里面的,规模都是上百亿条,而且根据楼主的描述,数据量 2 亿不算多,存 mongo 的话,也方便后续扩展,,而且基本也是一些在线索引查询。ES 、CK 等对于 TP 类业务实时性不一定能保证
|
40
demon1991yl 2022-09-29 11:32:42 +08:00
@onlyhuiyi 为啥不接 mongodb 了呢,我们挺多业务再用,还有很多 mysql 转过来的呢
|
41
fengjianxinghun 2022-09-29 11:37:33 +08:00
实时查询用 ES ?都是 ppt 架构师?
|
42
fengjianxinghun 2022-09-29 11:38:00 +08:00
@fengjianxinghun 还是都是个位数并发?
|
43
hahasong 2022-09-29 11:43:27 +08:00
肯定用 hbase 我之前就做过这个。消息都是时序写入,hbase 轻松无压力。只有硬盘到位,永久存都行
|
44
microxiaoxiao 2022-09-29 11:47:07 +08:00 via Android
2 亿条消息也不大吧,直接存内存相关的数据库吧。持久化随便选一个。200000000*1k/1024/1024/1024=190GB 。图片,视频另外存
|
45
tt67wq 2022-09-29 11:51:05 +08:00
热 tidb + 冷 hbase
|
46
helloxiaofan 2022-09-29 12:01:12 +08:00 via iPhone
MySQL 不行吗,我们之前每天 400w 左右,可以分库分表
|
47
shot 2022-09-29 12:25:50 +08:00 6
建议参考头部玩家的技术选型,比如 Discord 的数据库迁移历程:MongoDB → Cassandra → ScyllaDB
《 How Discord Stores Billions of Messages 》 > In July, we announced 40 million messages a day, in December we announced 100 million, and as of this blog post we are well past 120 million. > The messages were stored in a MongoDB ……, we reached 100 million stored messages and…… see the expected issues appearing: the data and the index could no longer fit in RAM and latencies started to become unpredictable. https://discord.com/blog/how-discord-stores-billions-of-messages 《 Discord Chooses ScyllaDB as Its Core Storage Layer 》 https://www.scylladb.com/press-release/discord-chooses-scylla-core-storage-layer/ |
48
cp19890714 2022-09-29 12:37:57 +08:00 1
首先排除 clickhouse 。clickhouse 主要用于 OLAP ,不适合 OLTP 。并发能力很弱,不适合你的场景。
mongodb 分片、写入并发、数据压缩、数据过期自动清理 都挺适合你的场景。数据量 2 亿真不多。 ES 我只是简单使用过,没有太多了解。不过,实时查询好像不是太快,而且服务器成本比 mongodb 高。 |
49
cp19890714 2022-09-29 12:39:22 +08:00
@cp19890714
不过,如果要做聊天记录查询,那么全文索引又必然是用 ES 了 |
50
defage 2022-09-29 13:01:28 +08:00
clickhouse 肯定是不合适的,这种端上的场景不是 clickhouse 的场景。
数据量级一大,要考虑综合做法,不一定是单个存储。 比如 db 分表+hbase 存详情,用户维度的列表从 db 查,详情回表用 hbase 构建出来。 |
51
liuhan907 2022-09-29 13:12:09 +08:00
@monkeydream 所以你是要做 IM 消息存储和消息本身的检索?那这个 2E 的量基本随便了吧,拿个 pgsql 硬件规格拉高一些单机大概都够。不放心就找一个分布式数据库一把梭。
|
52
guanhui07 2022-09-29 13:38:11 +08:00 via iPhone
tidb
polardb |
53
NoString 2022-09-29 13:40:06 +08:00
hbase
上 clickhouse 不可能的,你可以试试 ck 对并发支持。聊天记录你查详情又不聚合去重计算,选他干啥 |
54
lmmlwen 2022-09-29 13:50:26 +08:00
hbase 这些没现成的就没必要,毕竟你一天也就 100w ,只存 6 个月
|
55
wellsc 2022-09-29 13:58:58 +08:00
映射存就行了,kv 存消息尸体和 id ,量不大
|
56
dog82 2022-09-29 13:59:19 +08:00
IM 要做好非常难,存储只是难点之一
有条件的就买吧,腾讯云、网易云都有 IM 产品 |
57
yty2012g 2022-09-29 14:05:11 +08:00
CK 不太 ok ,ck 是 OLAP 引擎,QPS 不能太高,而且关联性能不太行。
第一想法是 ES |
59
wxf666 2022-09-29 15:15:59 +08:00
@monkeydream 我大概算算 MySQL 单表,受限于 IO 的读并发吧:
假设: - B+ 树 4 层 *(若 InnoDB 、Dynamic 、16 KB 每页、8 字节主键、1 KB 一条消息,可容纳 110 亿)* - 缓存前两层 *( 14 MB 内存代价)* - 有 `(uid 4 字节, time 5 字节)` 索引 - 每个用户每次获取不超过 700 条消息 *(此时索引只需读一个叶节点)* - **不缓存实际消息** *(就当所有用户都在获取历史消息吧。因为每个叶节点可能存着 15 个不同用户的消息,太散了,不会算『每次一个用户获取一堆消息时,能利用上多少缓存』,直接按最差情况算)* 设每秒有 x 人请求,平均每人有 y 条消息要获取,硬盘有 z 个 16 KB 的 IOPS ,那么: 2x (每人消耗 2 次 IO 去索引读取自某个时间以来的消息 ID 列表) + 2xy (每条消息都要 2 次 IO 去消息表读取) <= z 如,我的垃圾固态,16 KB 有 25000 IOPS (也就 400 多 MB/s )。那么: 每秒 100 人要获取消息时,平均每人能得到(不在缓存中的) 124 条历史消息? (数据库新手,算的不对,恳请指出) |
60
la2la 2022-09-29 15:29:00 +08:00
不考虑时序数据库么,本地缓存加线上时序数据库持久化。理论上线上存储的消息应该是加密的的吧?
|
61
paouke 2022-09-29 15:34:33 +08:00
公司有搭好的 hbase 就用 hbase ,没有用 mysql ,mongo 也能撑得住,ck 肯定是不太行,ES 用来全文索引还行,主存储不太行吧
|
62
aitaii 2022-09-29 16:21:26 +08:00
clickhouse 1000 个并发撑死了
|
63
ThinkCat 2022-09-29 17:02:01 +08:00
前公司用的是 mysql ,后面数据量实在过大,用了阿里的 OTS ,但是这个东西太贵了。IM 的热数据不多的话,可以用 mysql ,做好分表和冷热隔离。其实最好的,是楼上讲的时序数据库,较适合 IM 特性,不过这个没用过。
|
64
binge921 2022-09-29 17:21:46 +08:00
查询肯定 es 存储肯定 hbase
|
65
flycloud 2022-09-29 17:31:27 +08:00
说用 ES 的真是人才,还全文索引。。。
“客户端需要频繁的查询聊天数据” 意思是用户需要拉取和其他用户会话的聊天消息,而不是去全文索引查询某个关键字。 mongodb shard 再适合不过了,设计好 shard key ,保证两个用户之间的会话消息落入某一个分片中,不同的会话消息均匀分布到各个分片。比如 {sessionId: "hashed", msgId: 1},如果有群聊天也是一样的,分配一个 sessionId ,msgId 递增,以支持按会话批量按序拉取消息。 再设置一个字段自动过期删除。 |
67
flycloud 2022-09-29 17:39:42 +08:00
“频繁的查询聊天数据”
其实很多是无效请求,根本没有新增消息,可以在 redis 中设置标记,真正有新消息时才去读取 DB ,可以很大成都降低 DB 压力。 |
68
podel 2022-09-29 17:46:03 +08:00
不如所有的消息都是日志 /FILE 。以时间递增序列进行保存。
服务器只存储。 所有消息查询功能都要根据时间戳,从服务器下载下来 SYNC 后。在本地进行计算。比如说搜索之类的。 (服务器只承担存储功能,不承担任何查询功能) |
69
flycloud 2022-09-29 17:47:23 +08:00
@Huelse 是有这种需求,但是注意审题啊,是客户端查询。
第一种:本地有存储消息,直接客户端本地搜索啊。 第二种:客户端本地不存储消息,应该是没有什么 IM 应用会在所有会话中查询某个关键字吧,而是在某个会话里查询,直接拉取某个会话的历史消息来搜索,不就可以了? 当然也会有在后台查询关键字的情况,多半也是会指定某两个用户之间消息查询。 实在想不出来在所有用户的所有会话里查询关键字这种需求的意义,所以觉得 ES 没有适用场景。 |
70
playtomandjerry 2022-09-29 17:55:20 +08:00
@Smilencer 也信
|
71
jitongxi 2022-09-29 19:02:39 +08:00
说 es 的确实扯淡的,es 的缓存对于非公用的内容查询, 缓存空间估计就炸裂了。
查询确实只是给客户端做的事,服务端只负责存储。 |
72
sunmacarenas 2022-09-29 19:24:32 +08:00 via Android
公司有钱就上 SAP HANA
|
73
hopingtop 2022-09-29 20:39:50 +08:00
1.如果在都能满足功能的情况下,一定要选择团队熟悉的!!!
2.这里 2 亿数据确实不多,而且也不用依赖 mongodb 本身的分片,可依据时间自行管理分片,这样在扩容很有优势 3.mongodb 在查询方面性能还是很不错的,你的查询场景一般还带有时间限制。 4.楼上也说了参考 头部 ,Discord 当初在 2015 年就选择了 mongodb ,(2022 年的 mongodb 更强大了) 为什么不选择其他?当你数据量真的到达扛不住的量级了,我想肯定是很赚钱的了,这个时候人手和资源又不一样了!很多事情本就不可一步到位。 5.需要频繁查询聊天数据,这个需求一般只是 存在运营这个角色, 如果真到 DB 性能不够,那么你完全可以经过角色同步数据的概念到本地进行查询,然后,如果有必要再去服务器去获取上下文。 |
75
zmzeng12 2022-09-29 21:19:14 +08:00
写多读少,又不涉及修改消息。
数量不大用 SQLite ,数量大用 RocksDB 。 RocksDB 的话,服务器存全量 sstable 作为 single of truth ,客户端按需拉取查询时间范围内的 sstable 文件,Client 本地完成查询。 |
76
remember5 2022-09-29 22:12:44 +08:00
个人猜测,本地查询 sqllite + 后台 hbase
|
77
changdy 2022-09-29 22:59:51 +08:00
clickhouse 去掉 .不是干这个的
其次 时序数据库 了解的不多 .但是 也比较赞同 @joesonw 的说法 es 我觉得有几个问题吧.基于分词,无法保证查询结果 数据难分表. 不分表冷热数据混在一起也有点小问题. 感觉 im 这个场景还是挺大的 ,最好还是和产品一起商量下如何优化 使用体验. |
78
documentzhangx66 2022-09-29 23:08:05 +08:00 1
淘宝这么多年现成的方案,都不用?
直接按用户进行分库。 首先按用户热度,分为冷热用户集群。 热集群高配置,大内存,SSD 。冷集群低配置,小内存,HDD 。 每个集群由一大堆 Mysql 节点组成,每个 Mysql 节点负责一部分用户。节点散列策略按用户 IO 数量来进行负载均衡。 这样实现了几个好处: 1.对于一个用户,所有数据集中在一台 Mysql 里。 2.实现了基于性价比的冷热数据分离。 3.如果一些 Mysql 节点坏了,只会影响一小部分用户,不会影响整体业务。 4.如果一些用户的冷热度发生变化,方便做自动迁移。 5.每个 Mysql 节点的数据量小,能够支持 LIKE 进行高精度搜索。 |
79
djoiwhud 2022-09-29 23:39:50 +08:00 via Android
@monkeydream #30 。你的需求选 mysql 或者 pg 就可以了。
热数据放 redis 里面。 实在想折腾新方案,想永久保存聊天记录,考虑 hbase 或者 hive 。本人做过 IM 类的需求产品,我负责的说,这个需求用 es 是个错误。 |
80
akira 2022-09-30 00:14:34 +08:00
凡是发帖问方案的 ,一律推荐 用 三方的,例如腾讯的聊天服务 .
光是在线 1w 人这个事情 估计你们就已经要头大了。。 |
81
QlanQ 2022-09-30 08:50:58 +08:00
为啥还有推荐 es 的,这个量级用 es 做储存,会是什么价位的?
这个场景写入也很多,es 不合适吧 |
82
Asimov01 2022-09-30 09:32:02 +08:00
其他我不知道,这种需求别用 Clickhouse ,Clickhouse 设计目标就是做小规模并发,超大数据量且没有固定查询模式的快速即席分析,不适合做这种业务。
|
83
wqhui 2022-09-30 11:34:08 +08:00
mongo 挺合适做聊天数据存储的,全文查询什么的确实比不上 es ,但感觉 2 亿数据问题也不大,还可以建个时间索引自动把旧数据删掉,es 很少见到用来保存源数据的,一般都是从数据库存储然后同步到 es 。clickhouse 设计目标是拿来做数据分析不合适
|
84
onlyhuiyi 2022-09-30 18:11:37 +08:00
@monkeydream 我也不知道为啥,提申请页面都写着不再接新的实例了。应该是内部用的少吧,不想浪费人力去维护这部分了,主要还是用 mysql ,ES ,redis 等,最近越来越多用 clickhouse 。接触的系统很少用 mongo 。
|
85
onlyhuiyi 2022-09-30 18:13:15 +08:00
@demon1991yl 我也不知道为啥,用的人少,不值得安排人来维护吧。
|
87
AnLuoRidge 2022-10-01 19:03:00 +08:00
@Singular 这个附的链接 404 了
|
88
AnLuoRidge 2022-10-01 19:05:35 +08:00
|