Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Elixir中的最佳数据结构,用于频繁更新、项目删除和基于价值的子集创建_Elixir - Fatal编程技术网

Elixir中的最佳数据结构,用于频繁更新、项目删除和基于价值的子集创建

Elixir中的最佳数据结构,用于频繁更新、项目删除和基于价值的子集创建,elixir,Elixir,为了更好地理解Erlang、Elixir和函数数据结构,我正在做一个我从天上摘下来的项目。我问这个问题是为了深入了解以下场景的最佳数据结构,作为学习练习,并查看标准库中是否有一个理想的候选者满足以下场景 我想保留一个内存存储。我想知道哪种支持数据结构适合以下场景: 可能有数万条(或更多)条目 频繁插入和更新每个条目 定期扫描(考虑gc运行)以删除过时项目(例如,在最近X秒内未更新的项目) 查询以生成子集(例如,在最后X秒内更新的所有子集) 一些背景: 客户端-服务器场景,其中每个连接的客户

为了更好地理解Erlang、Elixir和函数数据结构,我正在做一个我从天上摘下来的项目。我问这个问题是为了深入了解以下场景的最佳数据结构,作为学习练习,并查看标准库中是否有一个理想的候选者满足以下场景

我想保留一个内存存储。我想知道哪种支持数据结构适合以下场景:

  • 可能有数万条(或更多)条目
  • 频繁插入和更新每个条目
  • 定期扫描(考虑gc运行)以删除过时项目(例如,在最近X秒内未更新的项目)
  • 查询以生成子集(例如,在最后X秒内更新的所有子集)
一些背景:

  • 客户端-服务器场景,其中每个连接的客户端对应于备份存储中的单个条目,其中密钥是客户端id
  • 每个客户端将每x秒发送一次更新的数据。(经常)
  • 当客户端断开连接时,备份存储中的项目将被删除
  • 如果备份存储中的每个条目在最后X秒内未更新,则也将删除该条目。(在未收到断开连接时处理删除过时数据的操作)

我目前正在使用一个HashDict支持的进程,这是最简单的,因为我知道可能会有大量的条目,这将允许快速随机访问更新,因为密钥将对应于客户端id。目前的值是一个映射,它本身将包含“上次更新”时间。

如果您计划拥有大量并发连接的客户端,那么使用单个进程可能会出现瓶颈。相反,您可以使用ETS表来存储数据。这将允许更好的CPU使用率,因为多个客户端可以同时查询和修改表

实现这一点的一种方法是使用每客户机GenServer,而该库依赖于ETS为进程提供丰富的别名。因此,您可以为特定于客户端的进程命名,例如
{client,1}
{client,2}
等等。然后,当请求到达时,您首先尝试通过gproc找到客户机,如果它不存在,则创建它。后一部分必须经过定义良好的单例过程,以避免竞争条件。找到客户机后,只需向该客户机发出请求

您可以在特定于客户端的进程中实现超时逻辑。本质上,从handle_*和init回调中,可以以毫秒为单位指定超时。如果新消息没有在给定的时间内到达,您的客户端进程将收到一条超时消息,您可以在handle_info中处理该消息并停止接收进程。一旦进程停止,它将自动从gproc注册表注销。在监督树中,这些过程显然应该是临时或临时工人,以防止监督人员重新启动它们


另一种选择是将所有内容都保存在ETS中,而不依赖于客户端进程。您需要某种到期逻辑来GC未使用的条目,这是手动完成的。一种简单的暴力方式是定期遍历整个表并删除旧条目。或者你可以设计出更聪明的东西。我在以前的项目中使用了此技术的一个版本,并提供了一个帮助程序库。

con_cache项目看起来很棒,我会喜欢阅读代码。谢谢你的帮助,谢谢!为了完全清楚,我认为第一种方法(特定于客户端的进程+gproc发现+进程内超时)更为惯用,我将首先尝试这种方法。事实上,回想起来,我相信这种方法可能更适合con_缓存起源的系统。唯一的缺点是它需要更多的样板文件,而con_缓存已经实现了一些东西(比如GCing和通知)。