Redis介绍及实践分享

一、Redis是什么
1)Redis是REmote DIctionary Server的缩写,是一个key- value存储系统
2)Redis提供了一些丰富的数据结构,包括Strings,Lists, HashesSets和Ordered Sets以及Hashes。 包括对这些数据结 构的操做支持
3)Redis能够替代Memcached,而且解决了断电后数据彻底丢 失的问题
4)Redis官方网站: http://redis.io
    Redis做者Blog: http://antirez.com

二、Redis安装
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
$ cd redis-3.2.5
$ make

The binaries that are now compiled are available in the src directory:Run Redis with:

$ src/redis-server
You can interact with Redis using the built-in client:
$ src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"

三、Redis优势
1)性能极高,Redis能支持10万每秒的读写频率
2)丰富的数据类型及对应的操做
3)Redis的全部操做都是原子性的,同时Redis还支 持对几个操做合并后的原子性执行,也即支持事
4)丰富的特性,Redis还支持publish/subscribe, key过时等特性

四、Redis性能
如下摘自官方测试描述:
在50个并发的状况下请求10W次,写的速度是11W次/s,读的速 度是8.1w次/s

测试环境:
1)50个并发,请求10W次
2)读和写大小为256bytes的字符串
3)Linux2.6 Xeon X3320 2.5GHz的服务器上
4)经过本机的loopback interface接口上执行

五、Redis数据类型
redis经常使用五种数据类型:string,hash,list,set,sorted set
 
Redis内部使用一个redisObject对象来表示全部的key和value,redisObject最主要的信息如上图所示:
    type表明一个value对象具体是何种数据类型,encoding是不一样数据类型在redis内部的存储方式,好比: type=string表明value存储的是一个普通字符串,那么对应的encoding能够是raw或者是int,若是是int 则表明实际redis内部是按数值型类存储和表示这个字符串的

Commands 集合: http://redis.io/commands

5.1 String
经常使用命令:
set,get,decr,incr,mget 等

应用场景:
String是最经常使用的一种数据类型,普通的key/value存储

实现方式:
String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr, decr等操做时会转成数值型进行计算,此时redisObject的encoding字段为int

5.2 Hash
经常使用命令:
hget,hset,hgetall 等

应用场景:
好比,咱们存储供应商酒店价格的时候能够采起此结构,用酒店编码做为Key, RatePlan+RoomType做为Filed,价格信息做为Value

实现方式:
Hash对应Value内部实际就是一个HashMap,实际这里会有2种不一样实现,这个Hash 的成员比较少时Redis为了节省内存会采用相似一维数组的方式来紧凑存储,而不 会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap;当成 员数量增大时会自动转成真正的HashMap,此时encoding为ht

5.3 List
经常使用命令:
lpush,rpush,lpop,rpop,lrang等

应用场景:
Redis list应用场景很是多,也是Redis最重要的数据结构之一,好比twitter的关注 列表,粉丝列表等均可以用Redis的list结构来实现

实现方式:
Redis list的实现为一个双向链表,便可以支持反向查找和遍历,更方便操做,不过 带来了部分额外的内存开销,Redis内部的不少实现,包括发送缓冲队列等也都是 用的这个数据结构

5.4 Set
经常使用命令:
sadd,spop,smembers,sunion 等

应用场景:
Set对外提供的功能与list相似,当你须要存储一个列表数据,又不但愿出现重复 数据时,set 是一个很好的选择,而且set提供了判断某个成员是否在一个set集合 内的接口,这个也是list所不能提供的

实现方式:
Set 的内部实现是一个value永远为null的HashMap,实际就是经过计算hash的方 式来快速排除重复的,这也是set能提供判断一个成员是否在集合内的缘由

5.5 Sorted set
经常使用命令:
zadd,zrange,zrem,zcard等

使用场景:
Sorted set的使用场景与set相似,区别是set不是自动有序的,而sorted set能够 经过用户额外提供一个优先级(score)的参数来为成员排序,而且是插入有序的, 即自动排序.当你须要一个有序的而且不重复的集合列表,那么能够选择sorted  set数据结构

