如何在小型聊天应用程序中为数据库存储的用户事务建模?
How to model user transactions for DB storage in a small chat app?
我正在尝试使用 Qt5 开发我自己的简单聊天应用程序。
一些上下文
到目前为止,我所拥有的是一个简单的服务器,它将接收来自用户(使用相应客户端)的任何消息并将它们与 from、[=23= 一起存储在数据库中]到和iseRead字段。
然后客户端会定期向服务器请求消息更新(我知道这可能不是一个好主意但我不确定我知道如何使用 Qt 查找谁在线所以请忽略它)并接收那些消息是为他们准备的。
我现在想要做的是添加一个功能,让用户不必专门从列表中选择其他人来发送消息,而是向所有人广播一些内容。将 ALL 值添加到我的 to 列将无济于事,因为我不知道何时标记 isRead 该消息的字段,这导致用户在每次客户端请求时不断收到它。
如果我想添加向一群人发送消息的功能,事情也会变得更加复杂。
真正的问题
我如何构建我的服务器端数据库以有效地存储和检索我在上面描述的用户事务(向个人发送消息、向所有人广播、向群组等)?
我认为您必须注册所有在线用户。也就是说,当客户端首次连接并进行身份验证时,您可以将带有客户端昵称的条目添加到 table online 形式的 [pk, user_nick] 例如。当客户外出(从网上删除)时,您会做相反的事情。
然后,当从客户端发送一条 ALL 消息时,您检查 online 中的内容并将 online table 中所有客户端昵称的条目添加到您的table 你存储消息的地方 ~ 这是 [from, to, isRead]。
您案例中的组功能 - 添加 table groups [pk, id_group, nick]。您必须为客户端实现逻辑以了解 id_group 标识的可能组。然后客户端将向 id_group 写入一条消息,服务器将检查该组中的用户(select .. 其中 id_group=x)并将该消息重复到您的消息中 table(那个有 from, to, isRead 的)
你说你不知道如何找出谁在线 - 通常你会实现一些登录机制 - 当客户端第一次连接时你存储他的 IP,源端口或任何东西来识别他连同他的昵称..在这个你知道谁在线的方式.. 当然你还必须实现注销和可选的一些超时机制,如果客户端不活动然后将他注销。
通过这种方式,您将拥有一些打开的连接数组,当客户端 A 向客户端 B 写入消息时,您只需将消息代理到 B.. 这样,实现其他功能会容易得多。
更新 - 添加示例
我会将逻辑从在线 table 转移到新 table 用户以存储有关用户的详细信息并简化身份验证过程等
Chat [pk, (fk) fromU , (fk) toU, isRead] #fk = 用户 pk 的外键
用户 [pk, Nick, Logged]
Group [pk, group_id, (fk) user_id] #有点讨厌,但我们会重复 group_id ..
我们在用户中有这个:
1,约翰,真实
2,伊娃,真实
3,贾娜,正确
然后当 Eva 发送所有消息时 "hello" 我们将向聊天添加三个条目 table:
54, 2, 1, "Hello"
55, 2, 2, "Hello" #这是可选的,这样 Eva 也会看到她自己的聊天记录,有时这没问题,你不必在你的应用程序中处理这个额外的东西..
56, 2, 3, "Hello"
然后当约翰查看消息时他会这样做:
Select * 来自聊天,其中 toU=1;
非常相似,我们会做组功能。
我会突然想到做这样的事情。
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。
在服务器端逻辑中,获取消息,解析出目标 user_ids,为每个目标 user_id 在消息 table 中创建一个新条目,并且将状态设置为未读,在您的服务器软件成功将消息数据传输到目标用户 ID 后将状态切换为已读。
简单。这解决了你所有的群聊消息、绝对所有人广播等问题
更新
现在显然你会想要优化它。例如,您可能真的不想复制和存储广播中发给每个用户的每条消息的数据,因此您可以在此处创建一个独立的 Messages
table 来保存具有自动递增唯一索引的原始消息内容,然后可能有第二个消息状态 table 就像这样:
Messages Status Table
message_id, target_user_id, sender_id, message_status
现在您可以让 10000000 人收到相同的消息,但您只存储了对消息 ID 的引用 10000000 次,而不是整个消息数据。然后你也可以有一个 cron 作业然后 运行 在你的服务器上每天一次或者从你的系统中清除所有状态为 READ 的消息以避免膨胀。
我正在尝试使用 Qt5 开发我自己的简单聊天应用程序。
一些上下文
到目前为止,我所拥有的是一个简单的服务器,它将接收来自用户(使用相应客户端)的任何消息并将它们与 from、[=23= 一起存储在数据库中]到和iseRead字段。
然后客户端会定期向服务器请求消息更新(我知道这可能不是一个好主意但我不确定我知道如何使用 Qt 查找谁在线所以请忽略它)并接收那些消息是为他们准备的。
我现在想要做的是添加一个功能,让用户不必专门从列表中选择其他人来发送消息,而是向所有人广播一些内容。将 ALL 值添加到我的 to 列将无济于事,因为我不知道何时标记 isRead 该消息的字段,这导致用户在每次客户端请求时不断收到它。
如果我想添加向一群人发送消息的功能,事情也会变得更加复杂。
真正的问题
我如何构建我的服务器端数据库以有效地存储和检索我在上面描述的用户事务(向个人发送消息、向所有人广播、向群组等)?
我认为您必须注册所有在线用户。也就是说,当客户端首次连接并进行身份验证时,您可以将带有客户端昵称的条目添加到 table online 形式的 [pk, user_nick] 例如。当客户外出(从网上删除)时,您会做相反的事情。 然后,当从客户端发送一条 ALL 消息时,您检查 online 中的内容并将 online table 中所有客户端昵称的条目添加到您的table 你存储消息的地方 ~ 这是 [from, to, isRead]。
您案例中的组功能 - 添加 table groups [pk, id_group, nick]。您必须为客户端实现逻辑以了解 id_group 标识的可能组。然后客户端将向 id_group 写入一条消息,服务器将检查该组中的用户(select .. 其中 id_group=x)并将该消息重复到您的消息中 table(那个有 from, to, isRead 的)
你说你不知道如何找出谁在线 - 通常你会实现一些登录机制 - 当客户端第一次连接时你存储他的 IP,源端口或任何东西来识别他连同他的昵称..在这个你知道谁在线的方式.. 当然你还必须实现注销和可选的一些超时机制,如果客户端不活动然后将他注销。 通过这种方式,您将拥有一些打开的连接数组,当客户端 A 向客户端 B 写入消息时,您只需将消息代理到 B.. 这样,实现其他功能会容易得多。
更新 - 添加示例
我会将逻辑从在线 table 转移到新 table 用户以存储有关用户的详细信息并简化身份验证过程等
Chat [pk, (fk) fromU , (fk) toU, isRead] #fk = 用户 pk 的外键
用户 [pk, Nick, Logged]
Group [pk, group_id, (fk) user_id] #有点讨厌,但我们会重复 group_id ..
我们在用户中有这个:
1,约翰,真实
2,伊娃,真实
3,贾娜,正确
然后当 Eva 发送所有消息时 "hello" 我们将向聊天添加三个条目 table:
54, 2, 1, "Hello"
55, 2, 2, "Hello" #这是可选的,这样 Eva 也会看到她自己的聊天记录,有时这没问题,你不必在你的应用程序中处理这个额外的东西..
56, 2, 3, "Hello"
然后当约翰查看消息时他会这样做: Select * 来自聊天,其中 toU=1;
非常相似,我们会做组功能。
我会突然想到做这样的事情。
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。
在服务器端逻辑中,获取消息,解析出目标 user_ids,为每个目标 user_id 在消息 table 中创建一个新条目,并且将状态设置为未读,在您的服务器软件成功将消息数据传输到目标用户 ID 后将状态切换为已读。
简单。这解决了你所有的群聊消息、绝对所有人广播等问题
更新
现在显然你会想要优化它。例如,您可能真的不想复制和存储广播中发给每个用户的每条消息的数据,因此您可以在此处创建一个独立的 Messages
table 来保存具有自动递增唯一索引的原始消息内容,然后可能有第二个消息状态 table 就像这样:
Messages Status Table
message_id, target_user_id, sender_id, message_status
现在您可以让 10000000 人收到相同的消息,但您只存储了对消息 ID 的引用 10000000 次,而不是整个消息数据。然后你也可以有一个 cron 作业然后 运行 在你的服务器上每天一次或者从你的系统中清除所有状态为 READ 的消息以避免膨胀。