This has been bugging me for a while until I found this question and answer. I just want to add some things I've learnt.
You can easily reproduce this problem with a local memcached instance:
from django.core.cache import cache
import os
def write_read_test():
pid = os.getpid()
cache.set(pid, pid)
for x in range(5):
value = cache.get(pid)
if value != pid:
print "Unexpected response {} in process {}. Attempt {}/5".format(
value, pid, x+1)
os._exit(0)
cache.set("access cache", "before fork")
for x in range(5):
if os.fork() == 0:
write_read_test()
What you can do is close the cache client as Django does in the request_finished
signal:
https://github.com/django/django/blob/master/django/core/cache/init.py#L128
If you put a cache.close()
after the fork, everything works as expected.
For celery you could connect to a signal that is fired after the worker is forked and execute cache.close()
.
This also affects gunicorn when preload is active and the cache is initialized before forking the workers.
For gunicorn, you could use post_fork
in your gunicorn configuration:
def post_fork(server, worker):
from django.core.cache import cache
cache.close()