Skip to content

clarification of how invalidation works #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vesper8 opened this issue Jan 16, 2018 · 10 comments
Closed

clarification of how invalidation works #59

vesper8 opened this issue Jan 16, 2018 · 10 comments

Comments

@vesper8
Copy link
Contributor

vesper8 commented Jan 16, 2018

I was just wondering if you could clarify how the invalidation works exactly

from the docs you said that if you don't use a cache driver that supports tags, then anytime a new model is added the entire cache will be flushed

is it then the case that if you do use a driver that supports tags.. that anytime any user adds a new model (a comment for example) then this will trigger what exactly? all cache related to comments for all users will be flushed ?

it seems it would be useful to have a way to customize our own invalidation logic.. through the configuration file

perhaps this could serve as inspiration, another excellent caching package that I use
https://github.com/spatie/laravel-responsecache/blob/master/config/responsecache.php

another question please.. you say it's a bad idea to cache users.. I agree inherently but then if the invalidation works perfectly then why not exactly?

but in any case, let's say you don't cache the user model.. what about all the relations between the user and other models? if those models extend your CacheModel then the relations will be cached but not the user ?

@vesper8
Copy link
Contributor Author

vesper8 commented Jan 16, 2018

I see that right now you're using rememberForever all over the place...

that could quickly lead to a problem where the cache fills up.. I'm not sure if there's some kind of automatic garbage collection that would happen here.. but I think it would be preferable to allow us to configure how long things should be cached for

@mikebronner
Copy link
Owner

@vesper8 Thats a good point. Memcached automatically flushes stale items, and I believe Redis dumps items if it runs out of memory.

But it is not really forever, since you will invariably add new records to all of your models at some point, which will flush the cache. And if you don't ever add, update, or remove a specific model in your database, then the forever cache is what you want. (Any time you add, update, or remove a record of a given model, that model's cache is invalidated.)

If you use a cache without tag support, then the entire cache (not just the items pertaining to models) will be flushed. There is no way around that. The best solution then is to create a cache connection specific to model-caching (which you can configure), then only that cache is flushed. You may wish to create two Redis or Memcached cache instance: one for your app in general, and another for the model cache. That way you don't have to worry about your app cache being flushed unexpectedly. :) I should add this to the documentation.

@vesper8
Copy link
Contributor Author

vesper8 commented Jan 16, 2018

@mikebronner Thank you for explaining. I guess you're right it's not really forever at all because of the way it aggressively invalidates currently.

Would there be a way to make this less aggressive on the invalidation part? Right now for example I have thousands of users and they have many model relationships. One example is users can post comments in threads.

Right now threads and comments are cached and that's fine. If someone adds a new thread then yes it makes sense to invalidate caches that contains threads because otherwise the new thread won't show up

However if a user adds a new comment to a single thread.. then it is kind of a huge performance hit if suddenly this invalidates ALL comments cache when ideally it should only invalidate the comments for the specific thread where the comment was added.

In an application where you have lots of users constantly adding comments.. like multiple times per minute.. then this would mean that the cache for all comments would be constantly flushed and basically it is as if it wasn't cached at all.. possibly making the performance even worse because of the constant cache-filling and cache-flushing

I could come up with many other examples where a full tag flush would be basically overkill and counter-productive.. could this be improved by adding model-ids to the tags ?

What are your thoughts on this?

@mikebronner
Copy link
Owner

Hi @vesper8,

Due to the nature of Eloquent relationships the entire "stack" of a given model must be flushed anytime a model record is updated. You are right, if you have a updates-versus-reads ratio of 1:1 then caching makes no sense. However, you are likely to have more reads than writes, so it will increase performance overall.

By implementing caching you are not actually taking a performance hit, but rather eliminating one - the processing it takes to implement the cache is negligible from what I can tell. So think of it like this: if users are updating comments multiple times per minute during peak hours, you might not be gaining much, however, you will benefit during off-peak hours.

I do see your point. Unfortunately I don't see an elegant solution for it in this package.

I could look into optimizing the cache for relationships when child-elements are added, say comments are added to a given post, then it would only flush the cache for that post, like you say. I will have to ponder on this and see how it would be best implemented.

Thank you for walking me through your scenario! :) You definitely have good ideas, implementing them may be more difficult, though . :)

@mikebronner mikebronner added this to the 0.3.0 milestone Feb 13, 2018
@srottem
Copy link

srottem commented Feb 22, 2018

I can certainly see value in providing a feature to allow individual models to override how long they will be cached for as per the comment by @vesper8 a few days back. For example, I might not mind a specific model being stale for 5 minutes and I perform some direct database updates to that model's table. It would be great to still be able to benefit from caching in this circumstance without having to flush the entire cache for that model.

@mikebronner
Copy link
Owner

Yes, this is definitely an interesting use-case. I will keep thinking on this. For the short term, I don't see this being implemented just yet, until the package is refined some more.

@mikebronner
Copy link
Owner

I'm going to close this issue, as the thread diverged from the original request, but will open a new issue to keep the idea alive.

@bitclaw
Copy link

bitclaw commented Dec 7, 2018

I see that right now you're using rememberForever all over the place...

that could quickly lead to a problem where the cache fills up.. I'm not sure if there's some kind of automatic garbage collection that would happen here.. but I think it would be preferable to allow us to configure how long things should be cached for

This actually happened to us on a high traffic web site. We had switched to redis for caching and it consumed our 16GB of RAM on our redis instance in a couple of hours. Then I had to switch to file based caching and setup a scheduled task to clear the cache every three hours or so.

@mikebronner
Copy link
Owner

@bitclaw
I believe it comes down to configuring redis or memcached correctly. You want to set up a max-memory usage, and it should then manage itself. Cache memory filling up is not a bad thing, it's just a problem if it doesn't release old data to make room for new data.

The key here is to configure redis appropriately, as that part is out of the hands of this caching package.

@bitclaw
Copy link

bitclaw commented Dec 7, 2018

@bitclaw
I believe it comes down to configuring redis or memcached correctly. You want to set up a max-memory usage, and it should then manage itself. Cache memory filling up is not a bad thing, it's just a problem if it doesn't release old data to make room for new data.

The key here is to configure redis appropriately, as that part is out of the hands of this caching package.

Thank you for getting back to me. That makes a lot of sense, I believe for redis you can set the max memory usage https://redis.io/topics/lru-cache.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants