Java后台是如何设计已读消息和未读消息的结构,或者有什么适合的工具

如题,想做一个消息提示,具体问题如下

如果系统给所有用户推送了一条站内消息,如何区分用户是否已读,从而实现取消红点或具体未读消息数量,总不可能所有消息全部放在一个表吧,那如果有1万个用户,那不是同样的消息要发1万条,如果是数据库的话,长久下来,负担太大了吧,当然更不可能放在内存中,不然重启项目,消息就全没了。所以敢问大佬,有啥好的设计方案,不限数据库,redis,或者其他工具

阅读 22.1k
4 个回答

如果系统有redis可以这么处理, redisset 保存已经读取得消息id = messageId eg: {messageid1,messageid2...}userid_read_message 作为键(每个用户存一条,保存每个用户已经读取的所有messageid)
最终既是这种结构your_user_id_read_message:{messageid1,messageid2...}
那么此时已读消息数量和具体消息的id可知,消息自然可知直接用id查表。

没有redis直接用数据库也行,反正建一张表记录用于已经读取的消息id列表。拼接成字符串也好直接存JSON格式的也好,都行。 目的是通过用户id能获取到该用户已经读取的消息ID。每个用户的每条已读消息存一条记录这样最好,直接通过sql就可以把这个已读未读,以及具体消息内容都能查出来。

站内信在数据库建表common_notice_message 用于保存具体的站内信,一条就算你发10W个人也指用存一条。
那么not in 第一步中的已读messageid就可以查到所有未读的消息,自然数量和具体内容也就出来了。
当用户读取了未读消息(web或者app上调用了读具体消息的接口)直接在redis的已读消息id的set中新增一条记录。

使用redishash实现:

  • hash的名称unread_msg_count
  • hash的键user_id
  • hash的值未读数
  1. 如果有新消息可以使用hincrby(unread_msg_count, user_id, 1) 来处理
  2. 用户已读时,hincrby(unread_msg_count, user_id, -1)来减1或者hdel(unread_msg_count, user_id)

性能和持久性要求都可以保证

数据库层面只要键两种表就行了,message表和message_user_last_ack表,第二张表存放用户最后一个已读消息的ID,比如某用户存了message_55,那么message_55之前的都是已读,之后的都是未读的,所以消息只用存一份就行了。

是的,消息表一个就可以了,不要把消息给每个人一份。对于消息的已读未读,你在redis给用户做一个缓存,保存某个会话的已读位置和总量就可以。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题