Mnesia 中安全、顺序且可扩展的计数器
我正在 Erlang/OTP 中编写一个应用程序,并希望在版本记录系统上使用顺序计数器。
我首先用
mnesia:dirty_update_counterbut the experience of using it drove out these hard requirements:
计数器必须具有以下属性:
严格顺序 - 后面跟着 1 2 后跟 3 等等 该序列在一组分布式系统之间共享,如果我 把你打成“3”然后你就来了 在“5”中我需要知道我们输了 一些通信应该重新同步
与分布式数据库安全
mnesia:dirty_update_countermeets neither of these requirements.
我如何实现顺序数据库计数器?
I am writing an application in Erlang/OTP and want to use sequential counters on a version recording system.
I first implemented them with
mnesia:dirty_update_counter
but the experience of using it drove out these hard requirements:
The counters must have the following properties:
be strictly sequential - 1 followed
by 2 followed by 3 etc, etc
the sequence is shared across a distributed set of systems and if I
have you down as a '3' and you come
in a '5' I need to know we have lost
some comms and should resyncsafe with a distributed database
mnesia:dirty_update_counter
meets neither of these requirements.
How could I implement a sequential database counter?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
好吧,由于 Mnesia 数据不能保证以原子方式复制,因此您必须以某种方式手动锁定。 我看到三种替代方案(两种带锁定,一种不带锁定):
在
当您请求新版本时表
数字。 这意味着交易
不过。
使用中央服务器进行跟踪
版本号和增量
他们原子地,例如通过
在你的一个节点上有一个进程
您要求提供版本号。
同步您的服务器
使用 NTP 并使用时间戳。
Well, since Mnesia data is not guaranteed to replicate atomicly you have to manually lock somehow. I see three alternatives (two with locking and one without):
Using read locks on the
table as you request a new version
number. That implies transactions
though.
Use a central server that keeps track
of the version numbers and increment
them atomically, for example by
having a process on one of your nodes
which you ask for version numbers.
Synchronize your servers
with NTP and use timestamps.
您考虑过消息代理吗? 您可以通过加载 RabbitMQ 并设置持久队列和持久消息来将其保留在 Erlang 中。 构建一个消费者,将消息正文中的数字加 1,然后在确认原始数字时将该新数字发布回新消息中的队列。
不确定它是否适合您,但似乎一旦您手动发布正文中包含 1 的第一条消息,您就会关闭并运行。
Have you though about a Message Broker? You could keep it in Erlang by loading up RabbitMQ and setting up a durable queue and persistent messages. Build a consumer that increments a number in the message body by 1 then publishes that new number back to the queue in a new message as it acks the original one.
Not sure it would work for you but it seems like once you manually publish the first message with 1 in the body you would be off and running.
我打算推荐一个为你提供数字的 erlang 进程。 由于 erlang 按顺序处理消息,因此可以保证按顺序获取它们。 无论如何,坚持它们是必要的。 上面的 RabbitMQ 建议是一种方法,但如果您觉得它太过分了,那么只需定期将进程存储到文件中就足够了。 gen_server 应该足以满足您的目的。
I was going to suggest an erlang process that serves up numbers for you. Since erlang processes messages sequentially you would be guaranteed of getting them in order. Persisting them would be necessary somewhow. The RabbitMQ suggestion above is one way but if you feel like it's overkill then just having the process store to a file periodically should be sufficient. A gen_server should be sufficient for your purposes.
也许最简单的答案就是您正在寻找的,只需获取写锁(用于复制同步)并创建一个事务函数来获取计数器的当前值,增加它并将其保存回数据库。 当然,随着系统的扩展,您的开销会增加,但我建议编写一个服务器来为您执行此操作并在节点的子集上运行它,因此锁争用与集群大小不直接相关。
Perhaps the simplest answer is what you are looking for, simply by getting a write lock (for replicated syncing) and making a transactional function that gets the current value of the counter, increments it and saves it back to the DB. Certainly you will get increased overhead as the system scales, but I would recommend writing a server that does this for you and run that on a subset of the nodes, so the lock contention is not directly linked with the cluster size.