Google Code offered in: English - Español - 日本語 - 한국어 - Português - Pусский - 中文(简体) - 中文(繁體)
Memcache is a high-performance, distributed memory object caching system, primarily intended for fast access to cached results of datastore queries.
Memcache is typically used with the following pattern:
The pseudocode below represents a typical memcache request:
def get_data(): data = memcache.get("key") if data is not None: return data else: data = self.query_for_data() memcache.add("key", data, 60) return data
The guestbook application in the Getting Started Guide queries the datastore on every request. You can modify the Guestbook application to use memcache before resorting to querying the datastore.
First we'll import the memcache module and create the method that checks memcache before running a query.
from google.appengine.api import memcache def get_greetings(self): """get_greetings() Checks the cache to see if there are cached greetings. If not, call render_greetings and set the cache Returns: A string of HTML containing greetings. """ greetings = memcache.get("greetings") if greetings is not None: return greetings else: greetings = self.render_greetings() if not memcache.add("greetings", greetings, 10): logging.error("Memcache set failed.") return greetings
Next we'll separate out the querying and creation of the HTML for the page. When we don't hit the cache, we'll call this method to query the datastore and build the HTML string that we'll store in memcache.
def render_greetings(self): """render_greetings() Queries the database for greetings, iterate through the results and create the HTML. Returns: A string of HTML containing greetings """ results = db.GqlQuery("SELECT * " "FROM Greeting " "ORDER BY date DESC").fetch(10) output = StringIO.StringIO() for result in results: if result.author: output.write("<b>%s</b> wrote:" % result.author.nickname()) else: output.write("An anonymous person wrote:") output.write("<blockquote>%s</blockquote>" % cgi.escape(result.content)) return output.getvalue()
Finally we will update the MainPage
handler to call the get_greetings() method and display some stats about the number of times the cache was hit or missed.
import cgi import datetime import logging import StringIO from google.appengine.ext import db from google.appengine.api import users from google.appengine.ext import webapp from google.appengine.ext.webapp.util import run_wsgi_app from google.appengine.api import memcache logging.getLogger().setLevel(logging.DEBUG) class Greeting(db.Model): author = db.UserProperty() content = db.StringProperty(multiline=True) date = db.DateTimeProperty(auto_now_add=True) class MainPage(webapp.RequestHandler): def get(self): self.response.out.write("<html><body>") greetings = self.get_greetings() stats = memcache.get_stats() self.response.out.write("<b>Cache Hits:%s</b><br>" % stats['hits']) self.response.out.write("<b>Cache Misses:%s</b><br><br>" % stats['misses']) self.response.out.write(greetings) self.response.out.write(""" <form action="/sign" method="post"> <div><textarea name="content" rows="3" cols="60"></textarea></div> <div><input type="submit" value="Sign Guestbook"></div> </form> </body> </html>""") def get_greetings(self): """ get_greetings() Checks the cache to see if there are cached greetings. If not, call render_greetings and set the cache Returns: A string of HTML containing greetings. """ greetings = memcache.get("greetings") if greetings is not None: return greetings else: greetings = self.render_greetings() if not memcache.add("greetings", greetings, 10): logging.error("Memcache set failed.") return greetings def render_greetings(self): """ render_greetings() Queries the database for greetings, iterate through the results and create the HTML. Returns: A string of HTML containing greetings """ results = db.GqlQuery("SELECT * " "FROM Greeting " "ORDER BY date DESC").fetch(10) output = StringIO.StringIO() for result in results: if result.author: output.write("<b>%s</b> wrote:" % result.author.nickname()) else: output.write("An anonymous person wrote:") output.write("<blockquote>%s</blockquote>" % cgi.escape(result.content)) return output.getvalue() class Guestbook(webapp.RequestHandler): def post(self): greeting = Greeting() if users.get_current_user(): greeting.author = users.get_current_user() greeting.content = self.request.get('content') greeting.put() self.redirect('/') application = webapp.WSGIApplication([ ('/', MainPage), ('/sign', Guestbook) ], debug=True) def main(): run_wsgi_app(application) if __name__ == '__main__': main()