具有房间的实时聊天项目的数据库模式

时间:2011-12-29 20:25:21

标签: php mysql database-design chat

对于我的大学项目,我正在开发一个动态的实时聊天网站,其中包括房间,用户注册等。我已经完成了整个系统的计划。房间。我对如何为房间设计数据库感到困惑。

为了透视,房间由用户创建,然后用户是该房间的操作员。用户可以加入房间并在其中进行交谈。该系统必须具有可扩展性,如果不是每天发送数百万条消息,则会占据数十万条。

最初,我打算在我的数据库中创建一个名为messages的表,并且有这样的字段:

| r_id | u_id | message | timestamp |

r_idu_id分别是房间ID和用户ID的外键。这样做意味着我需要在用户发送消息时插入新记录,并定期为每个客户端运行一个SELECT语句(比如每3秒左右)以获取最近的消息。我对此的担心是因为表格很大,运行这些语句可能会产生很多开销并且需要很长时间。

我想实现这个的另一种方法是为每个房间创建一个新的数据库表。假设用户创建了3个名为GeneralProgrammingGaming的房间,数据库表格如下:room_generalroom_programmingroom_gaming,每个都有以下字段:

| u_id | message | timestamp |

这会大大减少每个表的查询量,但在我编程时可能会出现问题。

所以,我坚持认为最好的方法是做什么。如果它有所作为,我使用的技术将是MySQL与PHP,以及一个完整的AJAX。

感谢您的帮助!

5 个答案:

答案 0 :(得分:2)

每个房间创建一个表是个坏主意。难以实施,难以支持。

不要担心选择的表现,因为它们很简单:

SELECT * FROM messages WHERE r_id=X ORDER BY timestamp DESC LIMIT X,Y

请确保按此顺序将您的(r_id,时间戳)编入索引,以使用索引进行此选择:

ALTER TABLE `messages` ADD KEY `IN_messages_room_time` (`r_id`, `timestamp`);

如果您仍然遇到性能问题(可能不会),只需添加1-3秒的内存缓存(使用内存缓存),每1-3秒从DB中获取一次邮件。

另请参阅Apollo Clark的答案:https://stackoverflow.com/a/8673165/436932以防止存储大量不必要的旧消息:您可以将其放入MYISAM表archive或只是删除。

答案 1 :(得分:1)

查看创建用于存储消息的“事务表”。基本上,您需要决定,我是否真的要记录发布到房间的所有消息,或者只记录过去一个月/周/天/小时发布的消息。如果您真的想要记录每条消息的历史记录,那么您将创建两个数据库。如果您不想保留每条消息的历史记录,那么您只需要一个表格。

使用交易表,以下是它的流程:

  1. 用户进入聊天室
  2. 用户键入一条消息,该消息将保存到事务表中。
  3. 每隔500毫秒或3秒,会议室中的每个用户都会查询交易表,以获取过去500毫秒或3秒的最新更新

    SELECT * FROM message_transactions WHERE timestamp > 123456789
    
  4. CRON作业每5分钟或1小时运行一次,并删除所有早于5分钟的条目或者您希望历史记录长的条目。

  5. 确保同步并循环每个用户查询事务表的时间,以便MySQL查询结果缓存将启动。例如,将时间戳每1秒或每500毫秒舍入一次。

    现在发生的是用户只获取最新消息,并且您的数据库不会随着时间的推移而大小爆炸,或者速度变慢。这样做,您需要在JS中缓存客户端消息的历史记录。

    另一方面,您可以获得一个PHP到IRC库,并将其称为一天。此外,如果您对此感到好奇,请研究Facebook如何实现基于AJAX的聊天系统。

答案 2 :(得分:1)

要加快数据库的速度,请查看对表格编制索引:http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html

在你的情况下,我假设你通过u_id在用户表上进行JOIN时通过r_id选择消息。我会索引r_id和u_id列。我绝不是这个主题的专家,因为我只对我自己的项目做了“有用的”。我不理解索引的每个赞成和反对意见,只是索引那些通常用作索引的列,加快速度。谷歌“mysql索引教程”,你会发现更多的信息。

不要疯狂并为每一列编制索引,否则会降低INSERT和UPDATE的速度。

我还建议您每隔几天/每周清除一次聊天记录,或者将它们移动到另一台服务器进行存档,如果这是您想要/需要做的事情。

答案 3 :(得分:0)

您可以使用memcached在内存中保存最近的聊天消息,并批量写入数据库。

Using memcached as a database buffer for chat messages

答案 4 :(得分:0)

你能做的是:

每当用户更新时,您都会将消息保存到特定于房间的缓存中,该缓存具有消息何时进入的时间戳,同时将其保存到数据库中。当客户端请求新消息时,如果用户不是聊天室中的新用户,则检查服务器上次服务用户的时间,并从请求的高速缓存中加载新消息。但如果用户是新用户,那么你就可以从数据库中为他服务。

为了提高此方案的可伸缩性,您必须设置邮件的到期时间,以便邮件在该时间之后过期。或者实现一个异步方法,根据时间戳删除旧消息。