9👍
You need a distributed lock manager at the point where your app suddenly needs to run on more than one service. I wrote elock for this purpose. There are bigger ones and others have chosen to ignore every suggestion and done the same with memcached.
Please don’t use memcached for anything more than light advisory locking. It is designed to forget stuff.
I like to pretend like filesystems don’t exist when I’m making web apps. Makes scale better.
17👍
If you use RDBMS, you can use its “LOCK” mechanism.
For example, while one “SELECT FOR UPDATE” transaction locks a row, the other “SELECT FOR UPDATE” transactions with the row must wait.
# You can use any Python DB API.
[SQL] BEGIN;
[SQL] SELECT col_name FROM table_name where id = 1 FOR UPDATE;
[Process some python code]
[SQL] COMMIT;
- [Django]-Django rest framework datetime field format
- [Django]-Django: Error: Unknown command: 'makemigrations'
- [Django]-Why middleware mixin declared in django.utils.deprecation.py
16👍
Use the Django builtin select_for_update function.
https://docs.djangoproject.com/en/1.8/ref/models/querysets/#select-for-update
From the docs:
Returns a queryset that will lock rows until the end of the transaction, generating a SELECT … FOR UPDATE SQL statement on supported databases.
For example:
entries = Entry.objects.select_for_update().filter(author=request.user)
All matched entries will be locked until the end of the transaction block, meaning that other transactions will be prevented from changing or acquiring locks on them.
- [Django]-How do you include a csrf token when testing a POST endpoint in django?
- [Django]-Django: Best way to implement "status" field in modules
- [Django]-CSRF with Django, React+Redux using Axios
5👍
You could use simple file locking as a mutual exclusion mechanism, see my recipe here. It won’t suit all scenarios, but then you haven’t said much about why you want to use this type of locking.
- [Django]-What is the difference between HttpResponse vs HttpResponseRedirect vs render_to_response?
- [Django]-Django: why i can't get the tracebacks (in case of error) when i run LiveServerTestCase tests?
- [Django]-What's the difference between select_related and prefetch_related in Django ORM?
3👍
I ended up going with a solution I made myself involving file locking. If anyone here ends up using it remember that advisory locks and NFS don’t mix well, so keep it local. Also, this is a blocking lock, if you want to mess around with loops and constantly checking back then there is instructions in the code.
import os
import fcntl
class DjangoLock:
def __init__(self, filename):
self.filename = filename
# This will create it if it does not exist already
self.handle = open(filename, 'w')
# flock() is a blocking call unless it is bitwise ORed with LOCK_NB to avoid blocking
# on lock acquisition. This blocking is what I use to provide atomicity across forked
# Django processes since native python locks and semaphores only work at the thread level
def acquire(self):
fcntl.flock(self.handle, fcntl.LOCK_EX)
def release(self):
fcntl.flock(self.handle, fcntl.LOCK_UN)
def __del__(self):
self.handle.close()
Usage:
lock = DJangoLock('/tmp/djangolock.tmp')
lock.acquire()
try:
pass
finally:
lock.release()
- [Django]-Displaying the model's__unicode__ in django admin
- [Django]-Django QuerySet order
- [Django]-Django 1.8 – what's the difference between migrate and makemigrations?
2👍
I did not write this article, but I found it supremely helpful faced with this same problem:
http://chris-lamb.co.uk/2010/06/07/distributing-locking-python-and-redis/
Basically you use a Redis server to create a central server that exposes the locking functionality.
- [Django]-Django: How to override unique_together error message?
- [Django]-How to express a One-To-Many relationship in Django?
- [Django]-Django — How to have a project wide templatetags shared among all my apps in that project