系统内部消息

一、前言

   站内信”不同于电子邮件和实时通讯,电子邮件通过专门的邮件服务器发送、保存;实时系统的通讯像QQ那样建立长连接实现,消息一般存储在客户端。而“站内信”是系统内的消息,说白了,“站内信”的实现,就是通过数据库插入记录来实现的.

二、总体描述.

1、“站内信”有两个基本功能。

(1)点到点的消息传送。用户给用户发送站内信;管理员给用户发送站内信。

(2)点到面的消息传送。管理员给用户(指定满足某一条件的用户群)群发消息

2、功能细分

(1)关于点对点的消息传输比较明确,就是我们和他人的私聊,很容易实现

(2)关于点到面的消息传送,在具体功能上还是可以细化一下的

     (a)强制广播的发送,类似于现在各大视频app中打开时弹出的的“青少年模式”,该模式也可以分成给全员发送(例如公告),以及部分发送(例如部分人员通知开会)的两种方式。该方式是强制接受的广播

     (b)关注人员的的推送,类似于微信公众号的关注后的消息推送,即该方式是接受者自愿接受的广播

三、数据库表设计

1、第一种情况,站内的用户是少量级别的。

 这种情况,由于用户的数量非常少,因此,没有必要过多的考虑数据库的优化,采用简单的表格,对系统的设计也来的简单,后期也比较容易维护,是典型的用空间换时间的做法。

     数据库的设计如下:表名:Message

  ID:编号;SendID:发送者编号;RecID:接受者编号(如为0,则接受者为所有人);Message:站内信内容;Statue:站内信的查看状态;PDate:站内信发送时间;

  如果,某一个管理员要给所有人发站内信,则先遍历用户表,再按照用户表中的所有用户依次将站内信插入到Message表中。这样,如果有个用户,则群发一条站内信要执行n个插入操作。这个理解上比较简单,比较耗损空间。

2、第二种情况,站内的用户中量级别的。

     如果还是按照第一种情况的思路。那发一条站内信的后果基本上就是后台崩溃了。因为,发一条站内信,得重复上千个插入记录,这还不是最主要的,关键是上千乃至上万条记录,Message字段的内容是一样的,而Message有大量的占用存储空间。因此,将原先的表格拆分为两个表,将Message的主体放在一个表内,节省空间的占用。这样的设计,将重复的站内信的主体信息(站内信的内容,发送时间)放在一个表内,大量的节省存储空间。不过,在查询的时候,要比第一种情况来的复杂。

        表名:notify

  ID:编号;messageType:消息类型;messageContentID:消息体ID;SendID:发送者编号;RecID:接受者编号;Statue:站内信的查看状态;

  表名:message_content

  ID:编号;Message:站内信的内容;PDate:站内信发送时间;

3、站内的用户是较大量级的

    当注册了一个用户。过了一段时间,由于种种原因,就不再登陆了。那么这个用户就称为不活跃的。从实际来看,不活跃的用户占着不小的比例。我们以注册用户2百万,其中活跃用户只占其中的10%。

那么,用户在登录以后,首先查询message_content中的那些没有在notify中有记录的记录,表示是未读的站内信。在查阅站内信的内容时,再将相关的记录插入到notify中。

四、实现

1、该文采用第二种数据库表的设计方式实现站内信的设计,能够基本完成我们的需求,也有不完美的地方,例如当发送公告时,按照上面的系统就直接暴力给每个用户都加一条通知消息;或者通过第三种方式通过反查message_content中的那些没有在notify中有记录的记录

-- 用户关注表,记录了所有用户的关注信息
CREATE TABLE `m_user_follow`
(
    `follow_id`  bigint(20)  NOT NULL AUTO_INCREMENT COMMENT '主键id',
    `uid`        varchar(20) NOT NULL COMMENT '用户ID',
    `follow_uid` varchar(20) NOT NULL COMMENT '关注的用户id',
    PRIMARY KEY (`follow_id`),
    UNIQUE INDEX(`uid` ,`follow_uid`)
)   COMMENT ='用户关注表,记录了所有用户的关注信息';

-- 用户通知表
CREATE TABLE `m_notify`
(
    `notify_id`      bigint(20)  NOT NULL AUTO_INCREMENT COMMENT '通知主键',
    `message_type`   char(2)     NOT NULL COMMENT '消息类型:01-广播,02-关注消息,03-私信',
    `sender_id`      varchar(20) NOT NULL COMMENT '发送者用户ID',
    `receiver_id`     varchar(32) COMMENT '接受者用户ID',
    `message_status` char(2)     NOT NULL DEFAULT '01' COMMENT '消息状态:01-未读,12-已读,03-删除',
    `content_id`     varchar(24) NOT NULL COMMENT '对应内容的id',
    `create_time`    timestamp   NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (`notify_id`)
)  COMMENT ='用户通知表';

-- 站内信息内容表
CREATE TABLE `m_message_content`
(
    `content_id`  varchar(32)   NOT NULL  COMMENT '内容主键',
    `title`  varchar(24)   NOT NULL  COMMENT '消息标题',
    `content`     varchar(1000) NOT NULL COMMENT '消息内容,最长长度不允许超过1000',
    `create_time` timestamp     NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (`content_id`)
)   COMMENT ='站内信息内容表';

五、其他

1、上面的设计是基于单体项目进行实现的,当涉及到数据库分库分表的情况下就不特别合适了,当用户基数足够庞大是,可以通过对上边的不同类型的站内信单独建notify表,即私聊、广播、关注,而且可以实现使一些冗余数据不再保存。数据是单表查询,关联处理最好是在程序里面做join,merge。

2、在消息的存储,可以考虑将经常访问公告的信息备份到redis中,设置key一定的有效时间段。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值