Welcome to the Question2Answer Q&A. There's also a demo if you just want to try it out.

Let's all brainstorm to solve this caching issue once for all

+7 votes
679 views
asked Feb 28, 2016 in Q2A Core by Waterfr Villa

Lets all brainstorm to get this thing done.

Few considerations:

1- Ideally we need to cache every single page( question pages, front page, list views, user pages, ) except admin-only pages

2- Each time an event fires, cache copy of pages affected by this event have to be updated.

3- Plug-ins also have to get notified of this cache page updates.

Two very typical scenario:

Scenario 1. A user answers a question.

- As a result his/her score has to be updated in his/her user page, the activity page, the question page, the questions list page, walls of other users if he/she has posted anything.

 

Scenario 2.  Each time a page gets visited, its cached version has to be updated too. why? because page views are displayed in question pages at the top.

In one word, each time there is an update/write to db, the corresponding cached pages have to be updated too (except the admin ones) .

Very expensive to implement right?

Suggesting approach:

so we need to lower our expectation and only concentrate on updating caching for more important stuff and leave some of the components to be later read and updated via ajax calls (e.g. users scores, page views, votes etc)

convention:

- Lets call important stuff like questions, answers, comments and the scaffoldingof the page (related CSS and HTML DOM) class 1 component

- Lets call user scores, vote values, flag values etc, class 2 components 

Example: For a question page, the question itself, the answers, the comments to be cached and leave the rest to be updated by ajax calls only after entire page is fully loaded ( from cache copy).

1- Each time a question or answer or a comment is posted/updated (class 1 components changed), update the cache of corresponding pages.

Updating or creating a cache for a page means: rendering entire page (class 1 and class 2) and storing them all together as cached copy

2- Each time a page is requested:

if (the cache copy of that page is available)

     { -load cache copy (the class 1 components  which are up to date and correct + cached copy of class 2 which might not be up to date )

       - update class 2 components like users scores, votes, flags by ajax calls

     e.g. the users sees the entire page loaded quickly and notices that the user A had score 85, but after 1-2 second his/her score get updated to value 93.

     }

else {

      - load class 1 components of the page from db

      - update class 2 components by ajax calls to db     

      - update the cache copy of that page

       }

I "think" this approach can also take care of complications the third party plugins add too

 

Question: is this possible?

----------------------------------------

Please kindly avoid posting comments like, it is not that easy, it needs time etc. Instead try to contribute please

 

 

 

Q2A version: 1.7x
commented Feb 28, 2016 by q2apro
Also consider plugins like the live events. It does a query on each page load. This is uncachable... or we start using more ajax and inserting the returned html in a prepared liveevent box.

2 Answers

+5 votes
answered Feb 29, 2016 by Scott
Here's some of my thoughts and issues I've run into.

Caching is hard! Especially with Q2A's plugin system, because any plugin can output a different thing on every page load depending on their IP, browser, or just plain randomly. For some plugins it may not matter if the same thing is shown to multiple people (e.g. a random question widget), but some it certainly does (e.g. location-based content or browser detection). We also use server-side detection for the mobile theme.

For these reasons, full-page caching is basically ruled out.

The route I'm currently taking is query caching. With a lot of visitors MySQL becomes the bottleneck (on my site mysql appears to be using most of the CPU).

The first solution I looked at was adding a "cachekey" element to the selectspec array (see db/selects.php). For example the query to get question #1234 would have a key like "question|1234". When the query is about to get executed we can look for that key in our cache, and get the previous results.

The main problem was that on a question page, there are 9 queries for getting basic information about a question, its answers, comments, duplicates etc. Storing each of those individually will bloat the cache (9 x 10,000 questions = 90,000 cache files) and reading all those files individually probably doesn't save much time (reading from the filesystem takes time as well).

So at least for that page, we'll cache all 9 queries in one file per question. The "cachekey" option above still works fine for other pages though, and even plugins should be able to hook into it.

In conclusion: I think I've finished my research/trial stage. Now I need to move my test code into proper functions, handle cache expiry, admin options and some more things. Hopefully I should have a beta within a couple of weeks!
commented Feb 29, 2016 by Ami
Thank you for the effort. Also please keep a option to disable cache while on development mode.
commented Mar 3, 2016 by Waterfr Villa
"So at least for that page, we'll cache all 9 queries in one file per question." that itself will be a big perf improvement
0 votes
answered Mar 20, 2016 by Amir Cmpe

As you all see there has been a number of attempts to create such plugin.

this one by Michael in 2012

or

this one in 2014 by Sama

My suggestion is to

1- Take very small step at a time and come up with a minimal viable solution that can cache one or two requests to improve the speed even 5%. Something we can start with, otherwise we will never be able to do this

2- Copy exactly what stackoverflow does. They use cloudflare, how come it does not work for us? look at this:= link:

How stackoverflow has implemented caching?

  

 

commented Mar 20, 2016 by Scott
#1: that's pretty much what I've done (it should help more than 5% I think!)

#2: Cloudflare is not something you'd build into the software per se. CF sits in front of the server and caches requests.

Stack Overflow will be using much more than just CF. And we are in a different situation - they are the only developers and can take caching into account with everything they do. Q2A cannot do that because of themes and plugins.
commented Mar 27, 2016 by Amir Cmpe
Thanks a lot. I noticed the release of new caching service. Will give it a try.
SO has updated their answers too: http://stackoverflow.com/questions/35678816/how-stackoverflow-has-implemented-caching
...