› 首页 ›产业观察›正文

消息未读数量查询对应的数据修改后如何更新或清除缓存?

admin 产业观察 2026-10-20 17:15:19 13 0
消息未读数量发生变化后,应在数据库更新成功后及时删除或刷新对应用户的缓存,确保查询结果与实际数据一致,通常优先采用“先更新数据库,再删除缓存”的策略,后续查询缓存未命中时重新统计未读数量并写入缓存,同时设置合理的过期时间,避免异常导致缓存长期失效,针对并发更新或删除失败,可结合延迟双删、消息队列重试等机制降低数据不一致风险。

未读消息数量改了,缓存却没更新?一文讲清缓存刷新与清除的正确姿势

做过消息中心、站内信或者聊天系统的开发者,基本都遇到过这样的情况:用户明明已经点了“全部已读”,右上角的小红点却还在;数据库里的未读数量已经变成了0,页面查询出来的结果却还是5。

这类问题看起来只是一个数字没有刷新,背后涉及的却是数据库、缓存和前端状态之间的一致性。消息未读数量对应的数据修改后,到底应该更新缓存,还是直接清除缓存?

今天就把这件事讲明白,并给出可以落地的处理思路。

先明确:未读数量的缓存究竟存了什么?

假设系统用数据库存储消息记录,每条记录包含用户ID、消息ID、是否已读等字段,查询某个用户的未读数量时,可以执行类似下面的SQL:

SELECT COUNT(*)
FROM user_message
WHERE user_id = ?
  AND is_read = 0;

用户量不大时,直接查数据库通常就够了,但如果首页、导航栏、消息页都频繁查询未读数,数据库就可能反复执行相同的统计操作。

很多系统会把结果放入Redis,

message:unread:10001 = 5

后续查询先读取Redis,缓存不存在时再查询数据库,并把结果写回缓存。

问题也随之而来:数据库里的消息状态改变了,Redis并不会自动感知。缓存刷新必须由业务逻辑或可靠的事件处理机制触发。

常规业务的首选:数据库提交成功后,删除缓存

对于大多数普通消息系统,推荐优先采用“先更新数据库,再删除缓存”的方式,而不是在每次操作后重新计算并覆盖缓存。

以“标记消息为已读”为例:

  1. 更新数据库中的消息状态。
  2. 确认数据库事务提交成功。
  3. 删除对应用户的未读数量缓存。
  4. 下一次查询未读数时,重新统计并写入缓存。

伪代码如下:

事务内:
    将指定消息更新为已读
事务提交成功后:
    删除 message:unread:{userId}

为什么强调“事务提交成功后”?

因为如果数据库事务尚未提交就删除缓存,其他请求可能趁缓存缺失时查到数据库里的旧数据,再把旧未读数写回Redis,这样即使事务随后成功提交,缓存仍可能是旧值。

同样,不建议先删除缓存再修改数据库,这会增加旧数据被重新加载的机会。

不过要注意,先提交数据库、再删除缓存,也不是严格一致性的保证,例如某个并发查询已经读到了旧数据,在删除动作完成后才回填缓存,仍然可能造成短暂不一致。

消息未读数量查询对应的数据修改后如何更新或清除缓存?
(图片来源网络,侵删)

对一般站内信场景,可以接受短暂延迟,并通过合理过期时间、删除失败重试等方式控制影响;对一致性要求更高的场景,则需要增加版本校验、协调读写或使用更严格的数据访问方案。

为什么不直接把缓存减1?

有人会问:用户读了一条消息,执行一次Redis的DECR,不是更快吗?

消息未读数量查询对应的数据修改后如何更新或清除缓存?
(图片来源网络,侵删)

确实更快,但也更容易踩坑。

用户连续点击两次,或者网络重试导致同一个“已读”请求执行两遍,如果两次都减1,实际只有一条消息变为已读,缓存却减少了两次。

正确处理至少要做到:

  • 数据库更新带上“当前仍未读”的条件。
  • 根据实际受影响的行数计算变化量。
  • 避免同一个事件重复扣减。
  • 确保缓存不存在时不会直接减成负数。
  • 考虑数据库更新成功、Redis操作失败后的补偿。
