目前涉及 1.消息表 A,2.消息发送表 B A->B 为 1 对多的关系。消息的发送使用了中间件,但统计已读未读存在性能压力。 现在的场景是,经常给 10 万用户发一条消息,然后查看哪些用户读了消息,哪些用户没有读消息。这么做 B 表的数据量会非常大,导致查询的效率非常底下,请问该如何设计,才能减少数据库压力? 目前的思路:分表。
1
rqrq 2021-03-11 11:53:00 +08:00 1
>>然后查看哪些用户读了消息
要不再建一张表,只记录查看了消息的用户 |
2
gBurnX 2021-03-11 12:04:40 +08:00 2
1.表 B 的设计思路,其实是偷懒的做法,这种思路方便一次性查出 8 辈子的消息记录,缺点就是性能差。
2.科学的高性能的设计思路应该是,发一次消息,建一个表。这样每个表里就只有十万条消息了。 3.每隔一段时间清理这些表,如果历史数据需要保存,可以直接 dump 到文件,或者放置在内存占用少的数据库实例中。 |
3
tabris17 2021-03-11 12:05:26 +08:00 1
已读和未读消息分两个表存
|
4
FucUrFrd 2021-03-11 13:57:43 +08:00 via Android 2
消息已读存 hbase,msgid:reader id
|
5
jacobsun 2021-03-11 14:06:37 +08:00 1
用 redis 记录发送的消息, 两个集合搞定. 一个记录发送的用户 ID 一个记录已读的用户 ID 然后去差集就好
已读未读的状态在前端的消息列表控制 |
6
Simle100 OP 大佬们有没有做过这样的需求?
|
7
teddy2725 2021-03-11 14:52:17 +08:00
把已读事件写到一个流里面,用 flink 做实时统计
|
8
wennew 2021-03-11 14:59:38 +08:00
我用的 redisSET 记录消息的用户状态,然后定时备份到 mysql,缺点很多,但是只要 redis 不挂勉强能应付
|
9
soulzz 2021-03-11 15:23:46 +08:00
放客户端 sql 库啊
|
10
soulzz 2021-03-11 15:41:38 +08:00
服务端可以这样做:消息发送后保存消息 id 和发送时的时间戳在内存中
半小时内在内存中用布隆过滤器处理客户端发过来的数据区分已读未读,写一个定时 对超过半小时的消息 id 入库处理(或者用消息队列异步合并写)。 客户端的已读未读就放在客户端的库一条条处理 |
11
labulaka521 2021-03-11 15:46:13 +08:00
插个眼 目前也有类似的需求
|
12
iceteacover 2021-03-11 15:53:49 +08:00
mark,感觉不同数量级的消息 会有不同的设计实践。
|
13
sujin190 2021-03-11 15:54:27 +08:00
|
14
sujin190 2021-03-11 15:57:56 +08:00
如果你觉得直接用 hashmap 太耗内存,那么就在发消息式给个再当前消息内部有效的自增 ID,redis 这边就能用 bitmap 来存是否已读了啊,查的时候直接取出哪些位置没读,然后结合消息 ID 就直接能查除用户了,这个应该式最省内存也不是很消耗性能的方式了吧
|
15
x537196 2021-03-11 16:16:18 +08:00
做了一套类似的,不过没有明细需求,只统计发送数、已读数
|
16
wennew 2021-03-11 18:00:11 +08:00
@sujin190 hashmap 加过期时间还是变成 redis 了呀, 而且这东西确实可以用 nosql 冗余存储,mysql 这种确实不好使啊
|
17
sujin190 2021-03-11 18:18:01 +08:00
@wennew #16 我的意思用 redis 的 set 数据结构比用 redis 的 hashmap 数据结构操作复杂,都是 redis 。。
|
18
aguesuka 2021-03-12 11:05:14 +08:00 via Android
才十万,直接存数据库建好索引分区肯定没问题。
|