节约内存:Instagram的Redis实践(转)

一、问题:

数据库表数据量极大(千万条),要求让服务器更加快速地响应用户的需求。
二、解决方案:
1.通过高速服务器Cache缓存数据库数据
2.内存数据库
三、主流解Cache和数据库对比
从以上各数据可知,对于我们产品最可行的技术方案有两种:
1.Memcached         内存Key-Value Cache
2.Redis                     内存数据库

四,节约内存:Instagram的Redis实践

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"

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

参考:

  • http://blog.nosqlfan.com/html/3379.html
  • http://instagram-engineering.tumblr.com/post/12202313862/storing-hundreds-of-millions-of-simple-key-value
  • http://www.open-open.com/lib/view/open1409643182369.html

转载于:https://www.cnblogs.com/JoannaQ/p/4470272.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/251526.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

多数公司容易犯的5个大数据错误

多数公司容易犯的5个大数据错误 如今,大数据革命驱动了现代工业发展,每天都有越来越多的企业采用大数据技术。然而,尽管大量数据已经存在和应用了很长时间,但如何使用它,仍然存在许多严重的错误。 以下是企业容易犯的5…

(2.15)备份与还原--使用作业备份、清理过期备份、清理历史记录、事务日志是否备份过...

一、建立作业备份数据库 打开SQL SERVER MANAGEMENT STUDIO,启动SQL SERVER代理服务(注意在“控制面板-管理工具-服务”中设置SQL SERVER AGENT的启动类型为自动)。启动后点击“作业-新建作业”,弹出一个作业属性的窗口&#xff0…

javascript+HTML+CSS面试题

今天参加面试,考了我三个小时,考晕了,赶紧补习补习javascript的知识!(另:人事部明明说招HTML5CSS3jQuery,考1个半小时左右,怎么变成了考传统DIVCSSjavascript啦,呜呜呜~~…

android 对话框

android 8种对话框(Dialog)使用方法汇总 作者:gzdaijie本文为作者原创,转载请注明出处:https://www.cnblogs.com/gzdaijie/p/5222191.html 目录 1.写在前面2.代码示例2.1 普通Dialog(图1与图2)2…

算法 --- 插入排序的JS实现

let A [5, 2, 4, 6, 1 ,3];// 插入排序 insertionSort (A) > {console.log("原数组>>>", A);for (let j1; j<A.length; j) {let key A[j];i j -1;while ( i > -1 && A[i] > key) {A[i1] A[i];i i-1;}A[i 1] key;}console.log(&q…

算法 --- 归并排序的js实现

let mergeSort (A, p, q, r) > {console.log("原数组>>>", A);let n1 q - p 1;let n2 r - q;let L new Array();let R new Array();for (let i 1; i < n1 1; i) {L[i -1] A[p i - 1];}for (let j 1; j < n2 1; j) {R[j-1] A[q j];}L[…

个人技术博客

一. Volley框架 在进行和服务器交互的时候需要发送请求&#xff0c;发现了volley这个好用易上手的框架。volley是一个异步网络通信框架&#xff0c;它的优点在于轻量级、适用于量小但传送频繁的请求操作 搭建请求的第一步就是新建一个请求队列RequestQueue queue Volley.newRe…

软件构造 第一章第二节 软件开发的质量属性

​软件构造 第一章第二节 软件开发的质量属性 1.软件系统质量指标 External quality factors affect users 外部质量因素影响用户 Internal quality factors affect the software itself and its developers 内部质量因素影响软件本身和它的开发者 External quality results fr…

css自媒体查询

准备工作1&#xff1a;设置Meta标签 首先我们在使用Media的时候需要先设置下面这段代码&#xff0c;来兼容移动设备的展示效果&#xff1a; <meta name"viewport" content"widthdevice-width, initial-scale1.0, maximum-scale1.0, user-scalableno">…

css --- 应用媒介查询制作响应式导航栏

以上导航会自动适应各个尺寸的屏幕 代码如下: <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <meta name"apple-mobile-w…

Drools 7.4.1.Final参考手册(六) 用户手册

用户手册 基础 无状态的知识Session Drools规则引擎拥有大量的用例和功能&#xff0c;我们要如何开始&#xff1f;你无须担心&#xff0c;这些复杂性是分层的&#xff0c;你可以用简单的用例来逐步入门。 无状态Session&#xff0c;无须使用推理&#xff0c;就形成了最简单的用…

css --- 弹性盒子

左右两侧按1:1自适应,中间固定宽度500px // CSS /* 首先定义 container &#xff0c;关注display */ /* webkit 是Chrome、Safari 的浏览器前缀 */ .container{margin: auto;display: -webkit-box;width: 80%&#xff1b;height: 200px; } /* 开始定义左、中、右 */ .left { …

更精炼更专注的RTMPClient客户端EasyRTMPClient,满足直播、转发、分析等各种需求...

现状 EasyRTMPClient&#xff0c;熟悉的朋友就会联想到EasyRTSPClient项目&#xff08;https://github.com/EasyDSS/EasyRTSPClient&#xff09;&#xff0c;EasyRTSPClient从14年中期开始发展&#xff0c;已经迭代发展历时3年多时间&#xff0c;可以说在RTSPClient领域是非常成…

bootstrap --- 表格

几个可选类: .table-bordered: 为表格加上边框 .table-striped: 为表格加上斑马效果 .table-hover: 鼠标悬停在表格行上时展现不同得颜色 .table-condensed: 更为紧凑的表格样式 // 导入样式,从bootstrap官网导入CDN // HEAD <link rel"stylesheet" href"…

mongodb数据库中插入数据

mongodb数据库中插入数据 一&#xff1a;connection 访问集合&#xff1b; 在mongodb数据库中&#xff0c;数据是存储在许多数据集合中&#xff0c;可以使用数据库对象的collection方法访问一个集合。该方法使用如下&#xff1a; db.collection(collectionName, [options], [ca…

bootstrap --- 表单

// HTML >>> 第一种样式 <!DOCTYPE html> <html> <head><link rel"stylesheet" href"https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity"sha384-Gn5384xqQ1aoWXA058RXPxPg6fy4IWvTNh0E263XmF…

bootstrap --- 按钮

<head><!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel"stylesheet" href"https://cdn.jsdelivr.net/npm/bootstrap3.3.7/dist/css/bootstrap.min.css" integrity"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4VaPmSTs…

bootstrap --- 分页

// bootstrap中给无序列表的ul元素添加pagination类即可.<ul class"pagination"><li class"disabled"><a href"#">&laquo;</a></li><li class"active"><a href"#">1</a&g…

图的基本知识

1.简介 图&#xff08;Graph&#xff09;是由顶点的有穷非空集合和顶点之间的边的集合组成&#xff0c;通常表示为&#xff1a;G(V,E)&#xff0c;G表示一个图&#xff0c;V是图G中顶点的集合&#xff0c;E是图G中边的集合。 图是一种复杂的非线性结构&#xff0c;在图结构中&a…

bootstrap --- 面板

基本样式 <div class"panel panel-default"><div class"panel-heading">面板头...</div><div class"panel-body">面板身体...</div><div class"panel-footer">面板脚...</div> </div>…