目录
介绍
一、数据库设计
公告消息记录应该全局唯一,还是为每个用户创建一条公告消息?
用MongoDB存储消息数据
1. 搞冷热数据分离,热数据定期归档
2. 冷数据存储一段时间后就销毁,释放存储空间
二、系统消息的发送与收取
三、业务说明
1. 系统登录
2. 首页定时轮询
3. 修改用户资料
介绍
Kafka快,RabbitMQ也不慢,即支持同步收发消息,又支持异步收发消息。队列有五种模式,功能上强于Kafka。综合考虑选择RabbitMQ。
一、数据库设计
很多人以为消息模块的数据表设计起来很简单,创建一个 消息表 就可以存储系统消息了,我只能说,你把问题想简单了。
公告消息记录应该全局唯一,还是为每个用户创建一条公告消息?
这个问题取决于你是怎么理解系统消息的,如果你不希望系统记录用户是否阅读了某条消息,哪些消息是未读消息,那么一个公告消息在数据表中就是一条唯一的记录,存储起来非常节省空间。但是很少有系统会这么设计,如果系统消息很多,又不告诉用户哪些是已读消息,哪些是未读消息,造成用户体验非常不好。所以系统必须要记录下来,用户阅读了哪些消息,还有哪些消息是未读的。
如果一个电商系统有800万注册用户,那么系统发出一条公告消息之后,意味着要在消息表中插入800万条消息记录,每条记录是发给某位用户的公告消息。瞬间数据库的负载达到顶峰,数据库被大量的写入操作占用,导致电商系统正常的业务无法展开。请记住,一条公告消息就能让电商系统濒临崩溃。微信有11亿的日活用户,如果微信给所有用户发出一条公告消息,岂不是微信的服务器就挂了?看来消息模块的数据库架构确实有技术含量。
用MongoDB存储消息数据
因为消息模块的要存储的数据量太大,普通MySQL单表超过2000万记录,MySQL数据库就难以支撑,所以我们要换能存储海量数据的数据库产品,于是MongoDB数据库就进入到我的视线里。MongoDB适合存储海量低价值的数据,正好符合消息模块的存储要求。
即便MongoDB能存储TB级别的数据,但是消息数据日积月累,MongoDB也会有撑不下来的时候,那该怎么办呢?
1. 搞冷热数据分离,热数据定期归档
根据数据被使用的频率,可以划分成热数据和冷数据。一年内的数据被看做是热数据,超过一年的数据被当做冷数据。我们编写定时程序,每天凌晨的时候把冷数据从MongoDB_1,转移到另一个MongoDB_2。这样MongoDB_1的数据量减小了,所以CRUD的速度变快了。MongoDB_2存放的是冷数据,即便数据量很大,但是冷数据很少被用到,所以MongoDB_2仅仅充当归档库而已。
2. 冷数据存储一段时间后就销毁,释放存储空间
归档库存储的冷数据太多,也难免出现崩溃,所以我们可以定期的删除超期的冷数据。假设五年以上的冷数据就被当成是超期数据,删除超期数据之后,归档库的空间也就腾出来了。
二、系统消息的发送与收取
刚才说到了,用MongoDB存储消息数据,但是一个大型Web系统,发送一条公告消息要往数据库里面写入大量的数据,即便MongoDB也支撑不下来瞬时写入百万、千万记录的情况,那该怎么办呢?我们可以把海量写入数据写入,变成细水长流,慢慢写入到MongoDB中。
比如说我们可以引入消息队列MQ,然后在Java后端系统上面,用异步多线程的方法,向消息队列MQ中发送消息,这样Web系统发布公告消息的时候就不占用数据库正常的CRUD操作。
系统消息保存在消息队列中,我们只是用它来做削峰填谷,系统消息最终还是要存储在数据库上面。于是我们可以这样设计,在用户登陆系统的时候,用异步线程从消息队列MQ中,接收该用户的系统消息,然后把系统消息存储在数据库中,最后消息队列MQ中的该条消息自动删除。你看,这么设计之后,所有用户不可能同时登陆Web系统,所以我们就把往数据库中写入系统消息的任务,变成了错峰写入,这种设计非常巧妙是吧。
三、业务说明
Emos系统中有很多模块都用到了消息模块,我们来看看具体都有哪些业务需要消息模块。
1. 系统登录
用户登陆系统的时候,后端Emos系统要创建异步线程,接收消息队列MQ中的消息,然后把消息写到数据库里面。
2. 首页定时轮询
大家需要注意,新接收的消息并不等于未读消息。比如上面的截图1,首页显示新接收到1条消息,但是总共的未读消息总共有3条。在数据库中的消息记录里面,我会用 readFlag 和lastFlag 分表标记 未读消息 和 新接收消息 。
Emos小程序的index页面设有定时器,每5分钟发送一次轮询,查询接收到多少条新消息。MessageTask利用异步线程接收MQ中的消息,然后保存到message_ref集合中,并且设置新消息的lastFlag字段为true。
Service把message_ref中的某人所有的消息记录的lastFlag字段设置成false,返回的修改记录条数就相当于接收到了多少条新消息,这个结果要返回给小程序的。
3. 修改用户资料
我们修改用户资料之后,Emos系统会自动向该员工发送消息通知。但是消息通知并不直接写入到MongoDB,而是写到MQ消息队列,然后在首页轮询的时候提示用户有新的系统消息。