聊天服务器:保存对话日志的最佳(优化)方式是什么

时间:2011-12-28 12:11:35

标签: java mysql optimization chat livechat

我正在java中构建一个简单的聊天服务器,用户可以在其中进行私人对话。我想在服务器级别(而不是在客户端)保存这些对话,以便我可以将它们作为对话日志服务列出给用户。 我也在我的软件中使用MySQL作为数据库。

我正在寻找的是保存这些对话的优化方式,以及稍后列出它们的快速方法。 到目前为止,我已经考虑了2个实现。

  1. 使用MySQL数据库和

    a)将对话作为文本连续保存,但问题是某些对话非常庞大(很多字符),我可能在保存整个对话时遇到问题

    b)连续保存会话的每一行,但这样当我想列出整个会话时,速度问题就会出现

  2. 将每个会话保存在一个单独的文本文件中,但我担心会出现读/写问题,尤其是当用户(客户端)写得很快(发送文本)时。

  3. 由于

2 个答案:

答案 0 :(得分:9)

这是一个很大的架构问题,你知道。像facebook和twitter这样的公司花了很多时间和金钱以强有力的方式解决你的问题。如果您的聊天服务器很简单(正如您所写),请使用1.b方式,但要创建一个抽象层(类似saveConversationgetConversation)。如果未来的速度不能满足你,那么考虑更高效的表示,比如NoSQL数据库(LevelDB或类似的东西)。现在不要考虑性能,制作具有良好抽象和可插拔架构的原型。

答案 1 :(得分:-3)

所提出的方法都不是存储它的最佳方法。 最好的方法是在对话的基础上使用动态表的条带段。

