文档章节

节约内存:Instagram的Redis实践

天天顺利
 天天顺利
发布于 2015/06/13 13:03
字数 1013
阅读 91
收藏 1

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

本文转载自:http://blog.nosqlfan.com/html/3379.html

共有 人打赏支持
天天顺利
粉丝 42
博文 167
码字总数 73007
作品 0
海淀
技术主管
如何用分布式缓存服务DCS实现Redis内存优化

Redis是一种支持Key-Value等多种数据结构的存储系统,其数据特性是“ALL IN MEMORY”,因此优化内存十分重要。在对Redis进行内存优化时,先要掌握Redis内存存储的特性比如字符串,压缩编码,...

中间件小哥
07/13
0
0
Redis内存容量的预估和优化

Redis是个内存全集的kv数据库,不存在部分数据在磁盘部分数据在内存里的情况,所以提前预估和节约内存非常重要.本文将以最常用的string和zipmap两类数据结构在jemalloc内存分配器下的内存容量预...

红薯
2011/11/15
6.1K
0
Redis 内存容量的预估和优化

Redis是个内存全集的kv数据库,不存在部分数据在磁盘部分数据在内存里的情况,所以提前预估和节约内存非常重要.本文将以最常用的string和zipmap两类数据结构在jemalloc内存分配器下的内存容量预...

红薯
2011/11/26
791
0
Instagram 架构分析笔记

by Fenng@dbanotes.net Instagram 团队上个月才迎来第 7 名员工,是的,7个人的团队。用户数量超过 1400 万,图片数量:1.5 亿。不得不说,这真他妈是个业界奇迹。 几天前,Instagram 发布了...

红薯
2011/12/07
5.4K
8
Redis 的基础数据结构(二) 整数集合、跳跃表、压缩列表

原文地址:https://www.xilidou.com/2018/03/13/redis-data2/ 上篇文章写了 Redis 基础数据结构的可变字符串、链表、字典。大家可以点击链接查看。今天我们继续研究 Redis 的基础数据结构。 ...

犀利豆
03/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring中static变量不能@value注入的原因

今天本想使用@Value的方式使类中的变量获得yml文件中的配置值,然而一直失败,获得的一直为null。 类似于这样写的。 public class RedisShardedPool { private static ShardedJedisPool pool...

钟然千落
24分钟前
0
0
CentOS7防火墙firewalld操作

firewalld Linux上新用的防火墙软件,跟iptables差不多的工具。 firewall-cmd 是 firewalld 的字符界面管理工具,firewalld是CentOS7的一大特性,最大的好处有两个:支持动态更新,不用重启服...

dingdayu
今天
1
0
关于组件化的最初步

一个工程可能会有多个版本,有国际版、国内版、还有针对各种不同的渠道化的打包版本、这个属于我们日常经常见到的打包差异化版本需求。 而对于工程的开发,比如以前的公司,分成了有三大块业...

DannyCoder
今天
2
0
Spring的Resttemplate发送带header的post请求

private HttpHeaders getJsonHeader() { HttpHeaders headers = new HttpHeaders(); MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8"); ......

qiang123
昨天
3
0
Spring Cloud Gateway 之 Only one connection receive subscriber allowed

都说Spring Cloud Gateway好,我也来试试,可是配置了总是报下面这个错误: java.lang.IllegalStateException: Only one connection receive subscriber allowed. 困扰了我几天的问题,原来...

ThinkGem
昨天
32
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部