通知系统里的系统公告该怎么存储用户是否已读

业务场景

  1. 想做一个类似阿里云的通知系统,一条系统公告只存一条数据,用户量大的话,怎么存储用户是否已读系统公告
  2. 用户首页看到的这个未读消息数目该怎么维护

个人想法

  1. 用 Redis bitmap 存每条公告哪些用户是否已读
  2. 用 Redis string 字段维护每个用户未读数,插入系统公告之后,全部扫一遍 incr 1?

不解

是怎么做到列表中未读的消息按时间顺序排列出来的
难道是用数据库每条公告关联所有用户?

您期望得到的结果?

问问各位有这方面的业务经验吗?
或是发表一下自己的看法?

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
最佳答案

两个表

  • notice 通知表
    字段
    id
    content
    created_at
  • notice_read 已读状态表
    字段
    user_id
    notice_id

用户已读向 notice_read 表添加一条数据 (可以同时使用redis bitmap 存储已读状态) 查询未读 可以查询 notice 总数 减去 notice_read 对应用户的数据总数 (当然也可以用缓存存储) 具体需求看自己怎么设计吧,数据量小用数据库也没关系

  • 时间排列可以 created_at 倒序

  • 有问题欢迎大佬纠正

11个月前 评论
讨论数量: 9

公告存储再一张表,用户是否读取公告再存储一张表。读了就记录在用户公告表插入已读公告,取出来和公告表对比。就能判断是否已读。未读数量直接相减即可!

11个月前 评论
fansheng (楼主) 11个月前

用户多了估计会存单独用户的已读id

11个月前 评论

如果是我来做基本上也会是和1楼1样的做法 插眼看看有没有大佬有更好的方法

11个月前 评论

首先排除楼主把读取状态存内存的想法,因为要保存每个用户对每个公告的读取状态,需要保存 n * m 条数据,随着用户量增长和公告数量增长,数据比较庞大,然后又要保证永久在内存存储,有点不靠谱

11个月前 评论
sanders

没想出来为何不直接使用一张表来存储消息。如果考虑到用户量,可以按用户主键哈希进行分表或者加上索引之后分区,然后通过仓库模式或封装服务来确保查询必含用户条件,来减少跨表或跨区查询。

“是怎么做到列表中未读的消息按时间顺序排列出来的” 按时间排序,暂时没想到其他的。

“难道是用数据库每条公告关联所有用户” 应该是公告和消息分两张表存储,用户看到的是“公告类型”的消息,用户消息可多态关联到公告中。

11个月前 评论

两个表

  • notice 通知表
    字段
    id
    content
    created_at
  • notice_read 已读状态表
    字段
    user_id
    notice_id

用户已读向 notice_read 表添加一条数据 (可以同时使用redis bitmap 存储已读状态) 查询未读 可以查询 notice 总数 减去 notice_read 对应用户的数据总数 (当然也可以用缓存存储) 具体需求看自己怎么设计吧,数据量小用数据库也没关系

  • 时间排列可以 created_at 倒序

  • 有问题欢迎大佬纠正

11个月前 评论

用数据表做

  1. 首先消息分为全体消息和单独私信,可以用2个表或者1个表增加类型区分
  2. 全体消息可不关联用户,指定私信的加一个表,一对多关联用户
  3. 如果2个表,查询所有消息用union all 连接即可
  4. 已读,私信就是修改状态,全体消息就是增加数据
  5. 未读数是所有消息和单独私信的未读书的总和,相加即可,
  6. 未读数具体怎么算,我用到的和上面提到的算法一致,求出消息总数和已读总数相减,只不过我把未读消息数存到了redis,有新公告就清楚所有缓存,有私信就重新计算此用户的未读数,因为点进去就默认全部已读,所以出错了也没什么影响。
  7. 已读,私信就是在关联表修改状态,全体消息就是增加一条数据
  8. 还有一种做法是,用户通过某些特定的行为,比如说登录,或者说任意网络请求,将全体消息也像单独私信一样绑定给用户,

具体怎么做要看自己的用户量和业务需求,历史公告等内容,新注册的用户是否可见等等。

11个月前 评论
fansheng (楼主) 11个月前

已在线上使用多次,做点补充。

两表法
1.通知表.(notice)

列名 说明
id 序号
created_at 创建时间

2.已读状态表(notice_read).

列名 说明
id 序号
notice_id 公告序号
user_id 用户序号
read_at 读公告时间

应用
1 当有公告时,插入 notice 即可,不用做其他操作。
2 当用户登录或刷新页面时,查询 notice 表与 notice_read,检查是否有未读通知。通过 noticenotice_read 相减可得有多少条未读以及是哪些条未读。
3 当用户点开公告阅读时,在 notice_read 中记录读了哪条以及时间。

这样的话,不管用户基数有多大, notice 表本身只存公告,条目比较少。notice_read 只存用户已读的条目,也不会大。
也可以实现例如某个公告所有用户可查看,比如引导;某些公告过期了不需要查看,比如新年祝贺。都在步骤2中实现即可。

对于一些用户基数大但活跃用户少的站点尤其好用。

11个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!