站内信的实现思路表的设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
站内信的实现思路表的设计
“站内信”不同于电⼦邮件,电⼦邮件通过专门的邮件服务器发送、保存。
⽽“站内信”是系统内的消息,说⽩了,“站内信”的实现,就是通过数据库插⼊记录来实现的。
“站内信”有两个基本功能。
⼀:点到点的消息传送。
⽤户给⽤户发送站内信;管理员给⽤户发送站内信。
⼆:点到⾯的消息传送。
管理员给⽤户(指定满⾜某⼀条件的⽤户群)群发消息。
点到点的消息传送很容易实现,本⽂不再详述。
下⾯将根据不同的情况,来说说“站内信”的群发是如何实现的。
第⼀种情况,站内的⽤户是少量级别的。
(⼏⼗到上百)
这种情况,由于⽤户的数量⾮常少,因此,没有必要过多的考虑数据库的优化,采⽤简单的表格,对系统的设计也来的简单,后期也⽐较容易维护,是典型的⽤空间换时间的做法。
数据库的设计如下:表名:Message
ID:编号;SendID:发送者编号;RecID:接受者编号(如为0,则接受者为所有⼈);Message:站内信内容;Statue:站内信的查看状态;PDate:站内信发送时间;
如果,某⼀个管理员要给所有⼈发站内信,则先遍历⽤户表,再按照⽤户表中的所有⽤户依次将站内信插⼊到Message表中。
这样,如果有56个⽤户,则群发⼀条站内信要执⾏56个插⼊操作。
这个理解上⽐较简单,⽐较耗损空间。
某⼀个⽤户登陆后,查看站内信的语句则为:
Select * FROM Message Where RecID=‘ID' OR RecID=0
第⼆种情况,站内的⽤户中量级别的(上千到上万)。
如果还是按照第⼀种情况的思路。
那发⼀条站内信的后果基本上就是后台崩溃了。
因为,发⼀条站内信,得重复上千个插⼊记录,这还不是最主要的,关键是上千乃⾄上万条记录,Message字段的内容是⼀样的,⽽Message有⼤量的占⽤存储空间。
⽐⽅说,Message字段有100个汉字,占⽤200个字节,那么5万条,就占⽤200×50000=10000000个字节=10M。
简单的⼀份站内信,就占⽤10M,这还让不让⼈活了。
因此,将原先的表格拆分为两个表,将Message的主体放在⼀个表内,节省空间的占⽤
数据库的设计如下:
表名:Message
ID:编号;SendID:发送者编号;RecID:接受者编号(如为0,则接受者为所有⼈);MessageID:站内信编号;Statue:站内信的查看状态;
表名:MessageText
ID:编号;Message:站内信的内容;PDate:站内信发送时间;
在管理员发⼀封站内信的时候,执⾏两步操作。
先在MessageText表中,插⼊站内信的内容。
然后在Message表中给所有的⽤户插⼊⼀条记录,标识有⼀封站内信。
这样的设计,将重复的站内信的主体信息(站内信的内容,发送时间)放在⼀个表内,⼤量的节省存储空间。
不过,在查询的时候,要⽐第⼀种情况来的复杂。
第三种情况,站内的⽤户是⼤量级的(上百万),并且活跃的⽤户只占其中的⼀部分。
⼤家都有这样的经历,某⽇看⼀个⽹站⽐较好,⼀时⼼情澎湃,就注册了⼀个⽤户。
过了⼀段时间,由于种种原因,就忘记了注册时的⽤户名和密码,也就不再登陆了。
那么这个⽤户就称为不活跃的。
从实际来看,不活跃的⽤户占着不⼩的⽐例。
我们以注册⽤户2百万,其中活跃⽤户只占其中的10%。
就算是按照第⼆种的情况,发⼀封“站内信”,那得执⾏2百万个插⼊操作。
但是其中的有效操作只有10%,因为另外的90%的⽤户可能永远都不会再登陆了。
在这种情况下,我们还得把思路换换。
数据库的设计和第⼆种情况⼀样:
表名:Message
ID:编号;SendID:发送者编号;RecID:接受者编号(如为0,则接受者为所有⼈);MessageID:站内信编号;Statue:站内信的查看状态;
表名:MessageText
ID:编号;Message:站内信的内容;PDate:站内信发送时间;
管理员发站内信的时候,只在MessageText插⼊站内信的主体内容。
Message⾥不插⼊记录。
那么,⽤户在登录以后,⾸先查询MessageText中的那些没有在Message中有记录的记录,表⽰是未读的站内信。
在查阅站内信的内容时,再将相关的记录插⼊到Message中。
这个⽅法和第⼆种的⽐较起来。
如果,活跃⽤户是100%。
两者效率是⼀样的。
⽽活跃⽤户的⽐例越低,越能体现第三种的优越来。
只插⼊有效的记录,那些不活跃的,就不再占⽤空间了。
以上,是我对群发“站内信”的实现的想法。
出处:
1. ⽅案描述
该⽅案⽤于系统站内信功能模块在百万级⽤户量情况下的效率问题,只是后台管理员给前台⽤户发送站内信,⽤户与⽤户之间的发送不在讨论内。
2. ⽅案详情
假设系统的⽤户量达到了200W,活跃⽤户为10W,系统后台管理员要给全体⽤户发送⼀条感谢信,如果按照之前的存储⽅式,消息队列需要插⼊200W条数据,可是除了活跃的10W⽤户,其他⽤户都忘了⾃⼰有该⽹站的账号,他都有可能不再登陆该⽹站了,数据库保存的消息队列⽆意义了。
现表结构如下:
消息表
编号 ID NUMBER
标题 TITLE VARCHAR2(50) 50
正⽂ CONTENTS VARCHAR2(1000)
发送状态 STATUS NUMBER
发送⽇期 SEND_DATE DATE
发送⽅式 SEND_TYPE NUMBER
最新创建⼈ FCU VARCHAR2(50) 50
更新⼈ LCU VARCHAR2(50) 50
创建时间 FCD DATE
最新更新时间 LCD DATE
删除标记 DELETE_TAG CHAR(1) 1
消息容器
编号 ID NUMBER
站内信ID MESSAGE_ID NUMBER
收件⼈ID MEMBER_ID NUMBER
是否已读 READ_STATUS NUMBER
会员表
主键 id NUMBER
会员编号 u_number NUMBER
电⼦邮箱 u_email VARCHAR2(200) 200
密码 u_passwd VARCHAR2(50) 50
企业认证 company_admit NUMBER(1) 1
帐号禁⽤帐号禁⽤ NUMBER(1) 1
创建⼈ FCU NUMBER
最后更新⼈ LCU NUMBER
⾸次创建时间 FCD DATE
最后更新时间 LCD DATE
删除标记 DETELE_TAG char(1) 1
在尽量不改变表结构的前提下,改变⼀下程序写数据库的⽅式:
后台管理员发送⼀条站内信,接收对象为全体会员,系统往站内信表插⼊⼀条站内信,其中发送⽅式区分接收的对象(0为全体发送,1为只发送给注册会员,2为只发送给企业会员,3为指定会员发送),这样,发送给全体会员的⼀条站内信暂时只⽣成了⼀条数据。
前台会员登陆的时候,根据会员⾃⾝的会员类型(普通会员,企业会员)查询站内信表中属于⾃⼰的最新消息(根据⾃⼰所持消息的最新时间与消息表的发送时间做⽐对),往消息容器中插⼊⾃⾝与所持消息的关联数据,默认未未读,在前台会员点击某⼀条未读站内信的时候,将容器中的对应站内信状态改为已读。
如果后台管理员只指定发送站内信给某⼏个会员,则往站内信表插⼊⼀条站内信后,将这⼏个会员与该站内信的关联直接往消息容器中写关联,不需要前台会员取。
另:因为改变了发送接收⽅式,后台管理员只指定发送站内信给某⼏个会员,但是站内信状态未未发送,只是保存草稿,需要往站内信主表增加⼀个字段,保存指定会员的id串,⽤于关联此草稿与指定会员的关联,此处就要求发送给指定会员的数量不能太多,需要限制。
这样,百万级⽤户量的系统,活跃度为10%的⽤户登陆系统,只⽣成了10W的数据,⽤户活跃度越低,此⽅案效率越明显,如果是100%活跃度的话,此⽅案和现有⽅法⽆区别。