实现方式:
Sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序, HashMap里放的是成员到score的映射,而跳跃表里存放的是全部的成员,排序依据 是HashMap里存的score,使用跳跃表的结构能够得到比较高的查找效率

5.6 内存优化
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发布/订阅
Redis的发布/订阅(Publish/Subscribe)功能类 似于传统的消息路由功能,发布者发布消息,订阅 者接收消息,沟通发布者和订阅者之间的桥梁是 订阅的Channel或者Pattern

订阅者和发布者之间的关系是松耦合的,发布者 不指定哪一个订阅者才能接收消息,订阅者不仅接 收特定发布者的消息

七、Redis数据过时设置
Redis能够按key设置过时时间,过时后将被自动 删除,这个特性让Redis很适合用来存储酒店动态 流量和价格信息

用TTL命令能够获取某个key值的过时时间,-1表 示不会过时

八、Redis事务支持
Redis目前对事务支持还比较简单,也即支持一些 简单的组合型的命令,只能保证一个client发起 的事务中的命令能够连续的执行,而中间不会插 入其余client的命令:因为Redis是单线程来处 理全部client的请求的因此作到这点是很容易

事务的执行过程当中,若是redis意外的挂了,这时 候事务可能只被执行了一半,能够用redis- check-aof 工具进行修复

九、Redis数据存储
9.1 数据快照
数据快照的原理是将整个Redis内存中存的全部 数据遍历一遍后,保存到一个扩展名为rdb的数据文件 中。经过SAVE命令能够调用这个过程

9.2 数据快照配置
save 900 1
save 300 10
save 60 10000
以上在redis.conf中的配置指出在多长时间内,有 多少次更新操做,就将数据同步到数据文件,这个 能够多个条件配合.上面的含义是900秒后有一个 key发生改变就执行save,300秒后有10个key发生 改变执行save,60秒有10000个key发生改变执行 save

十、Redis AOF
10.1 数据快照的缺点是持久化以后若是出现 crash则会丢失一段数据,所以做者增长了另外 一种追加式的操做日志记录,叫append only  file,其日志文件以aof结尾,咱们通常称为aof文 件。要开启aof日志的记录,须要在配置文件中进 行以下设置:
appendonly yes

10.2 appendonly配置若是不开启,可能会在断电时致使一段 时间内的数据丢失。由于redis自己同步数据文件是按save条 件来同步的,因此有的数据会在一段时间内只存在于内存中
appendfsync no/always/everysec
1)no:表示等操做系统进行数据缓存同步到磁盘
2)always:表示每次更新操做后手动调用fsync() 将数据写 到磁盘
3)everysec:表示每秒同步一次。通常用everysec

10.3 AOF文件只增不减会致使文件愈来愈大,重写过程以下
1)Redis经过fork产生子进程
2)子进程将当前全部数据写入一个临时文件
3)父子进程是并行执行的,在子进程遍历并写临时文件的时 候,父进程在照常接收请求,处理请求,写AOF,不过这时他是 把新来的AOF写在一个缓冲区中
4)子进程写完临时文件后就会退出.这时父进程会接收到子 进程退出的消息,他会把本身如今收集在缓冲区中的全部AOF 追加在临时文件中
5)最后把临时文件rename一下,更名为appendonly.aof, 这 时原来的aof文件被覆盖。整个过程完成

十一、Redis数据恢复
当Redis服务器挂掉时,重启时将按如下优先级恢复数据到内 存中:
1)若是只配置了AOF,重启时加载AOF文件恢复数据
2)若是同时配置了RBD和AOF,启动时只加载AOF文件恢复数据
3)若是只配置了RDB,启动时将加载dump文件恢复数据

十二、Redis主从复制
12.1 Master/Slave配置
Master IP:175.41.209.118
Master Redis Server Port:6379

