0
ScaleFail(and MPs’ expenses)
Copyright © Steve Bell 2009
How we built it
Crash #1: moreApache children thanMySQL connections
unreviewed_count = Page.objects.filter(   votes__isnull = True).distinct().count()
SELECT  COUNT(DISTINCT `expenses_page`.`id`)FROM  `expenses_page` LEFT OUTER JOIN `expenses_vote` ON (     `expenses_page`...
unreviewed_count = cache.get(homepage:unreviewed_count)if unreviewed_count is None:    unreviewed_count = Page.objects.filt...
• With 70,000 pages and a LOT of votes... • DB takes up 135% of CPU• Cache the count in memcached... • DB drops to %35 of ...
unreviewed_count = Page.objects.filter(   votes__isnull = True).distinct().count()reviewed_count = Page.objects.filter(   vo...
unreviewed_count = Page.objects.filter(   is_reviewed = False).count()
Migrating to InnoDBon a separate server
ssh mps-live "mysqldump mp_expenses" |sed s/ENGINE=MyISAM/ENGINE=InnoDB/g |  sed s/CHARSET=latin1/CHARSET=utf8/g |  ssh my...
“next” button
def next_global(request):  # Next unreviewed page from the whole site  all_unreviewed_pages = Page.objects.filter(      is_...
def next_global(request):  # Next unreviewed page from the whole site  all_unreviewed_pages = Page.objects.filter(      is_...
import randomdef next_global_from_cache(request):  page_ids = cache.get(unreviewed_page_ids)  if page_ids:      return Red...
Next time, I’ll use redis
Read-only modesaved our bacon
Copyright © Martin Rowson 2008
ScaleFail
ScaleFail
ScaleFail
ScaleFail
ScaleFail
ScaleFail
ScaleFail
ScaleFail
ScaleFail
Upcoming SlideShare
Loading in...5
×

ScaleFail

1,698

Published on

A 5 minute presentation for UK ScaleCamp 2009

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,698
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "ScaleFail"

  1. 1. ScaleFail(and MPs’ expenses)
  2. 2. Copyright © Steve Bell 2009
  3. 3. How we built it
  4. 4. Crash #1: moreApache children thanMySQL connections
  5. 5. unreviewed_count = Page.objects.filter( votes__isnull = True).distinct().count()
  6. 6. SELECT COUNT(DISTINCT `expenses_page`.`id`)FROM `expenses_page` LEFT OUTER JOIN `expenses_vote` ON ( `expenses_page`.`id` = `expenses_vote`.`page_id` ) WHERE `expenses_vote`.`id` IS NULL
  7. 7. unreviewed_count = cache.get(homepage:unreviewed_count)if unreviewed_count is None: unreviewed_count = Page.objects.filter( votes__isnull = True ).distinct().count() cache.set(homepage: unreviewed_count, unreviewed_count, 60)
  8. 8. • With 70,000 pages and a LOT of votes... • DB takes up 135% of CPU• Cache the count in memcached... • DB drops to %35 of CPU
  9. 9. unreviewed_count = Page.objects.filter( votes__isnull = True).distinct().count()reviewed_count = Page.objects.filter( votes__isnull = False).distinct().count()
  10. 10. unreviewed_count = Page.objects.filter( is_reviewed = False).count()
  11. 11. Migrating to InnoDBon a separate server
  12. 12. ssh mps-live "mysqldump mp_expenses" |sed s/ENGINE=MyISAM/ENGINE=InnoDB/g | sed s/CHARSET=latin1/CHARSET=utf8/g | ssh mysql-big "mysql -u root mp_expenses"
  13. 13. “next” button
  14. 14. def next_global(request): # Next unreviewed page from the whole site all_unreviewed_pages = Page.objects.filter( is_reviewed = False ).order_by(?) if all_unreviewed_pages: return Redirect( all_unreviewed_pages[0].get_absolute_url() ) else: return HttpResponse( All pages have been reviewed! )
  15. 15. def next_global(request): # Next unreviewed page from the whole site all_unreviewed_pages = Page.objects.filter( is_reviewed = False ).order_by(?) if all_unreviewed_pages: return Redirect( all_unreviewed_pages[0].get_absolute_url() ) else: return HttpResponse( All pages have been reviewed! )
  16. 16. import randomdef next_global_from_cache(request): page_ids = cache.get(unreviewed_page_ids) if page_ids: return Redirect( /page/%s/ % random.choice(page_ids) ) else: return next_global(request)
  17. 17. Next time, I’ll use redis
  18. 18. Read-only modesaved our bacon
  19. 19. Copyright © Martin Rowson 2008
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×