如何在小型聊天应用程序中为数据库存储的用户事务建模



我正在尝试使用Qt5开发我自己的简单聊天应用程序。

某些上下文
到目前为止,我拥有的是一个简单的服务器,它将接收来自用户(使用相应客户端)的任何消息,并将它们存储在数据库中,同时还有一个fromtoiseRead字段。

然后,客户端定期向服务器请求消息更新(我知道这可能不是一个好主意,但我不确定如何使用Qt找到在线用户,所以请忽略它),并接收那些针对他们的消息。

我现在想做的是增加一种功能,让用户不必从列表中专门选择其他人来发送消息,而是向所有人广播一些内容。将ALL值添加到我的to列将没有帮助,因为我不知道何时标记该消息的isRead字段,这会导致用户在每次客户端请求时都会不断收到该消息。

如果我想增加向一群人发送信息的能力,事情也会变得更加复杂。

真正的问题
我如何构建服务器端数据库,以有效地存储和检索我上面描述的用户事务(向个人发送消息、向所有人广播、向组等)?

我会做这样的事情,这是我的想法。

Users Table    
unique_user_id, user_specific_info1, user_specific_info2, so on..
Messages Table
message, target_user_id, sender_id, message_status

现在我甚至不用麻烦在数据库中存储会话或群组消息之类的东西了。这只是毫无理由的额外开销。拥有最少的服务器端代码,允许用户将彼此添加到聊天中,并让客户端软件处理谁被邀请进入房间等。然后让客户端发送一条包含相关数据的消息:target_user_ids、消息、发送者id。

在服务器端逻辑中,获取消息,解析出目标用户id,在消息表中为每个目标用户id创建一个新条目,并将状态设置为UNREAD,一旦服务器软件成功地将消息数据传输到目标用户id后,将状态翻转为READ。

很简单。这解决了群聊消息、向所有人广播等所有问题。

更新
现在很明显,您将希望对此进行优化。举个例子,您可能真的不想在广播中向每个用户复制和存储每条消息的数据,所以这就是您创建一个独立的Messages表的地方,该表包含带有自动递增唯一索引的原始消息内容,然后可能会有第二个消息状态表,它是这样的:

Messages Status Table
message_id, target_user_id, sender_id, message_status

现在,您可以让10000000人获得相同的消息,但您只存储了10000000次对消息ID的引用,而不是整个消息数据。然后,您还可以有一个cron作业,然后每天在服务器上运行一次,或者从系统中清除所有状态为READ的消息,以避免膨胀。

我认为您必须注册所有在线用户。也就是说,当客户端首次连接并进行身份验证时,您会将带有客户端nick的条目添加到表单[pk,user_nick]的在线表中。当客户端退出时,您将执行相反的操作(从联机中删除)。然后,当从客户端发送ALL消息时,您检查online中的内容,并将联机表中所有客户端昵称的条目添加到您存储消息的表中,该表是[from,to,isRead]。

您案例中的组功能-添加表groups[pk,id_group,nick]。您必须为客户端实现逻辑,以了解哪些可能是由id_group标识的组。然后,客户端将向id_group写入一条消息,服务器将检查该组中的用户(选择..,其中id_group=x),并将该消息重复到您的消息表中(带有from、to、isRead的表)

你说你不知道如何找出谁在网上——通常你会实现一些登录机制——当客户端第一次连接时,你会存储他的IP、源端口或任何东西来识别他和他的昵称。。这样你就知道谁在网上了。。当然,您还必须实现登出和可选的一些超时机制,如果客户端处于非活动状态,则将其注销。通过这种方式,您将拥有一些打开的连接阵列,当客户端A向客户端B写入消息时,您只需将消息代理到B即可。通过这种方式可以更容易地实现其他功能。

更新-添加示例

我会将逻辑从在线表移动到新表User,以存储有关用户的详细信息,并简化身份验证等过程。

聊天[pk,(fk)from U,(fk)to U,is Read]#fk=用户pk 的外键

用户[pk,Nick,已登录]

Group[pk,Group_id,(fk)user_id]#有点恶心,但很简单,我们会重复Group_id。。

我们在用户:中有这个

1,约翰,真正的

2,Eva,真正的

3,Jana,真正的

然后,当Eva发送ALL消息"你好"时,我们会在聊天表中添加三个条目:

54,2,1,"你好">

55,2,2,"你好"#这是可选的,通过这种方式,伊娃也会看到她自己的聊天,这有时是可以的,你不必在你的应用程序中处理这些额外的内容。。

56,2,3,"你好">

然后,当约翰查看信息时,他会这样做:从聊天中选择*,其中toU=1;

同样,我们也会做群组功能。

相关内容

最新更新