UPDATE user_message
SET is_read = 1
WHERE user_id = ?
  AND message_id = ?
  AND is_read = 0;

只有这次更新确实影响了1行,才代表未读数量发生了变化。

即便如此,数据库和Redis之间的双写一致性问题依然存在。原子加减适合经过专门设计的计数系统,不应被当成普通缓存的万能解决方案,如果业务量尚未达到需要精细优化的程度,删除缓存往往更简单,也更容易维护。

删除缓存失败了,该怎么办?

数据库已经提交成功,但Redis恰好超时,缓存没有删除,这是实际生产环境中必须考虑的问题。

常见的兜底方案有三种。

第一,设置合理的缓存过期时间。

例如根据业务允许的延迟设置几十秒或数分钟的有效期,并加入少量随机值,降低大量缓存同时失效的风险,过期时间只能限制旧值持续多久,不能代替正常的失效通知。

第二,建立可靠重试机制。

删除失败后记录日志并进入重试流程,而不是简单捕获异常后就不管了,对重要业务,可以使用事务消息表,也就是Outbox模式:业务修改和待处理事件在同一数据库事务里提交,再由后台任务持续投递和处理缓存失效事件。

第三,安排周期性校准。

如果采用Redis计数器维护未读数,可以定期与数据库统计结果对账,及时纠正计数漂移。

对于未读数量这类通常允许最终一致的数据,可靠失效通知加过期兜底,往往比堆叠复杂方案更划算。

后端缓存清了,前端也需要同步

还有一种常见误会:后端已经清除Redis,页面上的数字却没有变化,于是开发者继续排查Redis。

前端可能还保存着自己的查询缓存或者组件状态。

“全部已读”成功后,前端应该主动使未读数查询失效并重新请求;也可以先做乐观更新,再通过服务端返回结果校准,如果需要多端同步,可以通过WebSocket或SSE发送“未读数量已变化”的通知,让客户端重新拉取。

不要只修改当前按钮旁边的数字,却忘记导航栏、其他页面以及另一台设备上的状态。

服务器怎么选,才能让消息系统运行得更稳?

消息系统的稳定性,不仅取决于代码,也取决于数据库、Redis和应用服务的部署条件,CPU、内存、磁盘性能,以及服务之间的网络时延,都会影响查询和缓存失效操作的执行效果。

如果你正在为这类业务选购服务器,可以把慈云数据列入咨询和比较名单,根据自己的并发量、数据规模与预算,了解适合的服务器方案。

选购时不要只看价格,建议重点确认:

  • 应用、数据库和Redis之间的网络连通与时延。
  • 内存容量是否能够覆盖缓存规模并留有余量。
  • 磁盘性能、备份能力及故障恢复安排。
  • 带宽、扩容方式、服务支持范围和实际费用。
  • 是否支持测试,并用接近真实业务的负载进行验证。

慈云数据的具体配置、价格与服务承诺,应以实际咨询和合同约定为准,服务器配置再高,也无法自动解决缓存一致性问题;合理的程序设计加上匹配的基础设施,才是稳定运行的关键。

先把简单方案做可靠,再考虑复杂优化

回到最初的问题:消息未读数量对应的数据修改后,如何更新或清除缓存?

对于大多数业务,一个实用的起点是:

数据库事务提交成功后,删除对应用户的未读数缓存;查询时按需重建;同时配置过期时间、删除失败重试和前端主动刷新。

如果业务规模很大,再考虑事件驱动的计数维护、幂等处理、版本控制和定期校准。

小小的未读数字,串联的是完整的数据链路,把这条链路设计清楚,再结合包括慈云数据在内的服务器方案进行实际测试和选型,才能避免“数据库早就改了,小红点却一直不消失”的尴尬。

缓存更新清除
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

广州AI科技日报

https://rtximg.cn/

统计代码 | 京ICP备100000000

Powered By 某某网络科技有限公司

简体中文English