Slave配置很简单,只须要在slave服务器的redis.conf加入:
slaveof 175.41.209.118 6379
启动master和slave,而后写入数据到master,读取slave,可 以看到数据被复制到slave了

用途:读写分离,数据备份,灾难恢复等

12.2 Redis主从复制过程
配置好slave后,slave与master创建链接,而后发送sync命令。 不管是第一次链接仍是从新链接,master都会启动一个后台 进程,将数据库快照保存到文件中,同时master主进程会开始 收集新的写命令并缓存;后台进程完成写文件后,master就 发送文件给slave,slave将文件保存到硬盘上,再加载到内存 中, 接着master就会把缓存的命令转发给slave,后续master 将收到的写命令发送给slave;若是master同时收到多个 slave发来的同步链接命令,master只会启动一个进程来写数 据库镜像, 而后发送给全部的slave

12.3 Redis主从复制特色
1)master能够拥有多个slave
2)多个slave能够链接同一个master外,还能够链接到其余 slave
3)主从复制不会阻塞master,在同步数据时,master能够继续 处理client请求
4)能够在master禁用数据持久化,注释掉master配置文件中的 全部save配置,只需在slave上配置数据持久化
5)提升系统的伸缩性

12.4 Redis主从复制速度
          官方提供了一个数据, Slave在21秒即完成了对 Amazon网站 10G key set的复制

1三、Redis客户端
13.1 Redis的客户端很是丰富,几乎全部流行的 语言都有客户端
客户端列表:http://redis.io/clients
Java客户端推荐Jedis: https://github. com/xetorthio/jedis

13.2 Jedis目前Release版本是3.2.5,支持的特性以下,一句话归纳,该有的都有了,不应有的也有了
• Sorting
• Connection handling
• 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
• Transactions
• Pipelining
• Publish/Subscribe
• Persistence control commands
• Remote server control commands
• Connection pooling
• Sharding (MD5, MurmureHash)
• Key-tags for sharding
• Sharding with pipelining

13.3 Jedis使用
添加Maven依赖:
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>

最简单的使用方式:
Jedis jedis = new Jedis("localhost");
jedis.set("foo", "bar");
String value = jedis.get("foo");

更多高级用法参考: https://github.com/xetorthio/jedis/wiki

1四、Redis shard
14.1 目前,Redis server没有提供shard功能,只能 在client端实现
Redis有些客户端实现了shard,好比Java客户端 Jedis.

Jedis使用一致性哈希算法实现shard,提供
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>
<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>
<bean id="dataShardedJedisPool" class="redis.clients.jedis.ShardedJedisPool">
<constructor-arg index="0" ref="dataJedisPoolConfig"/>
<constructor-arg index="1">
<list>
<ref bean="dataJedisShardInfo"/>
</list>
</constructor-arg>
</bean>

14.3 Jedis shardedJedisPool的使用
ShardedJedis shardedJedis = shardedJedisPool.getResource();
//xxoo
shardedJedisPool.returnResource(shardedJedis);

1五、Redis cluster
稳定版本的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虚拟机,机器配置以下:
7.5 GB memory
4 EC2 Compute Units (2 virtual cores with 2
EC2 Compute Units each)
64-bit platform
I/O Performance: High

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性能达到最

16.7 总结:
从目前使用的状况来看,整体效果仍是比较理想 的, ChoiceHotels的价格存储使用Redis的Hash 结构也很是适合,HotelCode+Date最为key, 这样 的key很容易设置过时,RatePlan+RoomType做为 Filed, 价格和流量是Value
目前天天从GTA到Choice大约500w个请求,整个 过程80%的请求在500毫秒内返回,基本无超时现 象发生

16.8 Redis Master Info
redis_version:2.4.4
connected_clients:171
connected_slaves:1
used_memory_human:2.37G
used_memory_peak_human:2.46G
aof_enabled:0
expired_keys:1595004
keyspace_hits:2611419705
keyspace_misses:55827727
role:master
aof_current_size:3874203906
aof_base_size:3850549480
db0:keys=4073286,expires=4073286


相关文章
相关标签/搜索