群发消息已读未读如何设计才能降低数据库的压力

2021-03-11 11:40:11 +08:00
 Simle100

目前涉及 1.消息表 A,2.消息发送表 B A->B 为 1 对多的关系。消息的发送使用了中间件,但统计已读未读存在性能压力。 现在的场景是,经常给 10 万用户发一条消息,然后查看哪些用户读了消息,哪些用户没有读消息。这么做 B 表的数据量会非常大,导致查询的效率非常底下,请问该如何设计,才能减少数据库压力? 目前的思路:分表。

4685 次点击
所在节点    Java
19 条回复
rqrq
2021-03-11 11:53:00 +08:00
>>然后查看哪些用户读了消息
要不再建一张表,只记录查看了消息的用户
gBurnX
2021-03-11 12:04:40 +08:00
1.表 B 的设计思路,其实是偷懒的做法,这种思路方便一次性查出 8 辈子的消息记录,缺点就是性能差。

2.科学的高性能的设计思路应该是,发一次消息,建一个表。这样每个表里就只有十万条消息了。

3.每隔一段时间清理这些表,如果历史数据需要保存,可以直接 dump 到文件,或者放置在内存占用少的数据库实例中。
tabris17
2021-03-11 12:05:26 +08:00
已读和未读消息分两个表存
FucUrFrd
2021-03-11 13:57:43 +08:00
消息已读存 hbase,msgid:reader id
jacobsun
2021-03-11 14:06:37 +08:00
用 redis 记录发送的消息, 两个集合搞定. 一个记录发送的用户 ID 一个记录已读的用户 ID 然后去差集就好
已读未读的状态在前端的消息列表控制
Simle100
2021-03-11 14:40:45 +08:00
大佬们有没有做过这样的需求?
teddy2725
2021-03-11 14:52:17 +08:00
把已读事件写到一个流里面,用 flink 做实时统计
wennew
2021-03-11 14:59:38 +08:00
我用的 redisSET 记录消息的用户状态,然后定时备份到 mysql,缺点很多,但是只要 redis 不挂勉强能应付
soulzz
2021-03-11 15:23:46 +08:00
放客户端 sql 库啊
soulzz
2021-03-11 15:41:38 +08:00
服务端可以这样做:消息发送后保存消息 id 和发送时的时间戳在内存中
半小时内在内存中用布隆过滤器处理客户端发过来的数据区分已读未读,写一个定时
对超过半小时的消息 id 入库处理(或者用消息队列异步合并写)。

客户端的已读未读就放在客户端的库一条条处理
labulaka521
2021-03-11 15:46:13 +08:00
插个眼 目前也有类似的需求
iceteacover
2021-03-11 15:53:49 +08:00
mark,感觉不同数量级的消息 会有不同的设计实践。
sujin190
2021-03-11 15:54:27 +08:00
@jacobsun #5
@wennew #8 set 操作比直接用 hashmap 麻烦吧,而且直接写数据库就是了,redis 就是个缓存,统计已读有问题不是写已读数据有问题

其实直接发的时候都把发送用户 ID 己到 redis 消息 ID 对应的 hashmap 里就是了啊,读了就从里边删了,看哪些用户没读直接读整个 hashmap 就是了,设置一个合理过期时间也都不用清理,读不到再从数据库加载就是了,发消息和读消息都先写数据库再写 redis 就是了
sujin190
2021-03-11 15:57:56 +08:00
如果你觉得直接用 hashmap 太耗内存,那么就在发消息式给个再当前消息内部有效的自增 ID,redis 这边就能用 bitmap 来存是否已读了啊,查的时候直接取出哪些位置没读,然后结合消息 ID 就直接能查除用户了,这个应该式最省内存也不是很消耗性能的方式了吧
x537196
2021-03-11 16:16:18 +08:00
做了一套类似的,不过没有明细需求,只统计发送数、已读数
wennew
2021-03-11 18:00:11 +08:00
@sujin190 hashmap 加过期时间还是变成 redis 了呀, 而且这东西确实可以用 nosql 冗余存储,mysql 这种确实不好使啊
sujin190
2021-03-11 18:18:01 +08:00
@wennew #16 我的意思用 redis 的 set 数据结构比用 redis 的 hashmap 数据结构操作复杂,都是 redis 。。
aguesuka
2021-03-12 11:05:14 +08:00
才十万,直接存数据库建好索引分区肯定没问题。
Simle100
2021-03-12 13:39:12 +08:00
@aguesuka 群发一条就 10 万,要是每天 100 个用户群发一条,一天就有 1000 万了,你看看一个月就有多少数据量了。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/760623

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX