我们如何有效地处理 mnesia 记录的时间相关约束?

2024-04-22

我正在将记录写入mnesia,该记录应该保存在那里 仅在允许的时间(24 小时)内。 24小时后,在用户修改其中的一部分之前, 系统应该自动删除它们。例如,用户获得免费通话时间(用于语音通话) 他们应该在给定时间内使用它们。如果他们不使用它,24小时后,系统应该 从用户记录中删除这些资源预留。

现在,这引入了计时器。记录结构的一个示例是:



 -record(free_airtime,
            {
                reference_no,
                timer_object,   %% value returned by timer:apply_after/4
                amount
            }).
   

记录中的计时器对象很重要,因为万一用户 最终在超时之前使用保留的资源 (或者如果超时),系统可以调用timer:cancel/1从而缓解 来自该对象的计时器服务器。 现在的问题是,我有两种方法来处理这些记录上的计时器:

选项 1:在事务内处理计时器



 reserve_resources(Reference_no,Amnt)->
    F = fun(Ref_no,Amount) -> 
            case mnesia:read({free_airtime,Ref_no}) of
                [] -> 
                    case mnesia:write(#free_airtime{reference_no = Ref_no,amount = Amount}) == ok of
                        true -> 
                            case timer:apply_after(timer:hours(24),?MODULE,reference_no_timed_out,[Ref_no]) of
                                {ok,Timer_obj} -> 
                                    [Obj] = mnesia:read({free_airtime,Ref_no}),
                                    mnesia:write(Obj#free_airtime{timer_object = Timer_obj});
                                _ -> mnesia:abort({error,failed_to_time_object})
                            end;
                        false -> mnesia:abort({error,write_failed})
                    end;
                [_] -> mnesia:abort({error,exists,Ref_no})
            end
        end,
    mnesia:activity(transaction,F,[Reference_no,Amnt],mnesia_frag).
  

关于上面的选项。

Mnesia 文档说 tm 经理可能会重复交易(由于某种原因) 直到他们成功,所以当你输入代码时io:format/2或任何其他与此无关的 写入或读取,它可能会被执行多次。这句话让我此时停了下来 并想出一种从事务本身处理计时器的方法,所以我将代码修改为 如下:

选项 2:在事务外处理计时器




reserve_resources(Reference_no,Amnt)->
    F = fun(Ref_no,Amount) -> 
            case mnesia:read({free_airtime,Ref_no}) of
                [] -> 
                    P = #free_airtime{reference_no = Ref_no,amount = Amount},
                    ok = mnesia:write(P),
                    P;
                [_] -> mnesia:abort({error,exists,Ref_no})
            end
        end,    
    Result  =   try mnesia:activity(transaction,F,[Reference_no,Amnt],mnesia_frag) of
                    Any -> Any
                catch
                    exit:{aborted,{error,exists,XX}} -> {exists,XX}
                    E1:E2 -> {error,{E1,E2}}
                end,
    on_reservation(Result).

on_reservation(#free_airtime{reference_no = Some_Ref})-> 
    case timer:apply_after(timer:hours(24),?MODULE,reference_no_timed_out,[Some_Ref]) of
        {ok,Timer_obj} -> 
                [Obj] = mnesia:activity(transaction,fun(XX) -> mnesia:read({free_airtime,XX}) end,[Some_Ref],mnesia_frag),
                ok = mnesia:activity(transaction,fun(XX) -> mnesia:write(XX) end,[Obj#free_airtime{timer_object = Timer_obj}],mnesia_frag);
        _ -> 
            ok = mnesia:activity(transaction,fun(XX) -> mnesia:delete({free_airtime,XX}) end,[Some_Ref],mnesia_frag),
            {error,failed_to_time_object}
    end;
on_reservation(Any)-> Any.

  

处理预订超时的代码:



reference_no_timed_out(Ref_no)->
    do_somethings_here.....
    then later remove this reservation from the database....below..
    ok = mnesia:activity(transaction,fun(XX) -> mnesia:delete({free_airtime,XX}) end,[Ref_no],mnesia_frag).
  

现在我认为在选项 2 中,保持计时器处理会更安全 代码输出,即使 mnesia_tm 由于其原因重新执行交易 ,这段代码不会运行两次(我避免有几个计时器对象 反对相同的记录)。

问题一:这两种实现哪个是正确的?和/或错误?告诉我(也) 他们是否都错了

问题2:定时器模块,是否非常适合处理大量定时器 生产中的工作岗位?

问题3:与肖恩·辛德相比, 运行在 mnesia 之上,计时器模块(可能运行在 Ets 表之上)少 有能力(真正)生产吗? (我问这个是因为在本身使用 mnesia 的系统上使用 Sean Hinde 的 time_mn 会出现 在模式更改、节点问题等方面成为问题)

如果有人有另一种方法来处理与 mnesia 计时器相关的问题,请更新我 谢谢大家...


问题一:

在事务之外处理计时器。当 Mnesia 中的交易发生冲突时,它们会被简单地重复。这将为您提供多个计时器参考和两个计时器触发器。这本身不是问题,但如果等到交易成功后再安装计时器,就可以避免这个问题。

第二个解决方案就是我要做的。如果TX没问题,你可以在上面安装一个定时器。如果计时器触发并且没有对该对象的引用,则没关系。您只需担心这种情况是否经常发生,因为这样您就会有大量的杂散计时器。

问题2:

计时器模块很简洁,但性能指南建议您使用erlang:start_timer相反,请参阅 BIF

http://www.erlang.org/doc/efficiency_guide/commoncaveats.html#id58959 http://www.erlang.org/doc/efficiency_guide/commoncaveats.html#id58959

我会引入一个单独的过程作为gen_server它处理计时的事情。你发送一个remove(timer:hours(24), RefNo)消息,然后它启动一个计时器,得到一个TRef并安装映射{TRef, RefNo, AuxData}在 Mnesia 或 ETS 中。当计时器触发时,该进程可以生成一个助手来删除RefNo来自主表的条目。

此时,您一定对崩溃感到好奇。拆除gen_server可能会崩溃。此外,整个节点可能崩溃。如果发生这种情况,您想如何重新安装计时器取决于您,但您应该考虑它的发生,以便解决它。假设我们再次出现并从磁盘加载计时器信息。您打算如何重新安装计时器?

一种方法是有AuxData包含有关超时点的信息。每隔一小时或十五分钟,你就会扫描整个桌子,删除不应该出现的人。事实上,您可以选择这是删除计时器结构的主要方法。是的,在最坏的情况下你会给人们 15 分钟的额外时间,但从代码角度来说可能更容易处理。至少它可以更好地处理节点(以及计时器)死亡的情况。

另一种选择是作弊,仅将计时粗略地存储在数据结构中,这使得查找起来非常便宜过去 5 分钟内所有过期的 RefNo然后每 5 分钟运行一次。批量做事情可能会更有效。例如,操作系统内核大量使用这种批量处理。

问题3

我一无所知timer-tm, 对不起 :)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我们如何有效地处理 mnesia 记录的时间相关约束? 的相关文章

  • 在Erlang中如何获取客户端的ip和端口?

    在下面的代码中 服务器正在侦听端口 2345 接受客户端的连接后 它返回 ok Socket start gt ok Listen gen tcp listen 2345 binary packet 4 reuseaddr true act
  • 何时“让它崩溃”以及何时捍卫 Erlang 中的代码?

    因此 带着 让它崩溃 的口号 Erlang 代码意味着能够抵御残酷的世界事件 例如意外拔出插头 硬件故障和不稳定的网络连接 另一方面 有防御性编程 https en wikipedia org wiki Defensive programm
  • 如何在 erlang 中格式化包含整数的平面字符串?

    在erlang中 我想格式化一个包含整数的字符串 并且我希望结果被展平 但我明白了 io lib format sdfsdf B 12312 115 100 102 115 100 102 32 12312 我可以使用下面的代码获得所需的结
  • Erlang 记忆的简单示例

    假设您有一个简单的函数 对于较大的值来说 它的成本可能会相当高 fact 0 gt 1 fact N gt N fact N 1 在哪里可以找到使用缓存 或记忆 函数值的简单示例dets 任何其他方便记忆的方法都将受到高度赞赏 根据您的情况
  • 在 Erlang 中确定传入 TCP/IP 连接的 IP 地址和端口

    我想获取传入 TCP IP 连接的 IP 地址和端口号 很遗憾gen tcp s accept and recv函数只返回一个套接字 而gen udp s recv函数还返回地址信息 有没有一种简单的方法来收集属于 Erlang 中套接字的
  • 使用 OTP 原理的非阻塞 TCP 服务器

    我开始学习 Erlang 所以我尝试写 hello world 并发编程 IRC 机器人 我已经使用 Erlang 编写了一个 没有任何 OTP 细节 管理程序 应用程序等行为 我希望使用 OTP 原则重写它 但不幸的是我无法找出使用 OT
  • `ejabberdctl start` 导致“内核 pid 终止”错误 - 我该怎么办?

    我用谷歌搜索了三个小时但没有结果 我有一个 ejabberd 安装 但不是使用 apt 安装的 它是从源代码安装的 其中没有名为 ejabberd 的程序 启动和停止 一切都是通过 ejabberdctl 进行的 它完美地运行了一个月 突然
  • Elixir - 递归列表值的总和

    只是尝试对列表值进行简单求和 defmodule Mth do def sum list do 0 end def sum list H T do H sum list T end end IO puts Mth sum list 1 2
  • 如何在没有任何服务器的情况下创建 P2P 网络聊天?

    有没有一种方法可以在没有任何服务器的情况下创建 P2P 网络聊天 可以 但是您必须决定见面地点 如果你的朋友把他的IP发给你 你就可以连接 那么你只需要告诉更多的人加入即可 一段时间后 你会变得越来越大 然后 如果网络上的某个链接发生故障
  • 为什么在 Erlang 中使用 OTP?

    正如问题所说 使用 Erlang 进行开发时 使用 OTP 设计原则会带来什么好处 我正在开发一个仅接收命令并发送响应的服务器 正如 Jonas 所说 OTP 是一组久经考验的设计元素和习惯用法 用于创建容错系统以及其他功能 例如灵活性 实
  • 随机排列列表中的元素(随机重新排列列表元素)

    我的程序的一部分要求我能够随机洗牌列表元素 我需要一个函数 当我给它一个列表时 它会伪随机地重新排列列表中的元素 安排的改变Must每次通话时都可以看到相同的列表 我的实现似乎工作得很好 但我觉得它相当长 并且正在增加我的代码库 而且 我有
  • Erlang TCP 套接字关闭

    为了学习 Erlang 我正在尝试实现一个基于gen tcp 不幸的是 我的代码似乎触发了一些有线行为 为了演示这个问题 我附上了我的实现的最小化版本 它足以重现该问题 无论 HTTP 请求是什么 它都只是传递静态 200 OK 当我尝试运
  • 在 Erlang 中使用完全限定的函数调用?

    我刚刚学习了如何在 Erlang 中升级模块 并且我知道只有使用完全限定名称的函数调用 例如module function 重新链接 到加载到 VM 中的当前版本 但未指定模块名称的函数调用不会 重新链接 到当前版本 而是继续使用旧版本 关
  • RabbitMQ 失败,错误:无法连接到节点rabbit@TPAJ05421843:nodedown

    在 Windows 7 Enterprise 计算机上 我全新安装了 Erlang 17 4 和 RabbitMQ 3 4 3 x64 安装成功且顺利 我还没有尝试创建我的第一个队列或交换器 但我已经看到了麻烦 这个问题类似于另一个SO帖子
  • 与共享数据相比,消息传递的性能损失

    最近有很多关于不使用锁和使用 Erlang 等消息传递方法的讨论 或者关于使用不可变的数据结构 例如函数式编程与 C Java 中的比较 但我关心的是以下几点 AFAIK Erlang 不保证消息传递 消息可能会丢失 如果还要担心消息丢失
  • 有没有办法对默认记录值进行查找?

    给定一个记录 record something id integer name string email undefined string undefined 有没有办法获取字段的默认值 在本例中得到的事实是 something email
  • Erlang 如何并发处理访问邮箱

    关于如何使用erlang邮箱的信息有很多 但很少找到一篇论文或文档描述erlang如何在VM内部同时实际访问邮箱 据我了解 Erlang VM 必须执行锁定或 CAS 操作以确保消息完整性 erlang幕后有没有什么精巧的方法 我假设您所说
  • 如何使用 ibrowse 将附件上传到 CouchDB 中的文档?

    我已经使用curl上传图像文件Penguins jpg 例如 C curl gt curl vX PUT H Content Type image jpeg http localhost 5984 DBNAME DOCID Penguins
  • 将 erlang shell 作为守护进程/服务运行

    显然 我有一个在 Erlang shell 中运行的 Erlang 程序 我想监视它 这就是我要的 当机器启动时 Erlang shell 应该随之启动 并且在 shell 中运行的程序也应该随之启动 如果 Erlang shell 由于某
  • Erl 无法连接到本地 EPMD。为什么?

    Erlang R14B04 erts 5 8 5 source 64 bit rq 1 async threads 0 kernel poll false Eshell V5 8 5 abort with G root ip 10 101

随机推荐

  • 用于遍历目录/文件树和输出树作为嵌套 UL 的 PHP 脚本 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我有一个目录 子目录和文件树 在一些但不是所有目录中 这是整个树的示例 food food drinks food drinks wa
  • 我应该将局部变量设置为常量还是可移动?

    我对本地范围内的任何对象的默认行为是使其const E g auto const cake bake cake arguments 我尝试尽可能少地使用非功能代码 因为这可以提高可读性 并为编译器提供一些优化机会 因此 在类型系统中也反映这
  • 同一工作表中的不同细胞保护

    在 Excel 工作表中 我想保护一个单元格 A1 不被编辑 另一个单元格 B1 不被格式化 这意味着用户 无法编辑A1的值 可以编辑B1的值 无法更改 B1 的格式 保护工作表 选项允许保护整个工作表的所有锁定单元格 因此 A1 和 B1
  • UIButton 自定义边框中的 Tintcolor

    我为圆形自定义边框创建了 UIButton 的子类 void drawRect CGRect rect self layer setCornerRadius CORNER RADIUS self layer setMasksToBounds
  • jQuery UI 可排序表格和单元格在拖动 tr 时缩小

    在拖动时我面临两个问题 当我有一个隐藏的表时 它本身正在缩小td 拖动 tr 单元格 td 正在缩小 这是可排序的代码 tbody sortable items gt tr appendTo parent opacity 1 contain
  • PyMongo 在大量查询后引发 [errno 49] 无法分配请求的地址

    我有一个MongoDB收集超过 1 000 000 份文档 我正在执行初始 find my query 返回这些文档的子集 约 25 000 个文档 然后我将其放入list object 然后 我循环遍历每个对象 解析列表中返回的文档中的一
  • 我的 SQL 动态查询执行并将输出获取到存储过程中的变量中

    我在 My sql 存储过程中生成动态查询 我想将此查询的结果放入输出参数中 这个怎么做 CREATE PROCEDURE searchInvoice OUT numOfRecords INT BEGIN DECLARE query1 TE
  • 这个 UWSGI 错误是什么意思? “ SIGPIPE:写入关闭的管道/套接字/fd ”

    有几个与此问题相关的问题 但它们都没有真正帮助我理解发生了什么 完整错误 SIGPIPE writing to a closed pipe socket fd probably the client disconnected on requ
  • 在 Android 中将数据从 Activity 发送到 Fragment

    我有两节课 第一个是活动 第二个是我有一些的片段EditText 在活动中 我有一个带有异步任务和方法的子类doInBackground我得到一些结果 并将其保存到变量中 如何将此变量从子类 我的活动 发送到此片段 从 Activity 中
  • 从 parse.com 获取 objectId

    所以我正在构建一个使用 parse 作为后端的应用程序 我以前写过自己的 但我想我会节省一些时间并使用解析 我正在使用解析中的数据填充表视图 这很好 我想从解析数组构建的字典中获取 objectId 我的数组的输出如下
  • 漏洞! “语义分析”阶段的异常

    我有一个使用 Gradle 1 10 和 jdk1 8 的 1 1 7 spring boot 应用程序 我使用 Groovy Spock 进行测试它有两个依赖项 使用 Apache Maven 3 1 1 和 jdk 1 8 构建的 ja
  • 每个配置文件中的部分只能出现一次!为什么?

    我收到以下异常 每个配置文件中的部分只能出现一次 有关例外情况 请参阅帮助主题 我的配置文件看起来像这样
  • Sass - 安装错误[重复]

    这个问题在这里已经有答案了 我最近安装了 Ruby gem Sass 并且经常将它用于我正在开发的应用程序 今天我像平常一样去运行 sass watch scss css 并注意到我收到以下错误 bash sass command not
  • 故障转储分析:CxxUnhandledExceptionFilter

    我有一个崩溃小型转储需要分析 我的程序是多线程Qt5应用程序 我不是调试专家 但通常我可以轻松找到程序失败的地方 但这次我不能 我在 Visual Studio 2010 中打开转储文件 单击 仅使用本机调试 它向我显示问题所在 它是位置为
  • 有界上下文、子域和通用语言

    a 对于包含两个或多个子域的 BC 存在概念重叠的可能性 甚至更糟糕的是 相同的概念 由其中几个子域使用 可能会被每个子域以不同的方式解释 理解 无论如何 如果 BC 确实包含许多子域 它是否应该提供几种通用语言 每个子域一种 或者所有子域
  • Gson ClassCastException(LinkedTreeMap)

    Using Gson反序列化参数化类的对象Container
  • 将react-route-dom中的语法从“Switch”更改为“Routes”,但浏览器中仍然没有显示

    我正在创建一个 Google 克隆 这是我当前的代码 我读到 考虑到反应路由器的更新 我需要将语法从 Switch 更改为 Routes 我这样做了 但我的 这是搜索页面 没有显示在浏览器内部 import React from react
  • C#:Resharper 的替代品,C# 版本 [重复]

    这个问题在这里已经有答案了 这对我来说不太便宜 149 美元 我尝试过 但我很喜欢它 对我来说最酷的事情是重构为 LINQ 所以我想知道是否有一个更便宜的替代方案可以做到同样的事情 将我的循环重构为更小的 LINQ 循环 DevXpress
  • python文本框中文本和滚动条的自动滚动

    我有一个 tkinter 文本 和 滚动条 工作正常 在我的程序中 文本窗口中的行会自动不断添加 因此 当插入新的文本行且数据超出限制时 我希望文本和滚动条自动滚动到底部 以便始终显示最新的文本行 这个怎么做 另外 如何链接文本窗口和滚动条
  • 我们如何有效地处理 mnesia 记录的时间相关约束?

    我正在将记录写入mnesia 该记录应该保存在那里 仅在允许的时间 24 小时 内 24小时后 在用户修改其中的一部分之前 系统应该自动删除它们 例如 用户获得免费通话时间 用于语音通话 他们应该在给定时间内使用它们 如果他们不使用它 24