INSTAGRAM UNDER THE HOOD

2020-02-27 210浏览

  • 1.INSTAGRAM UNDER THE HOOD Django Under the Hood 2016 Carl Meyer
  • 2.
  • 3.
  • 4.
  • 5.4,200,000,000 EVERY DAY
  • 6.2,300,000,000,000
  • 7.
  • 8.October
 2010
  • 9.“SUPER EASY SET-UP... ONE WAY OF DOING THINGS... EASY TESTING.” — Mike Krieger
  • 10.1M Instagrammers December
 2010
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.5M Instagrammers June
 2011
  • 16.USERS MEDIA LIKES COMMENTS
  • 17.class VerticalPartitionRouter(object): DB_FOR_MODEL = { 'likes.like': 'likes', 'comments.comment': 'comments', 'media.media': 'media', } def _db_for(self, model_or_obj): label = model_or_obj._meta.label_lower return self.DB_FOR_MODEL.get(label, 'default') def db_for_read(self, model, **hints): return self._db_for(model) def db_for_write(self, model, **hints): return self._db_for(model) def allow_relation(self, obj1, obj2, **hints): return self._db_for(obj_1) == self._db_for(obj_2)
  • 18.
  • 19.USERS MEDIA LIKES COMMENTS
  • 20.
  • 21.LOGICAL SHARDS (PG SCHEMAS) PHYSICAL SERVERS
  • 22.LOGICAL SHARDS (PG SCHEMAS) PHYSICAL SERVERS
  • 23.commit 5c7034fa8b934569cce5c1bf4bb202f2f3f18bc9Author:Mike KriegerDate:Tue Jul 19 23:47:26 2011 -0700 WIP
  • 24.class ShardedObject(object): def insert(self, shard_on_id, from_table, values): shard, db = get_conn_for_shard_key(shard_on_id) cursor = db.cursor() placeholders = ','.join( [("%%(%s)s" % key) for key in values.keys()]) columns = ','.join(values.keys()) insert_statement = ( "INSERT INTO idb%s.%s (%s) VALUES (%s)" % (shard, from_table, columns, placeholders) ) cursor.execute(insert_statement, values) db.commit()
  • 25.SHARDED UNIQUE IDS 138726300013410905 TIMESTAMP SHARD ID SEQUENCE CREATE OR REPLACE FUNCTION insta5.next_id... CREATE TABLE insta5.our_table ( "id" bigint NOT NULL DEFAULT insta5.next_id(), ...rest of table schema... )
  • 26.
  • 27.40M Instagrammers April
 2012
  • 28.Memcached
  • 29.Data center A Memcached Invalidator Data center B Memcached Invalidator
  • 30.MULTI-REGION CACHE INVALIDATION
  • 31.CONTEMPLATING THE TAO
  • 32.TAO Memcached Memcached Memcached Memcached Memcached
  • 33.TAO DATA MODEL Jan follows Pat. Pat posts a photo. Jan authors a comment on the photo. Pat likes the comment. Followed by Pat Jan Comment on or ed or ed th th Au Au d ste Po by Has comment es Lik ed Lik Po ste d by by Follows "Contemplative cat!"
  • 34.CONTEMPLATING THE TAO
  • 35.
  • 36.500M Instagrammers June
 2016
  • 37.UPGRADING DJANGO “JUST KEEP FIXING UNTIL THE TESTS PASS.”
  • 38.INSTAGRAM:Now compatible with Django 3.1TM (1.3 + 1.8)
  • 39.INSTAGRAM:Now compatible with Django 1.8!
  • 40.OUR (MONKEY) PATCHES 1 Don't recompile URL regexes for every active language. 2 Don't try to load translations from an app with no locale directory. 3 Unlazified settings! 40
  • 41.UNLAZY ALL THE SETTINGS! from django.conf import settings def force_unlazified_settings(): for key in dir(settings): settings.__dict__[key] = getattr(settings, key)
  • 42.INSTAGRAM:Now compatible with Django 1.8! (and fast as ever)
  • 43.500M+ Instagrammers Today!
  • 44.Proxygen Django & uWSGI TAO Cassandra Everstore Celery & RabbitMQ
  • 45.
  • 46.
  • 47.Active Last Minute ???
  • 48.COUNTING CPU INSTRUCTIONS WITH PERF struct perf_event_attr pe; pe.type = PERF_TYPE_HARDWARE; pe.config = PERF_COUNT_HW_INSTRUCTIONS; fd = perf_event_open(&pe, 0, -1, -1, 0); ioctl(fd, PERF_EVENT_IOC_ENABLE); // code whose CPU instructions you want to measure ioctl(fd, PERF_EVENT_IOC_DISABLE); read(fd, &count, sizeof(long long));
  • 49.CPU instructions/s CPU instructions/s
  • 50.CPU instructions/s CPU instructions/s
  • 51.
  • 52.AppWeight
  • 53.Continuous deployment 30-50 deploys per day
  • 54.
  • 55.DYNOSTATS class DynostatsMiddleware(object): def process_request(self, req): req.dynostats_enabled = ( 1 == random.randint(1, settings.DYNO_SAMPLE_RATE)) if req.dynostats_enabled:'>enabled: