Redis经验谈(转)
原文:http://www.programmer.com.cn/14577/
新浪作为全世界最大的Redis用户,在开发和运维方面有非常多的经验。本文作者来自新浪,希望能为业界提供一些亲身经历,让大家少走弯路。
使用初衷
从2010年上半年起,我们就开始尝试使用Redis,主要出于以下几方面的考虑。
- 性能比MySQL好。因为业务的发展对性能的需求越来越强烈。
- 丰富的数据类型。在速度就是市场的互联网时代,快速开发是一个不变的需求。
- Cache宕机让人纠结,Redis有半持久化和持久化两种方式,能从某种程度上解决这个问题,以减少Cache宕机带来的雪崩效应。
- 在部分业务场景中,使用MySQL+Memcached存在一致性问题,若使用Redis替代,能降低整体架构复杂度。
完善过程
在开始应用Redis时,规模比较小,数据量也很小,没有遇到太多的问题。而随着数据量的增加,遇到了很多问题。总结一句话就是,当数据量变大时,以前不是问题的问题都变成了问题。
Master/Slave同步问题
首先遇到的是Master/Slave的同步问题。它的原理是Slave做了Slaveof之后,向Master发送一个Sync,Master把 内存的数 据Dump出来,形成rdb文件,然后传到Slave,Slave把这个文件加载到内存,完成之后Master向Slave发送新数据包。
在网络出现问题时,比如瞬断,会导致Master里的数据全部重传。对单个端口来说,如果数据量小,那么这个影响不大,而如果数据量比较大的话,则 会导致网 络瞬间流量暴增,同时在同步时Slave做不了读操作。我们对其进行了修改,加入Position的概念来解决这个问题,确保在网络出现问题时不会重传所 有数据,只重传断开时后面的数据。
aof的定期归档问题
Redis默认产生的aof文件需要手工做 bgrewrite-aof,这个操作产生的lock会对写产生一定的影响。因此,我们最开始用脚本在凌晨业务低峰时进行这个操作。而随着数量的增 加,lock的时间越来越不能被业务接受。我们对源代码进行了修改,将bgrewriteaof放到Redis内部去实现,在配置文件内制定执行时间,让 这个操作自动执行,并且不会导致写产生的lock问题。
同时,我们还将aof设计得与MySQL的binlog类似,设定每个aof的大小,在达到一定值时,会自动产生一个新的aof。
Mytrigger和MytriggerQ的设计
业务有这样的需求:应用按用户维度写入数据,统计用户的记录数(如关注数、粉丝数)时,需要从数据库中执行count(*)操作。在InnoDB中 执行这个 相对较慢,而增加Cache方案又满足不了业务对实时性的要求。因此,我们开发了Mytrigger组件来读取MySQL的binlog,然后通过业务逻 辑转化写入Redis。
例如,MySQL中存每条记录,Redis中存按用户维度的记录总和。这样实现之后,应用从MySQL中读取数据,从Redis里读取记录条数,MySQL的压力降低很多,同时计数读取性能提高了很多。
如果应用是数据的写入方,那么它需要将数据写入数据库,同时需要把这些新增或变更通知给另一个应用,另一个应用获得这些新增或更新后开始做自己的业务逻辑处理。
刚开始,我们采用了写数据库的同时再写一份MemcacheQ的方法,后来更换为MytriggerQ读取MySQL的binlog,将读取到的数 据转化为 队列。需要了解数据变化的业务通过读取这个MytriggerQ服务来获取数据的变化。这样,应用只用写一次,简化了应用架构的复杂度。
容量设计
在申请使用Redis之前,我们会对业务进行评估。通过填写预计容量和性能需求表格,我们能算出Redis占用的内存量,确保单个端口的数据量不高于机器内存的三分之一。
当前,我们使用的是96GB的内存型机型,每个端口最终容量控制在30GB以下。当业务需求的容量超过机器最大内存时,采用的拆分方式是Hash到 多个端 口,通过基准测试得出在容量允许的情况下,一台机器部署2个实例、4个实例或8个实例的最大性能,预留20%的容量用于增长,根据业务指标计算出需要的资 源数。
使用了Redis自身的过期策略之后,发现存入Redis的数据有可能出现即使还有大量内存没有使用,Redis还会让key过期去释放内存,或者内存不足时key还没有过期的问题。
对于过期的数据,我们采用清理和滚动两种方式。清理容易出现内存碎片;滚动即建两组端口,同时写两组端口。比如要保留3个月的数据,那么每个断开保 留6个月 的数据,两个同时写,使用奇数端口,在第4个月时,把读写切换到偶数端口,同时清理奇数端口里的数据,但使用这种方式带来了很高的维护成本。
应用场景
做Cache还是做Storage是我们一直在思考的问题。Redis有持久化和半持久化两种方式,但即使这样,所有Redis的数据都在内存中。大数据量存储时,数据类型的优势将越来越不明显。
当数据量小时,可以不用做过多考虑,因为一切都不是问题,可以利用其丰富的数据类型带来业务的快速开发和上线;数据量总量和增加量都相对可控,数据 比较精细 可以使用Redis做存储。例如,用户维度的计数就用Redis来做Storage。但对于对象维度,如微博维度的数据使用Redis做Cache。
有些业务的容量增长过快,与之前的预计有出入,且所有的数据都在内存中,没有冷热区分(降低存储最好的办法就是分级存储),我们就将这部分不再适合 放在 Redis的业务使用新的方案代替。例如把它替换成MySQL+Memcached的方式。因为每次做滚动切换的方案运维成本和硬件成本投入都很高,所以 可使用HandlerSocket来替换。例如,前6个月的数据放在Redis中,之后的数据放到MySQL中,在减少切换的同时也能降低运维成本。
未来的计划
随着机器规模的不断增加,可用性和自动化需求越来越强烈,目前我们正在结合ZooKeeper设计Redis的自动切换,同时提高Redis自动化 维护需 求。我们会开发一个高速数据访问框架和管理系统,将故障切换、数据拆分逻辑和自动数据迁移放到里面,实现其应用的产品化。希望走过的这些路对大家在使用 Redis的过程中有所帮助。
作者杨海朝,新浪首席DBA,在大规模高并发、海量访问方面有丰富的管理经验。热衷于整体架构、数据库设计、性能优化、分布式部署方案和高可用性方面的研究。
Redis经验谈(转)的更多相关文章
- Redis经验谈
新浪作为全世界最大的Redis用户,在开发和运维方面有非常多的经验.本文作者来自新浪,希望能为业界提供一些亲身经历,让大家少走弯路. 使用初衷 从2010年上半年起,我们就开始尝试使用Redis,主要 ...
- Remoting,OData Snippet Compiler等
http://www.sliver.com/dotnet/SnippetCompiler/ [ASP.NET Web API教程]ASP.NET Web API系列教程目录 张逸 .Net Remot ...
- Hadoop、Pig、Hive、Storm、NOSQL 学习资源收集
(一)hadoop 相关安装部署 1.hadoop在windows cygwin下的部署: http://lib.open-open.com/view/1333428291655 http://blo ...
- Hadoop、Pig、Hive、NOSQL 学习资源收集
转自:http://www.cnblogs.com/zzjhn/p/3855566.html (一)hadoop 相关安装部署 1.hadoop在windows cygwin下的部署: http:// ...
- REDIS基础笔记
Redis基础笔记 资源链接 简介 简介 安装 五种数据类型及相应命令 1. 字符串类型 2. 散列类型 3. 列表类型 4. 集合类型 5. 有序集合 其他 事务 SORT 生存时间 任务队列 发布 ...
- 使用redis构建可靠分布式锁
关于分布式锁的概念,具体实现方式,直接参阅下面两个帖子,这里就不多介绍了. 分布式锁的多种实现方式 分布式锁总结 对于分布式锁的几种实现方式的优劣,这里再列举下 1. 数据库实现方式 优点:易理解 缺 ...
- Ignite性能测试以及对redis的对比
测试方法 为了对Ignite做一个基本了解,做了一个性能测试,测试方法也比较简单主要是针对client模式,因为这种方法和使用redis的方式特别像.测试方法很简单主要是下面几点: 不作参数优化,默认 ...
- mac osx 安装redis扩展
1 php -v查看php版本 2 brew search php|grep redis 搜索对应的redis ps:如果没有brew 就根据http://brew.sh安装 3 brew ins ...
- Redis/HBase/Tair比较
KV系统对比表 对比维度 Redis Redis Cluster Medis Hbase Tair 访问模式 支持Value大小 理论上不超过1GB(建议不超过1MB) 理论上可配置(默认配置1 ...
随机推荐
- 安装ubuntu后,你的屏幕尺寸太小,无法设置,该怎么解决
安装完虚拟机之后,你的Ubuntu可能会在尺寸很小,(这种情况可能有,可能没有) 想要点击设置,选中Display里的分辨率下拉框,但是却因为这个窗口太大,无法点击apply按钮.悲剧啦!!! Ctr ...
- 【Java并发编程二】同步容器和并发容器
一.同步容器 在Java中,同步容器包括两个部分,一个是vector和HashTable,查看vector.HashTable的实现代码,可以看到这些容器实现线程安全的方式就是将它们的状态封装起来,并 ...
- UIWindow 详解及使用场景
首先来看一下UIWindow 继承关系 方法和属性 NS_CLASS_AVAILABLE_IOS(2_0) @interface UIWindow : UIView //window的屏幕,默认是 [ ...
- UIImageView的contentMode属性
UIViewContentMode 都有哪些值: typedef NS_ENUM(NSInteger, UIViewContentMode) { UIViewContentModeScaleToFil ...
- window下遍历并修改文件
今天需要写一个遍历文件夹下的所有文件,试了试以前的方法竟然报错了.重新改了一下. #include <iostream> #include <stdlib.h> #includ ...
- linux批量修改文件名
源文件; [root@test_machine fuzj]# ls fuzj-1.txt fuzj-2.txt fuzj-3.txt fuzj-4.txt fuzj-5.txt fuzj-6 ...
- 【Linux】 Centos7 NC探测端口命令
linux centos7 测试端口的连通性, 分别测试TCP端口与UDP端口 1 这个需要Linux服务器里边支持nc命令,检查NC 是否安装 2 安装nc yum install nc - ...
- 【java工具】AES CBC加密
一.定义 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先 ...
- html2canvas - 项目中遇到的那些坑点汇总(更新中...)
截图模糊 原理就是讲canvas画布的width和height放大两倍. 后来学习canvas的时候,才了解到这种写法不同于css的宽高设置, 因为css里的只是展示画布显示的大小,不像这样是c ...
- 父窗口 和 iframe 互相访问
在父窗口中获取iframe中的元素 1. 格式:window.frames["iframe的name值"].document.getElementByIdx_x("ifr ...