Instagramz最初存储采用CouchDB(Apache CouchDB 是一个面向文档的数据库管理系统),而且只有一台服务器(在洛杉矶),比一台比MacBook Pro强不到哪里去。后来有了一些升级,具体如下:



一、数据库扩展

使用django ORM+postgresql,因为PostGIS,选择了postgresql。(PostGIS在对象关系型数据库PostgreSQL上增加了存储管理空间数据的能力,相当于Oracle的spatial部分)并且数据库部署在独立服务器上。

因为EC2机器的最大内存为68G,随着照片存储量的增加,进行垂直分区(vertical partitioning);使用django db routers,做垂直分区变得很容易;如下:照片则映射到photodb

def db_for_read(self, model): if app_label == 'photos': return 'photodb'​

 

当照片存储量大于60G的时候,采用水平分区(也就是所谓的“分片”sharding)

sharding带来的问题:
  1. 数据的检索,hard to know what your primary access patterns will be w/out any usage in most cases, user ID
  2. 当有分片变得太大的时候怎么办?

基于范围的分片策略(就像MongoDB那样)





3、性能有下降趋势,尤其在EC2上,原因:disk IO,解决方法:预先切分(pre-split),即预先切分上千个逻辑切片,将它们映射到较少的物理分区节点中去。

关于相关内容,更详细的可以参看这里

二、选择合适工具

进行缓存/反规范化数据设计

用户上传图片时:
  • 用户上传带有标题信息和地理位置信息(可选)的照片
  • 同步写到这个用户对应的数据库(分片)中

进行队列化处理
  • 如果带有地理位置信息,通过异步的POST请求,将这个图片的信息送到Solr(Instagram 用于geo-search API的全文检索服务器)。
  • 跟随者的信息分发(follower delivery),即告诉我的follower ,我发布了新的照片。如何来实现的呢?每个用户都有一个follower 列表,新照片上传时会把照片ID发送给列表中的每一个用户,用Redis 来处理这一业务简直太棒了,快速插入,快速子集化(rapid subsets)
  • when time to render a feed,we take small # of IDs, go look up info in memcached(当需要生成feed的时候,我们通过ID+#的格式,直接在memcached中查找信息)


Redis适合什么样的场景?
  1. 数据结构相对有限
  2. 对频繁GET的地方,对复杂对象进行缓存