转载自: http://my.oschina.net/u/176507/blog/137022
写这篇文章主要是在开发www.ximalaya.com的feed(登录首页看到的好友动态,未登录是看不到的)模块使用Redis的一些经验。(www.ximalaya.com是音频为传播介质的SNS网站,喜欢的同学不妨用一用,也有APP的,还是一款非常不错的产品。音乐,相声,有声小说等等 一网打尽)。关于Feed本身的讨论以后再专门发博,有兴趣的同学也可以先开博,然后共同讨论。
Redis这个神器已经在互联网名声大作了,主要是对关系型数据库的补充。因为在大并发下,IO往往是性能的瓶颈,所以把数据尽量放到离cpu近的地方,是解决IO瓶颈的有效途径。呵呵,谁都想把数据放到寄存器,L1 L2 L3cache上,因为这些都是离cpu很近的地方,在一到几十个cpu时钟周期内能读到数据,但是这些缓存空间实在太小了。所以只能把最热的数据去征用这部分缓存。那么比这些数据稍微"冷"一点,但又经常访问的数据怎么办呢?目前最好的途径就是放在内存中。redis,memcache这类的内存数据库就是这样做的。放到内存中就意味着cpu可以在几百个时钟周期内能读到数据。一般服务器配置也是16个G内存吧,在64位系统下,理论可以让你的程序完全占用这16G内存。既然可以在这么快速的读到数据,那么采用什么算法读数据呢?线性查找?那又是浪费cpu时钟周期的。查找最快的莫过于hash表,它的时间复杂度是O(1)。所以本质来说Redis,memcache都是在内存上的hash数据库。Redis和memcache在互联网的应用都比较多,如何选择呢?当然两个都是解决缓存问题的神器,我更趋向于Redis这个神器。原因如下:
1,丰富的数据结构,string,hash,list,set,sortset等数据结构都支持,而memcache仅支持string(相当于key-value结构,这里说string是说的redis中的string),而其他数据结构也是在互联网中常用的。如果你想用就只能选Redis了。
2,可持久化,memcache是不支持持久化的。那么对于缓存的应用,一旦memcache服务挂掉了,内存的数据就丢失了,那么可以快速重启是吧,内存的数据全没了,这时候就有一个热点故障。或许你说可以通过预热来解决这个问题。但是Redis可以不需要预热,他会从rdb或aof中自动重建内存。之前的Redis版本中重启是需要花费很长时间的,但是在2.6版本后这个过程非常快了。即使是开启aof的情况下重启,9G的数据也只需要六分半的时间(www.ximalaya.com的真实案例)。这主要是Redis作者对aof的命令进行了合并,加快了重启的速度。对于需要持久化的应用,memcache就无能为力了,或许你可以选择memcached,当然Redis任然是更好的方案。
3,至于速度方面,Redis不会差于memcache,主要是Redis采用了epoll进行通信吧。
4,memcache是多线程的,Redis是单线程的,虽然更喜欢多线程的应用。但貌似Redis在单线程的操作下速度一点也不逊色,而且让操作更安全了,不需要锁,也不需要线程切换的开销了。Redis在备份rdb的时候会fork一个进程出来,让主进程不受任何影响。
Redis这个服务器,对于高并发快速读写,原子计数,消息队列,实时排名都是实用的。对于互联网网站来说这些都是频繁使用,也是关系型数据库比较头疼的。恰好以上提到的用途都在生成环境中有用到。根据实际经验来看,Redis还是实用于缓存,原子计数。对于持久化存储真的不太适合。因为它会把数据都加载到内存中(如果内存不够用会load到虚拟内存,但这是一个悲剧)。当然如果你用于持久存储的数据是有限的,那么也是非常适合的。但是对于数据需要无限增长的业务,这个真不太适合。网站登录首页的feed,收件箱列表全部放在Redis中。收件箱列表随着注册用户的增长而增长,需要消耗的内存也是逐步增长。为了缓解这个内存压力,客户端做了sharding,实现内存分片。这虽然能够解决内存问题,但需要更多的机器来做。所以我也一直在想怎么来缓解这块内存的问题。扯远了以后在把关于这方面的思考写出来吧。现在还是讲一讲Redis的应用。
在缓存中的应用:
缓存中的应用在memcache中就是对key-value的缓存。它之所以能快,是因为它是存放在内存中的hash数组。内存,hash。这两个关键词就足够解释为什么读写快了。现在对于速度和容量都比合适的存储也就内存最合适吧。ssd的速度快,容量也大。但需要在价格和寿命上有更大的突破才能被广泛使用。况且,ssd的速度比起主存来说还是有一定差距的。
下面对redis中string hash list set sortset分别说下使用场景。
string:这是使用最简单,也是非常频繁的一种数据类型。它就是一种单纯的key-value对。适用于那些通过键直接找值得业务场景。get string的时候需要用到mutil get,这是可以减少网络通信的,也是非常高效的。
hash:hash类型是对于string类型的补充,主要是有些key有共同的特征,不如一个用户对应的多个值,那么用户id只需要出现一次就可以了,对于string来说是需要出现多次的。所以hash是比string更节约了存储。同样hash也可以对多列mutil get,一次网络传输就可以得到所有值。
list:适用于不排重,且有序的操作。这其实就是一个队列,先进先出。放不排重的列表很有用。曾经还用它来做过队列。但队列还是用专门的消息队列更好,因为list不支持消息应答的,也就是不能确保你的消息被处理成功。
set:相当于java中的HashSet,用于排重的列表,但是无序的,在无序的列表还是很适合的。
sortset:这是有序,排重的列表,相当于java中的TreeSet。不过TreeSet是用的红黑树算法,sortset是用的skip table。sortset是很有用的一种数据结构,之前提到的收集箱列表就是用的sortset存放。不过这个数据结构很耗存储。特别是不是用ziplist时。后面谈优化的时候具体说。
Redis中的一些常见优化:
Redis中最好不要开启VM,在2.6版本也是默认关闭的。即使把vm指定到ssd中,redis作者也是反对的。
对于cache的redis,一定要设置最大内存。这样后台线程的LRU数据淘汰策略才能被触发。所以在未设置最大内存的情况下,对数据设置过期时间往往是无效的。这是一个坑,曾经跳到这个大坑里面,通宵解决性能问题。切记!
ziplist很有必要设置大一点。比如之前提到的收件箱长度是500条,但有些时候长度可能达到700条,所以把ziplist设置成1024会是一个好的策略。下面具体介绍下这几个参数:
hash-max-ziplist-entries:针对hash类型,只要hash的filed在这个范围内使用紧凑存储,这可以节约存储,也是为什么要尽量使用hash少使用string的理由,特别是在原子计数的时候,对一个用户可能要记录很多数量,一定要采用hash的策略,这是非常有用的。当然这个值绝不是越大越好,通常不要超过1024
hash-max-ziplist-value:hash的value的大小,在这个大小内会使用紧凑存储。这个值也不是越大越好,最好不要超过512。
list-max-ziplist-entries
list-max-ziplist-value
这两个参数和hash用法一样。不过这是针对list类型的。
zset-max-ziplist-entries
这个参数是针对sortset。在这个范围内,将不使用红黑树,是线性查找,所以这个值也不能太大,一般不要超过1024。
Redis的扩容问题:
Redis扩容目前来还是比较麻烦一点的。因为服务端是不支持数据的sharding的。需要在客户端做sharding。通常有两种sharding策略。一致性hash和非一致性hash。
对于非一致性hash:
可以实现把Redis实例事先切分成多个数据库,比如32或64个库。或者在同一个机器上启多台Redis实例,这样还可以利用多核系统多进程的优势提高并发。当单台机器上的Redis难以支撑时。把这些实例迁移到其他机器上,这样就变相的减轻了单台机器的压力。还可以把数据库切分开,分别放到多台机器上启动。这种做法最大的缺点是,当单台Redis实例的每个数据库都无法支撑数据时,麻烦就来了。这是需要程序把数据迁移出来,这个迁移往往是很耗时的,也是很容易出错的。对于线上的产品这往往是不可以接受的。那么就一致性hash登场吧。
对于一致性hash:
对于一致性hash的介绍可以搜索一下。主要的优势就是,在扩容的时候只需要移动受影响的节点。对于整个集群来说,这些受影响节点的数据是非常少的。如果对于cache来说,加一台机器,几乎不需要移动数据。让cache miss重建缓存也是可以的。当然这个得针对具体应用评估。不要因此而热点故障,挂网站了,呵呵。一致性hash的优势是可以任意加机器解决容量问题。理论上只要机器够,容量就不是问题。
嗯,暂时就写到这里吧,redis中的注意事项还很多,应用也绝不限于此,具体的官方文档已经介绍的很详细。用到的同学,可以发表和补充下Redis的其他用途。如有任何纰漏还多多指出,谢谢!
相关推荐
这个压缩包文件包含的"最全面的Redis应用代码"为学习者提供了丰富的资源,涵盖了Redis的多种应用场景和实现方式。让我们深入探讨Redis的基础知识、主要特性和常见应用场景。 1. Redis基础概念: - Redis是Remote ...
标题:“Redis实战 中文版 红丸出品”指明了这本书是关于Redis应用的实战指南,由“红丸”出品。Redis是一种广泛使用的开源内存数据结构存储系统,通常用作数据库、缓存或消息代理。Redis提供了一系列数据结构,包括...
Carlson所著的一本关于Redis应用的书籍。Redis是一种开源的内存数据结构存储系统,它通常用作数据库、缓存和消息代理。它支持多种类型的数据结构,如字符串(strings)、散列(hashes)、列表(lists)、集合(sets...
去年我写的培训用教材,redis应用场景简介,简单列举了一些Redis的使用场景。 发现下载积分居然无法调整……
TP6 Redis 应用方案详解 在本文中,我们将详细介绍 TP6 Redis 应用方案的实现细节,该方案涉及到微信登录、Token 认证、购物车管理、订单提交等多个方面。 微信登录流程 在微信登录流程中,前端调用 login 获取 ...
Redis Redis 应用构建实例.flv
本篇文章将详细讲解如何在Qt应用程序中利用Redis来实现一个高效的消息队列,以实现点对点的生产者-消费者模式。 首先,我们需要了解Qt和Redis的基础知识。Qt是一个跨平台的C++图形用户界面库,它提供了丰富的API...
关于Redis的集群方案,文档提到了codis作为目前使用最多的集群方案之一。Codis是Redis的水平拆分解决方案,通过增加更多的Redis实例来扩展读写能力。除此以外,Redis官方提供的分布式方案、twemproxy等也是实现Redis...
文档方面,`Redis on Windows.docx`、`Windows Service Documentation.docx`和`Redis on Windows Release Notes.docx`分别提供了关于Redis在Windows平台上的使用指南、服务安装说明以及版本发布说明,对于初学者和...
Linge-互联网行业中Redis的应用.pptx==Redis应用讲解PPT文件。Redis(Remote Dictionary Server ),远程字典服务,是一个开源的使用C语言编写、支持网络、可基于内存、分布式、可选持久性的键值对(Key-Value)存储...
2. **Redis应用实践**: - **缓存**:Redis的高速读写性能使其成为理想的缓存解决方案,可以缓解数据库的压力,提高Web应用的响应速度。 - **消息队列**:通过发布/订阅模式或列表数据结构,Redis可以实现简单的...
Spring MVC + Redis 应用实例,包括Srping MVC配置,spring和redis整合,以及简单的页面展示,提供写入内存的增删改查功能;编辑工具eclipse;代码本人调试过,可执行
#### 二、Redis的选择与应用场景 1. **大规模互联网应用:** 随着互联网应用规模的增长,对数据处理速度和并发能力的要求越来越高。Redis作为一种高性能的NoSQL数据库,能够满足这些需求。 2. **云存储:** 在...
在“Redis简单应用代码”中,我们可以探讨如何使用Redis进行基本操作,包括连接建立、数据读写以及常见命令的使用。下面将详细介绍Redis的一些核心概念和常用功能。 1. **Redis连接**: - 在编程中,我们需要先...
Redis核心原理与应用实践 Redis 作为互联网技术架构中最为广泛使用的中间件,它在存储系统中发挥着至关重要的作用。特别是在大型互联网公司中,Redis 是面试官最喜欢问的工程技能之一,这也反映了 Redis 在行业中的...
标签 "redis" 暗示了主题是关于Redis数据库的。Redis支持多种数据结构,如字符串、哈希表、列表、集合和有序集合,使其在处理多种应用场景时非常灵活。"php5.6" 指的是PHP的一个特定版本,5.6是PHP的一个稳定且广泛...
redis 应用 教程
Redis基本应用模型框架图、Redis缓存层设计图、Redis缓存层架构图
本进阶教程“Redis深度历险”旨在帮助读者深入理解Redis的核心特性和应用场景,从而更好地利用它来提升应用的性能和效率。 1. **Redis的数据结构** - 字符串(Strings):最基础的数据类型,可存储任意长度的字符串...