这是范例的原型: -

  1. 与多个参与者进行对话。
  2. 确认聊天的选项。
  3. 操作选项更新。
  4. 发布附件的选项。
  5. 选择与当前位置分享地图坐标。
  6. 保持聊天的选项。
  7. 类型

    Coordinates(
      lat FLOAT( 10, 6 ) NOT NULL ,
      lng FLOAT( 10, 6 ) NOT NULL 
    )
    

    模式

    dbo.User(UserId,<..Details..>)
    
    dbo.Conversation(ConversationId,Title,CreationDate,LastActivityDate)
    

    索引:LastActivityDate,ConversationId

    dbo.Participants(ConversationId,UserId)
    

    表格集合 - 动态创建

    msg.msg_*ConversationId*(MessageId,FromUserId,Message,Attachment,LocationCoordinates,Action,LogDate,AcknowledgeDate)
    

    抽象

    usp_TouchMessage(@Which):
       if (not exists (select 1 from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA+'.'+TABLE_NAME = 'msg.msg_'+CAST(@Which as nvarchar(max)))
       begin
            @dynamic_sql = 'create table msg.msg_'+CAST(@Which as nvarchar(max))+' (MessageId uniqueidentifier,FromUserId uniqueidentifier,Message nvarchar(max),Attachment BLOB,LocationCoordinates Coordinates,Action nvarchar(max),LogDate DateTime, AcknowledgeDate DateTime);';
            exec(@dynamic_sql);
            @dynamic_sql = 'CREATE TRIGGER msg.trig_msg_'+CAST(@Which as nvarchar(max))+'  ON msg.msg_'+CAST(@Which as nvarchar(max))+' AFTER INSERT AS Delete From msg.msg_'+CAST(@Which as nvarchar(max))+' where MessageId in (Select MessageId,ROW_NUMBER() OVER (order by LogDate Desc,AcknowledgeDate Desc,MessageId Desc) RN from msg.msg_'+CAST(@Which as nvarchar(max))+') where RN>=5000';
            exec(@dynamic_sql);
    
         end
    
    usp_GetParticipants(@Where) :
        Select User.UserId,User.FullName 
              from Participants 
                    inner join Users on (
                            Participants.UserId = Users.UserId 
                        And Participants.ConversationId = @Where
                    );
    
    
    usp_AddParticipants(@Who, @Where) :
        insert into Participants(ConversationId,UserId) values (@Where, @Who);
        @action = ( select User.FullName + ' has joined the chat' from User where User.UserId = @Who );
        update Conversation set LastActivityDate = GETUTCDATE() where ConversationId = @conversation_id;
        exec usp_TouchMessage(@Where);
        @dynamic_sql = 'insert into msg.msg_'+CAST(@Where as nvarchar(max))+' (MessageId,FromUserId,Action,LogDate) values (NewId(),@Who,@Action,GETUTCDATE())';
        sp_executesql @dynamic_sql, N'@Who uniqueidentifier,@Action nvarchar(max)', @Who = @Who, @Action = @Action;
    
    
    usp_GetConversationList() :
        With Participation As (
            Select User.UserId,User.FullName,Participants.ConversationId 
              from Participants 
                    inner join Users on (Participants.UserId = Users.UserId)
        ) select Conversation.*,
                (STUFF((
                        SELECT ',' + CAST([FullName] AS nvarchar(max)) 
                          FROM Participation 
                         WHERE (Participation.ConversationId = Conversation.ConversationId) 
                  FOR XML PATH ('')
                 ),1,1,'')) ParticipantList
            from Conversation 
        order by Conversation.LastActivityDate;
    
    
    usp_GetConversationById(@Which,@Lite = 0,@Page = 1) :
        Select User.UserId,User.FullName 
              from Participants
                inner join Users on (Participants.UserId = Users.UserId and Participants.ConversationId = @Which);
        @dynamic_sql = 'select * from
                            (select u.UserId,u.FullName,m.MessageId,'
                                    +(case when @Lite=1 then 'm.Message,m.LocationCoordinates,m.Attachment,m.Action,' else '' end)
                                    +'m.LogDate,m.AcknowledgeDate, ROW_NUMBER() Over (order by m.LogDate Desc,m.AcknowledgeDate Desc,m.MessageId Desc) RN
                              From msg.msg_'+CAST(@Which AS nvarchar(max))+' m 
                                inner join User u on (m.FromUserId = u.UserId) 
                            ) tmp 
                        where RN Between ((@Page-1)*20+1) AND (@Page*20+1)
                    ';
        sp_executesql @dynamic_sql, N'@Page bigint', @Page = @Page;
        If @Page = 1 And @Lite=0
        begin
            @dynamic_sql = 'update msg.msg_'+CAST(@Which as nvarchar(max))+' Set AcknowledgeDate = GETUTCDATE() where AcknowledgeDate is null and FromUserId <> @Who';
            sp_executesql @dynamic_sql, N'@Who uniqueidentifier', @Who = @Who;
        end
    
    usp_GetConversation(@Who,@WithWhome,@Lite = 0,@Page = 1) :
        @conversation_id = (
            Select top 1 ConversationId 
              from Participants self 
                inner join Participants partner 
                    on ( self.ConversationId = partner.ConversationId and self.UserId = @Who and partner.UserId = @WithWhome)
                where (Select count(1) from Participants where ConversationId = self.ConversationId) = 2
        );  
        if(@conversation_id is not null)
        then
            exec usp_GetConversationById(@conversation_id, @Lite, @Page);
        end
    
    
    usp_PostConversationById(@Who,@Which,@WhatMessage,@WhichLocation,@WhatAttachment) :
        update Conversation set LastActivityDate = GETUTCDATE() where ConversationId = @Which;
        exec usp_TouchMessage(@Which);
        @dynamic_sql = 'insert into msg.msg_'+CAST(@Which as nvarchar(max))+' (MessageId,FromUserId,Message,Attachment,LocationCoordinates,LogDate) values (NewId(),@Who,@WhatMessage,@WhichLocation,@WhatAttachment,GETUTCDATE())';
        sp_executesql @dynamic_sql, N'@Who uniqueidentifier,@WithWhome uniqueidentifier,@WhatMessage nvarchar(max),@WhichLocation Coordinates,@WhatAttachment BLOB', @Who = @Who, @WhatMessage = @WhatMessage, @WhichLocation = @WhichLocation, @WhatAttachment = @WhatAttachment;
    
    
    usp_PostConversation(@Who,@WithWhome,@WhatMessage,@WhichLocation,@WhatAttachment) :
        @conversation_id = (
            Select top 1 ConversationId 
              from Participants self 
                inner join Participants partner 
                    on ( self.ConversationId = partner.ConversationId and self.UserId = @Who and partner.UserId = @WithWhome)
                where (Select count(1) from Participants where ConversationId = self.ConversationId) = 2
        );  
        if(@conversation_id is not null)
        then
            @conversation_id = newid()
            insert into Conversation(ConversationId,CreationDate) values (@conversation_id,GETUTCDATE());
            exec usp_AddParticipants(@Who,@conversation_id);
            exec usp_AddParticipants(@WithWhome,@conversation_id);
        end
        exec usp_PostConversationById(@Who,@conversation_id,@WhatMessage,@WhichLocation,@WhatAttachment);
    
    
    usp_UpdateConversationAlias(@Who,@Which,@WithWhat) :
        @action = ( select User.FullName + ' has changed title'+isnull(' from <b>'+Conversation.Title+'</b>','')+isnull(' to <b>'+@WithWhat+'</b>','') from User inner join Conversation on (Conversation.ConversationId = @Which and User.UserId = @Who));
        update Conversation set LastActivityDate = GETUTCDATE(), Title = @WithWhat where ConversationId = @conversation_id;
        if (not exists (select 1 from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA+'.'+TABLE_NAME = 'msg.msg_'+CAST(@Which as nvarchar(max)))
        exec usp_TouchMessage(@Which);
        @dynamic_sql = 'insert into msg.msg_'+CAST(@Which as nvarchar(max))+' (MessageId,FromUserId,Action,LogDate) values (NewId(),@Who,@Action,GETUTCDATE())';
        sp_executesql @dynamic_sql, N'@Who uniqueidentifier,@Action nvarchar(max)', @Who = @Who, @Action = @Action;
    
    
    usp_LeaveConversation(@Who,@Which) :
        delete from Participants where ConversationId = @Where and UserId = @Who;
        if(not exists (Select 1 From Participants Where ConversationId = @Which))
        begin
            @dynamic_sql = 'drop table msg.msg_'+CAST(@Which as nvarchar(max))+';
            exec @dynamic_sql;
            delete from Conversation where ConversationId = @Which;
        end
        else
        begin
            @action = ( select User.FullName + ' has left the chat' from User where User.UserId = @Who );
            update Conversation set LastActivityDate = GETUTCDATE() where ConversationId = @conversation_id;
            exec usp_TouchMessage(@Which);
            @dynamic_sql = 'insert into msg.msg_'+CAST(@Which as nvarchar(max))+' (MessageId,FromUserId,Action,LogDate) values (NewId(),@Who,@Action,GETUTCDATE())';
            sp_executesql @dynamic_sql, N'@Who uniqueidentifier,@Action nvarchar(max)', @Who = @Who, @Action = @Action;
        end