How is cache.clear() supposed to work?

I hope I’m posting the right place with this.

I am trying to clarify the intented behaviour of cache.clear(), and perhaps get the documentation updated.

I have recently experienced what I think is a bug, that led me to ask this question at the django-redis project.

In short: I have configured multiple caches on the same Redis database, but with different prefixes. Onte of these caches must be cleared completely on certain events, and of course I reached for cache.clear(), but to my surprise this also cleared the other caches on the same database.

I cannot imagine that this is as intented, but I would like to hear it from someone who is deeper into the Django machine room.

This is exactly how it is intended, and as it is documented.

From the docs you linked:

Finally, if you want to delete all the keys in the cache, use cache.clear() . Be careful with this; clear() will remove everything from the cache, not just the keys set by your application:

This means exactly what it says - “… delete all keys in the cache, …” and “… will remove everything from the cache …”

Also, if you look at the implementation of cache.clear you’ll see that it calls flushdb.

From the docs for FLUSHDB:

Delete all the keys of the currently selected DB. This command never fails.

So yes, I would say that this is clearly working as designed.

I see your point. Especially after reading up on the meaning of the options.

I guess I just expected the KEY_PREFIX to be a part of the equation when invokong .clear() without thinking too much of it, but it seems you are right, that it is meant to apply to the whole LOCATION, regardless of whether we are sharing that internally, or between different services or applications.

I think the documentation could be a bit clearer on this, but I guess it’s resolved for now.

I actually think it’s a shame that the standard API does not have better means managing content distinguished by KEY_PREFIX. I use it frequently in favour of having to prefix keys manually to avoid clashes. Often caches have a relatively small number of keys, but they have big impact on performance. The ability to get the keys of a cache is also valuable for unit tests. Luckily django-redis made .delete_pattern() and .keys(), so I’m good for now, but it would be nice if the standard API would have something similar, so you are not tied to a single backend when using KEY_PREFIX.

I think the reason the prefix isn’t taken into account is that memcached, the original backend, doesn’t (or didn’t) have a way to delete by prefix—just clear the whole thing. Similarly for the local memory backend, which is backed by a Python dict. Clearing by prefix is typically an O(n) operation rather than the (potentially) O(1) runtime for clearing everything.

Maybe there’s scope to add a parameter to clear() or similar to allow clearing by prefix, given Redis’ popularity.

2 Likes