How to atomically update a counter shared between Docker instances How to atomically update a counter shared between Docker instances docker docker

How to atomically update a counter shared between Docker instances


It looks like for your case database is overhead. You just need some distribute lightweight key-value storage with shared key lock support. Here are some candidates:


The --ipc option of docker run enables shared-memory access between containers:

IPC settings (--ipc)

--ipc="" : Set the IPC mode for the container,

'container:<name|id>': reuses another container's IPC namespace

'host': use the host's IPC namespace inside the container

By default, all containers have the IPC namespace enabled.

IPC (POSIX/SysV IPC) namespace provides separation of named sharedmemory segments, semaphores and message queues.

Shared memory segments are used to accelerate inter-processcommunication at memory speed, rather than through pipes or throughthe network stack. Shared memory is commonly used by databases andcustom-built (typically C/OpenMPI, C++/using boost libraries) highperformance applications for scientific computing and financialservices industries. If these types of applications are broken intomultiple containers, you might need to share the IPC mechanisms of thecontainers.

This article provides some demonstration of its usage.


I was facing a similar problem, and decided to dig in it head on.

The only thing that goes fast is domain sockets. So i created a small c-program that listens on a domain socket, on a shared volume /sockets.

see a working concept on test on gitlab.com.

counter.c does the job, listens on sockets/count.sock andon receipt of a single char in a datagram:

  • '+' : it will increase the count and return the count as an u_int64_t
  • '0' : resets the count and return the 0 value as an u_int64_t
  • '=' : returns the count as an u_int64_t, without increment
  • '-' : decrement count with one and returns count as an u_int64_t

for concept testing:

  • counter --interval=1000000 => starts the counter
  • test_counter --repeats=100000 stress => sents 100k request to the socket
  • test_counter reset set's counter to 0
  • test_counter --quiet --strip result returns the counter without \n
  • test_counter [count] increments the counter and returns result.

2 docker containers are build: count & test repo

and to test, I used docker-compose.yml in a gitlab-runner:

my-test:    image: dockregi.gioxa.com/dgoo2308/dockersocket:test    links:    - counter    entrypoint:    - /test_counter    - --repeats=${REPEATS}    - --timeout=200    - stressvolumes:- './sockets:/sockets'counter:    image: dockregi.gioxa.com/dgoo2308/dockersocket:count    volumes:    - './sockets:/sockets'    entrypoint:    - /counter    - --start_delay=100    - --interval=${TARGET}

to start test:

mkdir socketsdocker-compose pull --paralleldocker-compose up -ddocker-compose scale my-test=$SCALE

Concept Test Success full!!! see test Job

cavecat:

for client implementation, client socket cannot be bind as auto, but need to be given a name, see in test we use the hostname, mapped in the same /sockets volume.Also they need to be different for each client.