чат-сервер: какой лучший (оптимизированный) способ сохранить журнал разговоров - PullRequest
3 голосов
/ 28 декабря 2011

Я создаю простой чат-сервер в Java, где пользователи могут общаться друг с другом.Я хочу сохранить эти разговоры на уровне сервера (не на стороне клиента), чтобы я мог перечислить их пользователям в качестве службы журнала разговоров.Я также использую MySQL в качестве базы данных в своем программном обеспечении.

То, что я ищу, - это оптимизированный способ сохранения этих разговоров, а также быстрый способ перечислить их позже.До сих пор я думал о 2 реализациях.

  1. с использованием базы данных MySQL и

    a) сохранить разговор в виде строки, но проблема в том, чтонекоторые разговоры очень большие (много символов), и у меня могут возникнуть проблемы с сохранением всего разговора

    b) сохранить каждую строку разговора подряд, но в этом случае могут возникнуть проблемы со скоростью, когда я хочу перечислитьвесь разговор

  2. сохранение каждого разговора в отдельном текстовом файле, но я боюсь, что могут возникнуть проблемы с чтением / записью, особенно когда пользователи (клиенты) пишут (отправляют текст) очень быстро.

Спасибо

Ответы [ 2 ]

9 голосов
/ 28 декабря 2011

Знаете, это большая архитектурная проблема. Такие компании, как Facebook и Twitter, потратили много времени и денег, чтобы решительно решить вашу проблему. Если ваш чат-сервер прост (как вы написали), используйте способ 1.b, но создайте слой абстракции (что-то вроде saveConversation, getConversation). Если в будущем скорость вас не удовлетворит, подумайте о более эффективном представлении, таком как база данных NoSQL (LevelDB или что-то подобное). Не думайте о производительности сейчас, создайте прототип с хорошей абстракцией и подключаемой архитектурой.

0 голосов
/ 27 июня 2017

Ни один из предложенных способов не является наилучшим оптимизированным способом его хранения. Лучше всего использовать сегменты стрипов динамических таблиц на основе разговоров.

Это прототип с парадигмами: -

  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
...