在 erlang 中同步外部状态(例如来自数据库)

synchronizing an external state (e.g. from a db) in erlang

假设有一家在线售票处出售 100 张门票。 如果同时有许多购买门票的请求,则存在竞争条件的风险,因为可能同时有 2 个(或更多)请求试图购买最后一张门票。而如果软件统计已经售出的票数,有可能对于同时进来的两个请求,计数器会return99(所以还剩一张票)。 因此,该软件可能会售出 101 张门票(而不是仅售出 100 张门票)。 在大多数命令式语言中,您可能会使用诸如关键字“synchronized”之类的东西(例如在 Java 中),以确保计数和销售是“原子”操作,在前一个之前没有其他请求可以进入请求已经处理完了吧?

但是,您将如何在 erlang 中执行此操作?

我的意思是函数中没有“状态”,对吧?许多请求可以同时进入,从计算已售出门票的柜台(例如来自数据库)获取数字 99...

那么,在erlang中怎么走?

Erlang 中的原子操作

Erlang 进程不共享内存,因此无需同步对每个进程内存的访问。
ETS, which allow shared access, have ACID properties in most methods, e.g. ets:update_counter/3
此外,由于仅将 ETS 用于计数器会产生大量开销,因此在 OTP21

中为 shared atomic integers 提供了更多 low-level 接口

干得好(这是主观的)

通常的方法是开始使用单个进程(或进程池),利用参与者模型 + 消息传递来提供原子性。由于一个进程负责它自己的内存,因此它本身不存在竞争条件。在您的示例中,这意味着每个商店都有一个流程,并且客户会与他们互动。

大多数情况下这就足够了(先发制人 scheduling/domain 拆分创造奇迹),但如果不够,您可以探索 ETS/atomics-based 解决方案(原子操作并不是 ETS 唯一有趣的特性和原子,它们也有其他用途)

外部状态

我故意省略了对“外部”状态的任何引用,因为在那里你开始不得不处理现实世界:多个节点、崩溃节点、网络分裂......而“同步”并不能解决你那里的问题.
同步分布式状态需要更多的工作,有时复杂性不值得,有时这种复杂性被转移到另一个系统,例如数据库。