我正在java中构建一个简单的聊天服务器,用户可以在其中进行私人对话。我想在服务器级别(而不是在客户端)保存这些对话,以便我可以将它们作为对话日志服务列出给用户。 我也在我的软件中使用MySQL作为数据库。
我正在寻找的是保存这些对话的优化方式,以及稍后列出它们的快速方法。 到目前为止,我已经考虑了2个实现。
使用MySQL数据库和
a)将对话作为文本连续保存,但问题是某些对话非常庞大(很多字符),我可能在保存整个对话时遇到问题
b)连续保存会话的每一行,但这样当我想列出整个会话时,速度问题就会出现
将每个会话保存在一个单独的文本文件中,但我担心会出现读/写问题,尤其是当用户(客户端)写得很快(发送文本)时。
由于
答案 0 :(得分:9)
这是一个很大的架构问题,你知道。像facebook和twitter这样的公司花了很多时间和金钱以强有力的方式解决你的问题。如果您的聊天服务器很简单(正如您所写),请使用1.b方式,但要创建一个抽象层(类似saveConversation
,getConversation
)。如果未来的速度不能满足你,那么考虑更高效的表示,比如NoSQL数据库(LevelDB或类似的东西)。现在不要考虑性能,制作具有良好抽象和可插拔架构的原型。
答案 1 :(得分:-3)
所提出的方法都不是存储它的最佳方法。 最好的方法是在对话的基础上使用动态表的条带段。
这是范例的原型: -
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