Welcome Guest, Not a member yet? Register   Sign In
Caching Models with Memcached?
#11

[eluser]dmorin[/eluser]
I understand where you're coming from, but I have a few questions. In your example above (unless I'm reading it wrong), a write query would just be passed to the database to do its work but it wouldn't invalidate the select query that's already cached.

For example, let's say I run your select query and get all rows where id is greater than 0. The query result is cached and I can use it again next time. Now, I insert 100 rows, update 20, and delete 5. Because the write queries don't invalidate that select query, running the select query again will get the original results from memcached which are now invalid and out of date. You might say that you can simply invalidate this one query from each of the write queries, but when you have more than one select query that could have potentially cached a row, especially when you start talking about joins, it gets even more complex.
#12

[eluser]freakylp[/eluser]
[quote author="dmorin" date="1231965501"]I understand where you're coming from, but I have a few questions. In your example above (unless I'm reading it wrong), a write query would just be passed to the database to do its work but it wouldn't invalidate the select query that's already cached.

For example, let's say I run your select query and get all rows where id is greater than 0. The query result is cached and I can use it again next time. Now, I insert 100 rows, update 20, and delete 5. Because the write queries don't invalidate that select query, running the select query again will get the original results from memcached which are now invalid and out of date. You might say that you can simply invalidate this one query from each of the write queries, but when you have more than one select query that could have potentially cached a row, especially when you start talking about joins, it gets even more complex.[/quote]
Yeah I agree , but there is no problem with that.

When you need to delete and update $this->load->database() is called.
You need first update or delete to be able to retrieve valid results from the database.
This is the first way to have fresh data.
Other way is set again ( rewrite ) old data. I didnt think about.It depends only of your needs.If you dont need of fresh data anytime that is not a bad idea.

If you want fresh data you can cache data only for one client ( user ). / I mean personal cache.

When you need of more complex stuff , you need of more complex solution.
#13

[eluser]dmorin[/eluser]
Quote:When you need of more complex stuff , you need of more complex solution.

Which was the original point of this thread, optimal way of caching data in the processed state while making sure you always had the most up to date information. Because of the way I use models, caching the model object seems like the way to go.
#14

[eluser]freakylp[/eluser]
Im not so quite sure about caching models.
First of all you dont have the same queries except if you have only static queries ( with static I mean queries without any dynamic parameters ).

Caching models is not solution.If you cache the model you will not have fresh data too.
Lets say that we have News_model which has 3 methods.
News_model.php
Code:
public function Get_News_By_Id( $news_id )
    {
        $news_id = (int)$news_id;
        $query = $this->db->query("SELECT * FROM news WHERE id = '$news_id'");
        return $query->result();
    }
    
    
    
    public function Get_News_Title( $news_id )
    {
        $news_id = (int)$news_id;
        $query = $this->db->query("SELECT title FROM news WHERE id = '$news_id'");
        return $query->result();
    }

Lets say that we have a News_Controller:
News_Controller
Code:
class News_Controller extends Controller{

    public function __construct()
    {
        parent::__construct();
        $this->load->model('News_Model','news');    
    }
    
    
    public function Index()
    {
        $this->data['news']     = $this->news->Get_News_By_Id(5);
        $this->data['title']    = $this->news_Get_News_Title(5);    
    }
    
}

If we cache $this->news and parameter of methods of News_Model are not the same we will have 1 copy of News_model object resource but we dont have the same data.

What we shall do ?
#15

[eluser]dmorin[/eluser]
Quote: However, I’m using models in more of an ORM sense where each instance of the model represents one database record. The models have their own get and save methods. Also, if there’s something processor intensive, I save it to a class var in case I need to reference it multiple times within a page load. Because of all of this, I thought it would be ideal to cache the object instances themselves instead of just the db results. It would also be much easier to invalidate these versus invalidating individual queries.

That's from reply #2 in this thread. I use models differently than you. Mine actually model the information in the database instead of just providing a repository for queries. Anytime I need to modify a record in the database, I do so with this model. That's the difference.

Post #5 about using __sleep() is probably the best answer for this situation.
#16

[eluser]Phil Sturgeon[/eluser]
Could you not store values in an array/object property of the database and use some obverloading with __set() and __get() to access them?

That way you only need to memcache one property which would essentially be your instance, and you don't get all the extra base class code in there.
#17

[eluser]dmorin[/eluser]
You can use serialize() to serialize an object in which case it only stores the values of any class variables, not all of the function/methods/etc. My ORM-like models store an array of the current data record, so it would get cached. The issue that prompted me to start the thread is that CI loads the global CI instance into a var in each object so that you can do $this->db or use any other loaded reference. Because these are loaded, they also get serialized.

So my solution is to not extend the parent Model controller when creating these models. Instead, I'll use the trick used for libraries:

Code:
$this->CI = get_instance();

Then, before the object gets serialized, the __sleep() function is called automatically which I can use to unset $this->CI. When something is unserialized, such as when it is restored from memchached, it calls the __wakeup() method which I can use to restet the CI var.

Again, the advantage of this approach is that if I always use the models to represent the rows in the database, I never have to worry about invalidating old data. But there are other downsides, so I'm not sure its the best solution yet. Hope that makes sense.
#18

[eluser]Unknown[/eluser]
I agree with dmorin that it's tricky to cache queries with memcache and easier to invalidate with memcached models. I heard about facebook successfully scaled with memcache recently. Here's a note from their engineering. just an interesting read:
scaling out at facebook




Theme © iAndrew 2016 - Forum software by © MyBB