Re:Lovely Week with Elixir
by winrid on Wednesday May 20, 2020 @04:18PM
(#23251270)
Wait, how does that answer prevent only one instance of the job across the whole system? That's what I'd use Redis or something for - for locking.
[ Parent
| on HN ]
If there is only one process running this GenServer, there will only be one instance of the job in the system.
An BEAM process, and therefore a GenServer, has an atomic message queue built in. Only the process itself can pop messages out of its queue, so there is no need for locking. It is not possible to get messages out of the queue concurrently. Messages can be processed concurrently, but that's after they've already been removed from the queue.
What if you have 100 servers running the same application code and you just want to run this job, one time, for a customer? Usually I'd use a Cron with a distributed lock, which is served via Redis.
Just curious as to how the BEAM solves it as I imagine it can.
You can use tricks like the global spawn option to make processes globally unique. Doesn't scale infinitely, but for a 2->low double digits HA/load balanced system it should be fine.
Oh wow, so this will work across multiple instances of the BEAM?
If they are clustered using erlang clustering, yes. https://erlang.org/doc/man/global.html
Note that this works by taking a transaction lock on the entire cluster, so it's not recommended if you're making requests frequently. It also doesn't respect netsplits, unless you instruct in code to fail with a deficient cluster membership.