3

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

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

  1. 使用 MySQL 数据库和

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

    b)连续保存对话的每一行,但是当我想列出整个对话时,可能会出现速度问题

  2. 将每个对话保存在一个单独的文本文件中,但恐怕会出现读/写问题,尤其是当用户(客户)非常快速地写入(发送文本)时。

谢谢

4

2 回答 2

10

这是一个很大的架构问题,你知道的。facebook 和 twitter 等公司花费大量时间和金钱以稳健的方式解决您的问题。如果您的聊天服务器很简单(如您所写),请使用 1.b 方式,但创建一个抽象层(类似于saveConversation, getConversation)。如果将来的速度不能满足您,请考虑更有效的表示,例如 NoSQL 数据库(LevelDB 或类似的东西)。现在不要考虑性能,做一个具有良好抽象和可插拔架构的原型。

于 2011-12-28T12:18:47.840 回答
-7

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

这是具有范式的原型:-

  1. 与多个参与者进行对话。
  2. 确认聊天的选项。
  3. 操作更新选项。
  4. 发布附件的选项。
  5. 共享地图坐标的选项,例如您当前的位置。
  6. 离开聊天的选项。

类型

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
于 2017-06-26T22:31:01.507 回答