Your SlideShare is downloading. ×

ScaleFail

1,615
views

Published on

A 5 minute presentation for UK ScaleCamp 2009

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,615
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. ScaleFail(and MPs’ expenses)
  • 2. Copyright © Steve Bell 2009
  • 3. How we built it
  • 4. Crash #1: moreApache children thanMySQL connections
  • 5. unreviewed_count = Page.objects.filter( votes__isnull = True).distinct().count()
  • 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. 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. • 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. unreviewed_count = Page.objects.filter( votes__isnull = True).distinct().count()reviewed_count = Page.objects.filter( votes__isnull = False).distinct().count()
  • 10. unreviewed_count = Page.objects.filter( is_reviewed = False).count()
  • 11. Migrating to InnoDBon a separate server
  • 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. “next” button
  • 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. 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. 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. Next time, I’ll use redis
  • 18. Read-only modesaved our bacon
  • 19. Copyright © Martin Rowson 2008