目前涉及 1.消息表 A,2.消息发送表 B A->B 为 1 对多的关系。消息的发送使用了中间件,但统计已读未读存在性能压力。 现在的场景是,经常给 10 万用户发一条消息,然后查看哪些用户读了消息,哪些用户没有读消息。这么做 B 表的数据量会非常大,导致查询的效率非常底下,请问该如何设计,才能减少数据库压力? 目前的思路:分表。
目前涉及 1.消息表 A,2.消息发送表 B A->B 为 1 对多的关系。消息的发送使用了中间件,但统计已读未读存在性能压力。 现在的场景是,经常给 10 万用户发一条消息,然后查看哪些用户读了消息,哪些用户没有读消息。这么做 B 表的数据量会非常大,导致查询的效率非常底下,请问该如何设计,才能减少数据库压力? 目前的思路:分表。
|
1
>>然后查看哪些用户读了消息
要不再建一张表,只记录查看了消息的用户 |
|
2
1.表 B 的设计思路,其实是偷懒的做法,这种思路方便一次性查出 8 辈子的消息记录,缺点就是性能差。
2.科学的高性能的设计思路应该是,发一次消息,建一个表。这样每个表里就只有十万条消息了。 3.每隔一段时间清理这些表,如果历史数据需要保存,可以直接 dump 到文件,或者放置在内存占用少的数据库实例中。 |
|
3
已读和未读消息分两个表存
|
|
4
消息已读存 hbase,msgid:reader id
|
|
5
用 redis 记录发送的消息, 两个集合搞定. 一个记录发送的用户 ID 一个记录已读的用户 ID 然后去差集就好
已读未读的状态在前端的消息列表控制 |
|
6
大佬们有没有做过这样的需求?
|
|
teddy2725Mar 11, 2021
7
把已读事件写到一个流里面,用 flink 做实时统计
|
|
wennewMar 11, 2021
8
我用的 redisSET 记录消息的用户状态,然后定时备份到 mysql,缺点很多,但是只要 redis 不挂勉强能应付
|
|
soulzzMar 11, 2021
9
放客户端 sql 库啊
|
|
soulzzMar 11, 2021
10
服务端可以这样做:消息发送后保存消息 id 和发送时的时间戳在内存中
半小时内在内存中用布隆过滤器处理客户端发过来的数据区分已读未读,写一个定时 对超过半小时的消息 id 入库处理(或者用消息队列异步合并写)。 客户端的已读未读就放在客户端的库一条条处理 |
|
labulaka521Mar 11, 2021
11
插个眼 目前也有类似的需求
|
|
iceteacoverMar 11, 2021
12
mark,感觉不同数量级的消息 会有不同的设计实践。
|
|
sujin190Mar 11, 2021
13
|
|
sujin190Mar 11, 2021
14
如果你觉得直接用 hashmap 太耗内存,那么就在发消息式给个再当前消息内部有效的自增 ID,redis 这边就能用 bitmap 来存是否已读了啊,查的时候直接取出哪些位置没读,然后结合消息 ID 就直接能查除用户了,这个应该式最省内存也不是很消耗性能的方式了吧
|
|
nimonewMar 11, 2021
15
做了一套类似的,不过没有明细需求,只统计发送数、已读数
|
|
aguesukaMar 12, 2021 via Android
18
才十万,直接存数据库建好索引分区肯定没问题。
|