一、Redis是什么
1)Redis是REmote DIctionary Server的缩写,是一个key-
value存储系统
2)Redis提供了一些丰富的数据结构,包括Strings,Lists,
Hashes,
Sets和Ordered Sets以及Hashes。
包括对这些数据结
构的操做支持
3)Redis能够替代Memcached,而且解决了断电后数据彻底丢
失的问题
Download, extract and compile Redis with:
$ wget http://download.redis.io/releases/redis-3.2.5.tar.gz
$ tar xzf redis-3.2.5.tar.gz
The binaries that are now compiled are available in the src directory:Run Redis with:
You can interact with Redis using the built-in client:
三、Redis优势
1)性能极高,Redis能支持10万每秒的读写频率
2)丰富的数据类型及对应的操做
3)Redis的全部操做都是原子性的,同时Redis还支
持对几个操做合并后的原子性执行,也即支持事
务
4)丰富的特性,Redis还支持publish/subscribe,
key过时等特性
在50个并发的状况下请求10W次,写的速度是11W次/s,读的速
度是8.1w次/s
3)Linux2.6 Xeon X3320 2.5GHz的服务器上
4)经过本机的loopback interface接口上执行
redis经常使用五种数据类型:string,hash,list,set,sorted set
Redis内部使用一个redisObject对象来表示全部的key和value,redisObject最主要的信息如上图所示:
type表明一个value对象具体是何种数据类型,encoding是不一样数据类型在redis内部的存储方式,好比:
type=string表明value存储的是一个普通字符串,那么对应的encoding能够是raw或者是int,若是是int
则表明实际redis内部是按数值型类存储和表示这个字符串的
String是最经常使用的一种数据类型,普通的key/value存储
String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr,
decr等操做时会转成数值型进行计算,此时redisObject的encoding字段为int
好比,咱们存储供应商酒店价格的时候能够采起此结构,用酒店编码做为Key,
RatePlan+RoomType做为Filed,价格信息做为Value
Hash对应Value内部实际就是一个HashMap,实际这里会有2种不一样实现,这个Hash
的成员比较少时Redis为了节省内存会采用相似一维数组的方式来紧凑存储,而不
会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap;当成
员数量增大时会自动转成真正的HashMap,此时encoding为ht
lpush,rpush,lpop,rpop,lrang等
Redis list应用场景很是多,也是Redis最重要的数据结构之一,好比twitter的关注
列表,粉丝列表等均可以用Redis的list结构来实现
Redis list的实现为一个双向链表,便可以支持反向查找和遍历,更方便操做,不过
带来了部分额外的内存开销,Redis内部的不少实现,包括发送缓冲队列等也都是
用的这个数据结构
sadd,spop,smembers,sunion 等
Set对外提供的功能与list相似,当你须要存储一个列表数据,又不但愿出现重复
数据时,set 是一个很好的选择,而且set提供了判断某个成员是否在一个set集合
内的接口,这个也是list所不能提供的
Set 的内部实现是一个value永远为null的HashMap,实际就是经过计算hash的方
式来快速排除重复的,这也是set能提供判断一个成员是否在集合内的缘由
Sorted set的使用场景与set相似,区别是set不是自动有序的,而sorted set能够
经过用户额外提供一个优先级(score)的参数来为成员排序,而且是插入有序的,
即自动排序.当你须要一个有序的而且不重复的集合列表,那么能够选择sorted
set数据结构
Sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,
HashMap里放的是成员到score的映射,而跳跃表里存放的是全部的成员,排序依据
是HashMap里存的score,使用跳跃表的结构能够得到比较高的查找效率
Redis为不一样数据类型分别提供了一组参数来控制内存使用,咱们在前面提到过Redis Hash的value内部
是一个HashMap,若是该Map的成员数比较少,则会采用一维数组的方式来紧凑存储该Map,即省去了大量指
针的内存开销,这个参数在redis.conf配置文件中下面2项:
hash-max-zipmap-entries 64
hash-max-zipmap-value 512
含义是当value这个Map内部不超过多少个成员时会采用线性紧凑格式存储,默认是64,即value内部有64
个如下的成员就是使用线性紧凑存储,超过该值自动转成真正的HashMap
hash-max-zipmap-value 含义是当value这个Map内部的每一个成员值长度不超过多少字节就会采用线性紧
凑存储来节省空间
以上2个条件任意一个条件超 过设置值都会转换成真正的HashMap,也就不会再节省内存了,那么这个值是
不是设置的越大越好呢,答案固然是否认的,HashMap的优点就是查找和操做的时间复杂度都是O(1)的,而
放弃Hash采用一维存储则是O(n)的时间复杂度,若是成员数量不多,则影响不大,不然会严重影响性能,所
以要权衡好这个值的设置,整体上仍是时间成本和空间成本上的权衡
Redis的发布/订阅(Publish/Subscribe)功能类
似于传统的消息路由功能,发布者发布消息,订阅
者接收消息,沟通发布者和订阅者之间的桥梁是
订阅的Channel或者Pattern
订阅者和发布者之间的关系是松耦合的,发布者
不指定哪一个订阅者才能接收消息,订阅者不仅接
收特定发布者的消息
Redis能够按key设置过时时间,过时后将被自动
删除,这个特性让Redis很适合用来存储酒店动态
流量和价格信息
用TTL命令能够获取某个key值的过时时间,-1表
示不会过时
Redis目前对事务支持还比较简单,也即支持一些
简单的组合型的命令,只能保证一个client发起
的事务中的命令能够连续的执行,而中间不会插
入其余client的命令:因为Redis是单线程来处
理全部client的请求的因此作到这点是很容易
的
事务的执行过程当中,若是redis意外的挂了,这时
候事务可能只被执行了一半,能够用redis-
check-aof 工具进行修复
数据快照的原理是将整个Redis内存中存的全部
数据遍历一遍后,保存到一个扩展名为rdb的数据文件
中。经过SAVE命令能够调用这个过程
以上在redis.conf中的配置指出在多长时间内,有
多少次更新操做,就将数据同步到数据文件,这个
能够多个条件配合.上面的含义是900秒后有一个
key发生改变就执行save,300秒后有10个key发生
改变执行save,60秒有10000个key发生改变执行
save
10.1 数据快照的缺点是持久化以后若是出现
crash则会丢失一段数据,所以做者增长了另外
一种追加式的操做日志记录,叫append only
file,其日志文件以aof结尾,咱们通常称为aof文
件。要开启aof日志的记录,须要在配置文件中进
行以下设置:
10.2 appendonly配置若是不开启,可能会在断电时致使一段
时间内的数据丢失。由于redis自己同步数据文件是按save条
件来同步的,因此有的数据会在一段时间内只存在于内存中
appendfsync no/always/everysec
2)always:表示每次更新操做后手动调用fsync() 将数据写
到磁盘
3)everysec:表示每秒同步一次。通常用everysec
10.3 AOF文件只增不减会致使文件愈来愈大,重写过程以下
3)父子进程是并行执行的,在子进程遍历并写临时文件的时
候,父进程在照常接收请求,处理请求,写AOF,不过这时他是
把新来的AOF写在一个缓冲区中
4)子进程写完临时文件后就会退出.这时父进程会接收到子
进程退出的消息,他会把本身如今收集在缓冲区中的全部AOF
追加在临时文件中
5)最后把临时文件rename一下,更名为appendonly.aof, 这
时原来的aof文件被覆盖。整个过程完成
当Redis服务器挂掉时,重启时将按如下优先级恢复数据到内
存中:
1)若是只配置了AOF,重启时加载AOF文件恢复数据
2)若是同时配置了RBD和AOF,启动时只加载AOF文件恢复数据
3)若是只配置了RDB,启动时将加载dump文件恢复数据
十二、Redis主从复制
Master Redis Server Port:6379
Slave配置很简单,只须要在slave服务器的redis.conf加入:
slaveof 175.41.209.118 6379
启动master和slave,而后写入数据到master,读取slave,可
以看到数据被复制到slave了
配置好slave后,slave与master创建链接,而后发送sync命令。
不管是第一次链接仍是从新链接,master都会启动一个后台
进程,将数据库快照保存到文件中,同时master主进程会开始
收集新的写命令并缓存;后台进程完成写文件后,master就
发送文件给slave,slave将文件保存到硬盘上,再加载到内存
中, 接着master就会把缓存的命令转发给slave,后续master
将收到的写命令发送给slave;若是master同时收到多个
slave发来的同步链接命令,master只会启动一个进程来写数
据库镜像, 而后发送给全部的slave
2)多个slave能够链接同一个master外,还能够链接到其余
slave
3)主从复制不会阻塞master,在同步数据时,master能够继续
处理client请求
4)能够在master禁用数据持久化,注释掉master配置文件中的
全部save配置,只需在slave上配置数据持久化
官方提供了一个数据, Slave在21秒即完成了对
Amazon网站 10G key set的复制
13.1 Redis的客户端很是丰富,几乎全部流行的
语言都有客户端
客户端列表:http://redis.io/clients
Java客户端推荐Jedis: https://github.
com/xetorthio/jedis
13.2 Jedis目前Release版本是3.2.5,支持的特性以下,一句话归纳,该有的都有了,不应有的也有了
• Commands operating on any kind of values
• Commands operating on string values
• Commands operating on hashes
• Commands operating on lists
• Commands operating on sets
• Commands operating on sorted sets
• Persistence control commands
• Remote server control commands
• Sharding (MD5, MurmureHash)
• Sharding with pipelining
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
Jedis jedis = new Jedis("localhost");
String value = jedis.get("foo");
14.1 目前,Redis server没有提供shard功能,只能
在client端实现
Redis有些客户端实现了shard,好比Java客户端
Jedis.
JedisPool,JedisPoolConfig,JedisSharedInfo,
ShardedJedisPool等相关类来使用shared功能
14.2 Jedis shardedJedisPool的建立例子
<bean id="dataJedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxActive" value="200"/>
<property name="maxIdle" value="200"/>
<property name="maxWait" value="1000"/>
<property name="testOnBorrow" value="true"/>
<bean id="dataJedisShardInfo" class="redis.clients.jedis.JedisShardInfo">
<constructor-arg index="0" value="${redis.host}"/>
<constructor-arg index="1" value="${redis.port}"/>
<constructor-arg index="2" value="10000"/>
<bean id="dataShardedJedisPool" class="redis.clients.jedis.ShardedJedisPool">
<constructor-arg index="0" ref="dataJedisPoolConfig"/>
<constructor-arg index="1">
<ref bean="dataJedisShardInfo"/>
14.3 Jedis shardedJedisPool的使用
ShardedJedis shardedJedis = shardedJedisPool.getResource();
shardedJedisPool.returnResource(shardedJedis);
稳定版本的redis(2.4.5)只支持简单的
master-slave replication: 一个master写,多
个slave读。只能经过客户端一致性哈希本身作
sharding
Redis cluster是下一阶段最重要的功能之一,会
有集群的自动sharding,多节点容错等:集群功
将在3.0版本推出
1六、Redis Use In ChoiceHotels
16.1 Choice的Redis Server是一主一从,使用亚马
逊AWS虚拟机,机器配置以下:
4 EC2 Compute Units (2 virtual cores with 2
16.2 现状:天天约更新30万左右的数据,如今库里有400W条纪
录(400W个Key,使用的是Hash结构存储),每条数据都设有过
期时间,占用了2.5G的内存
为了提升读写性能Master关闭了Persistence功能,Slave只
负责同步备份Master的数据,不对外提供服务
另外一种可选方案是用Master提供写服务,Slave提供读服务来
实现读写分离
16.3 Master开启Save功能的影响:在dump过程当中,除了磁盘有
大量的IO操做之外,Redis是fork一个子进程来dump数据到硬
盘,原有进程占用30%+的CPU,dump数据的子进程单独另外占
用一个CPU
Master开启Save对性能的直接影响:TPS大概减小
30%
Choice Master Redis服务器开启Save功能后的明显影响是:
机器Load一直居高不下,大量请求超时:关闭Save功能后服
务器压力锐减,基本无请求超时状况发生
16.4 Redis开启AOF日志功能的影响:对性能有影
响,可是因为每次追加的数据量小,因此对性能的
影响相对小不少
Choice Master Reids开启AOF功能后,机器load
微升,对性能无明显影响
16.5 bgrewriteaof对性能的影响:为了定时减少
AOF文件的大小,Redis2.4之后增长了自动的
bgrewriteaof的功能,Redis会选择一个自认为负
载低的状况下执行bgrewriteaof,这个重写AOF文
件的过程是很影响性能的
Choice Master开启自动bgrewriteaof功能对系
统的明显影响是:高并发时段有请求超时,机器
load 明显上升几倍
16.6 目前较好的方案是:Mater关闭Save功能,关
闭AOF日志功能,以求达到性能最佳:Slave开启
Save并开启AOF日志功能,并开启bgrewriteaof
功能,不对外提供服务,这样Slave的负载整体上
会一直略高于Master负载,但Master性能达到最
好
从目前使用的状况来看,整体效果仍是比较理想
的, ChoiceHotels的价格存储使用Redis的Hash
结构也很是适合,HotelCode+Date最为key, 这样
的key很容易设置过时,RatePlan+RoomType做为
Filed, 价格和流量是Value
目前天天从GTA到Choice大约500w个请求,整个
过程80%的请求在500毫秒内返回,基本无超时现
象发生
used_memory_peak_human:2.46G
aof_current_size:3874203906
db0:keys=4073286,expires=4073286