我这个项目,将创建一个“NAT-T服务器”
这是某个端口中的服务器列表,其中客户端发送其ID,IP,端口和服务器保持其最后联系时间,以清除olders客户端。
ID是唯一的,是客户端的位置。
问题是它必须每秒处理15k个事务。 不需要存储数据库。
平均跟踪客户数应为200k。
如何使用SQL服务器或数据结构实现它的最佳方法? 巫婆数据结构?
答案 0 :(得分:2)
因此,您需要能够按ID插入项目,查找,更新和删除项目。您还需要清除一段时间内未访问过的客户端。假设时间由常数定义:OldClientRemovalInterval
。
客户端数据结构将包含ID,IP,端口和上次访问时间。
这是一种方法:
维护客户端记录的关联数组,其中键为ID。 C ++标准模板库具有几种不同的关联数组数据结构(map
,hash_map
等)。 hash_map
提供非常快的访问时间。您可以非常快速地插入,更新或删除项目。
要删除,请维护包含客户端ID和预期删除时间的FIFO队列。无论何时插入或更新客户端记录,都要创建第二个结构{ ClientID, RemovalTime }
,并通过将RemovalTime
添加到当前时间来计算OldClientRemovalInterval
。
队列中的项目通过增加删除时间来排序。定期检查队列,删除删除时间已过的所有项目。
但请注意,客户端可能已更新,因为它已添加到队列中。因此,当您从队列中取出某些内容时,您必须在关联数组中查找该客户端,并确定是否确实需要将其删除。类似的东西:
ClientID = RemoveItemFromQueue();
Client = GetClientRecord(ClientID);
ClientRemovalTime = Client.LastAccess + ClientRemovalInterval;
if (ClientRemovalTime <= CurrentTime)
RemoveClient(ClientId);
这实际上要求数据结构每秒支持30K事务(对于每次插入/更新,将有相应的查找和可能的删除)。但是hash_map
应该毫无困难地处理它。
如何检查队列取决于您。您可以在计时器或第二个线程上执行此操作,但是您在锁定对队列和关联数组的访问时遇到问题。也许更好的想法是在每次插入/更新后运行删除算法,删除任何时间已过期的项目。或者,为避免在删除过程中花费太多时间,请为每次插入/更新删除最多两个旧客户端。那就是:
InsertOrUpdateClient();
// now remove up to 2 items
for (int i = 0; i < 2; ++i)
{
if (queue.Peek().RemovalTime >= CurrentTime)
{
// Remove item from queue,
// and potentially remove client from associative array.
}
else
{
break;
}
}
这样可以避免在删除时花费太多时间,但平均而言,会使旧客户端不会堵塞数据结构。唯一的缺点是如果没有插入/更新,则不会发生删除。因此,经过长时间的不活动,桌子可能充满了老客户。如果这很重要,你可以有一个定时器发送一个空请求(例如,特殊客户端ID为-1)的计时器,它不会更新关联数组,但会进行删除。