节约内存:Instagram的Redis实践

news/2024/6/18 19:14:43 标签: 数据库, python

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

Instagram可以说是网拍App的始祖级应用,也是当前最火热的拍照App之一,Instagram的照片数量已经达到3亿,而在Instagram里,我们需要知道每一张照片的作者是谁,下面就是Instagram团队如何使用Redis来解决这个问题并进行内存优化的。

首先,这个通过图片ID反查用户UID的应用有以下几点需求:

  • 查询速度要足够快
  • 数据要能全部放到内存里,最好是一台EC2的 high-memory 机型就能存储(17GB或者34GB的,68GB的太浪费了)
  • 要合适Instagram现有的架构(Instagram对Redis有一定的使用经验,比如这个应用)
  • 支持持久化,这样在服务器重启后不需要再预热

Instagram的开发者首先否定了数据库存储的方案,他们保持了KISS原则(Keep It Simple and Stupid),因为这个应用根本用不到数据库的update功能,事务功能和关联查询等等牛X功能,所以不必为这些用不到的功能去选择维护一个数据库

于是他们选择了Redis,Redis是一个支持持久化的内存数据库,所有的数据都被存储在内存中(忘掉VM吧),而最简单的实现就是使用Redis的String结构来做一个key-value存储就行了。像这样:

SET media:1155315 939
GET media:1155315
> 939

其中1155315是图片ID,939是用户ID,我们将每一张图片ID为作key,用户uid作为value来存成key-value对。然后他们进行了测试,将数据按上面的方法存储,1,000,000数据会用掉70MB内存,300,000,000张照片就会用掉21GB的内存。对比预算的17GB还是超支了。

NoSQLFan:其实这里我们可以看到一个优化点,我们可以将key值前面相同的media去掉,只存数字,这样key的长度就减少了,减少key值对内存的开销【注:Redis的key值不会做字符串到数字的转换,所以这里节省的,仅仅是media:这6个字节的开销】。经过实验,内存占用会降到50MB,总的内存占用是15GB,是满足需求的,但是Instagram后面的改进任然有必要

于是Instagram的开发者向Redis的开发者之一Pieter Noordhuis询问优化方案,得到的回复是使用Hash结构。具体的做法就是将数据分段,每一段使用一个Hash结构存储,由于Hash结构会在单个Hash元素在不足一定数量时进行压缩存储,所以可以大量节约内存。这一点在上面的String结构里是不存在的。而这个一定数量是由配置文件中的hash-zipmap-max-entries参数来控制的。经过开发者们的实验,将hash-zipmap-max-entries设置为1000时,性能比较好,超过1000后HSET命令就会导致CPU消耗变得非常大。

于是他们改变了方案,将数据存成如下结构:

HSET "mediabucket:1155" "1155315" "939"
HGET "mediabucket:1155" "1155315"
> "939"

通过取7位的图片ID的前四位为Hash结构的key值,保证了每个Hash内部只包含3位的key,也就是1000个。

再做一次实验,结果是每1,000,000个key只消耗了16MB的内存。总内存使用也降到了5GB,满足了应用需求。

NoSQLFan:同样的,这里我们还是可以再进行优化,首先是将Hash结构的key值变成纯数字,这样key长度减少了12个字节,其次是将Hash结构中的subkey值变成三位数,这又减少了4个字节的开销,如下所示。经过实验,内存占用量会降到10MB,总内存占用为3GB

HSET "1155" "315" "939"
HGET "1155" "315"
> "939"

优化无止境,只要肯琢磨。希望你在使用存储产品时也能如此爱惜内存。

来源:instagram-engineering.tumblr.com

转载于:https://my.oschina.net/u/658658/blog/466347


http://www.niftyadmin.cn/n/1414874.html

相关文章

linux IPC 通信 study 二:信号signal

信号是一种软中断,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的。信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。signal是ipc机制中唯一的异步通信机制。 信…

大流士三世

大流士三世传世的波斯王,其他的波斯君主都只有浮雕和钱币上千篇一律的侧影流传下来。 1831年,意大利那布勒斯王国发掘古罗马庞贝(Pompeii)遗址的过程中,发现了保存相当完好的一幅壁画,这就是著名的“伊苏斯壁画” (Issus Mosaic)。…

Linux 目录初识

/ 根目录/bin 存放必要的命令 /boot 存放内核以及启动所需的文件 /dev 存放硬件设备文件 /etc 存放系统配置文件/home 普通用户的宿主目录,用户数据存放在其主目录中/lib 存放必要的运行库/mnt 存放临时的映射文件系统,通常用来挂载使用。/proc …

mysql数据的导入和导出

一. mysqldump工具基本用法,不适用于大数据备份 1. 备份所有数据库: mysqldump -u root -p --all-databases > all_database_sql2. 备份mysql数据库:mysqldump -u root -p --databases mysql > mysql_database_sql3. 备份指定的多个数据库&#xf…

linux IPC 通信 study 三:system v 信号量semphore

常用于进程间同步 API 介绍 1 semget sys/sem.h int semget(key_t key, int nsems, int flag); 执行成功返回信号量ID, 出错返回-1,同时errno标识错误原因 参数key 通过ftok获得 参数 nsems 是信号量集合中信号量的个数; 在创建新集合时(一般在服务器…

【TYVJ1340】送礼物(折半搜索+hashmap)

当答案可以分为两半时 为了降低复杂度 可以使用折半搜索 对前半部分 搜出所有可能的和 用map记录 对后半部分 同样也是搜出可能的和 如果前半部分存在一个和 能拼起来 那ans #include<bits/stdc.h> #define N 45 #define ll long long using namespace std; ll n,key,ans…

亚瑟王

亚瑟王亚瑟王(King Arthur)是 英格兰传说中的国王&#xff0c; 圆桌骑士团的首领&#xff0c;一位近乎神话般的传奇人物。他是 罗马帝国瓦解之后&#xff0c;率领圆桌骑士团统一了 不列颠群岛&#xff0c; 被后人尊称为亚瑟王。关于亚瑟王的传奇故事&#xff0c;最初如何诞生&a…

分享2个实用的nodejs模块

2019独角兽企业重金招聘Python工程师标准>>> 分享2个实用的nodejs模块 kp 根据端口号杀死进程&#xff0c;尤其对于pm2的集群模式&#xff0c;僵尸进程有效mount-routes 根据路径来自动加载路由&#xff0c;让开发更简单kp kp is a tool for kill process by server…