是否提供了一次性更新和读取的方法 - 如增量操作?

Cha*_*gwu 2 erlang increment ets

在设置标准的Cowboy Web处理例程之前,我在我的开始(_StartType,_StartArgs) - >函数中初始化了一个命名的ets表.

ets:new(req_stats,[named_table,public]),ets:insert(req_stats,{ req_count,0})

我有这个功能:

 count_req()->
    [{_,Cnt}]=ets:lookup(req_stats,req_count),
    ets:insert(req_stats,Cnt+1),
    Cnt+1.
Run Code Online (Sandbox Code Playgroud)

我关心的是这个;

如果我在高负载下为每个Web请求调用count_req(),我很可能会得到一个不准确的计数,因为[{_,Cnt}] = ets:lookup(req_stats,req_count)可能会在我返回之前多次更新CNT + 1

是否提供了一次性更新和读取的方法 - 如增量操作?

谢谢.

leg*_*cia 8

您可以使用ets:update_counter/3:

ets:update_counter(req_stats, req_count, {2, 1})
Run Code Online (Sandbox Code Playgroud)

也就是说,将元组的第二个元素递增1,并返回新值.


在Erlang/OTP 18.0(2015-06-24发布)中,ets:update_counter/4介绍了.它允许您提供默认值,以便在表中尚未存在键时使用.因此,如果您希望计数器在第一次递增后变为1,请将0作为默认值:

1> ets:new(req_stats, [named_table]).
req_stats
2> ets:tab2list(req_stats).
[]
3> ets:update_counter(req_stats, req_count, {2, 1}, {req_count, 0}).
1
4> ets:tab2list(req_stats).
[{req_count,1}]
Run Code Online (Sandbox Code Playgroud)