redis + 主从 + 持久化 + 分片 + 集群 + spring集成

Redis是一个基于内存的数据库,其不只读写速度快,每秒能够执行大约110000的写操做,81000的读取操做,并且其支持存储字符串,哈希结构,链表,集合丰富的数据类型。因此获得不少开发者的青睐。加之其支持主从、持久化等功能,3.0版本开始正式提供分片技术、让其在大型互联网应用中大显身手,本文经过实际操做和理论相配合,对redis进行详细地阐述。html

1、redis的安装与使用java

下载直接去redis的官网http://redis.io/进行不一样操做系统对应的版本。本文中采用的redis的版本为3.2.五、linux平台,安装过程以下node

[root@hbase usr]# tar -zxf redis-3.2.5.tar.gz 
[root@hbase usr]# cd redis-3.2.5
[root@hbase redis-3.2.5]# ll
[root@hbase redis-3.2.5]# make
[root@hbase redis-3.2.5]# cd src
[root@hbase src]# ll

以后咱们会发现其中redis-server和redis-cli,这两个文件分别对应启动redis的服务端和客户端,启动服务端linux

[root@hbase src]# ./redis-server 
11579:M 13 Nov 15:07:01.399 # Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now.
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 3.2.5 (00000000/0) 32 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 11579
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                                               

11579:M 13 Nov 15:07:01.404 # Server started, Redis version 3.2.5
11579:M 13 Nov 15:07:01.409 * The server is now ready to accept connections on port 6379

能够看到,redis正常启动,6379 是 redis 服务端口,这个端口在redis.conf中能够进行配置,稍后咱们讲解配置文件的时候会提到。不要关闭这个窗口,由于当前redis-server不是在后台运行,咱们另起一个窗口,在当前目录下进行客户端链接服务端。redis

[hadoop@hbase src]$ ./redis-cli 
127.0.0.1:6379> 

说明一切正常,linux环境下的redis安装成功,至于windows下的安装过程相对更加简单,只需打开.exe文件便可,不在详细演示算法

2、redis数据类型spring

2.1 string数据库

字符串类型是Redis中最为基础的数据存储类型,它在Redis中是二进制安全的,在Redis中字符串类型的Value最多能够容纳的数据长度是512M。除了get、set、做外,Redis还提供了其余的一些诸如追加、递增等功能。apache

set key value O(1) 设定该key对应的value,若是该Key已经存在,则覆盖其原有值。get key O(1) 获取指定Key的value,若是该Key不存在,返回nil。windows

setnx key value O(1) 若是指定的Key不存在,则设定该Key持有指定字符串value,此时其效果等价于set命令。若是该Key已经存在,该命令将不作任何操做。 

 1 127.0.0.1:6379> set hello word
 2 OK
 3 127.0.0.1:6379> get hello
 4 "word"
 5 127.0.0.1:6379> set hello world
 6 OK
 7 127.0.0.1:6379> set hello world
 8 OK
 9 127.0.0.1:6379> get hello
10 "world"
11 127.0.0.1:6379> get world
12 (nil)
13 127.0.0.1:6379> set hello world_new
14 OK
15 127.0.0.1:6379> get hello
16 "world_new"
17 127.0.0.1:6379> setnx hello nihao
18 (integer) 0
19 127.0.0.1:6379> setnx new_hello nihao
20 (integer) 1
View Code

mset key value [key value ...] O(N) N表示指定Key的数量。该命令能够当作是屡次迭代执行set命令。

mget key [key ...] O(N) N表示获取Key的数量。返回全部指定key的value,若是其中某个key不存在,该key的value将返回nil。 

msetnx key value [key value ...] O(N) N表示指定key的数量。该命令原子性的完成参数中全部key/value的设置操做,其具体行为能够当作是屡次迭代执行setnx命令。若是在这一批keys中有任意一个key已经存在,那么该操做将所有回滚,即全部的修改都不会生效。 1表示全部keys都设置成功,0则表示没有任何key被修改。 

 1 127.0.0.1:6379> mset key1 hello key2 world
 2 OK
 3 127.0.0.1:6379> mget key1 key2
 4 1) "hello"
 5 2) "world"
 6 127.0.0.1:6379> mget key1 key3
 7 1) "hello"
 8 2) (nil)
 9 127.0.0.1:6379> msetnx key1 nihao key3 hi
10 (integer) 0
11 127.0.0.1:6379> msetnx key3 nihao key4 hi
12 (integer) 1
View Code

append key value  O(1) 若key已经存在,将value的数据追加到对应key的value的末尾。若是该key不存在,append命令将会建立一个新的key/value。

strlen key O(1) 返回指定Key的字符值长度,若是该Key不存在,返回0。

decr key O(1) 将指定key的value原子性的递减1。若是该key不存在,其初始值为0,在decr以后其值为-1。若是value的值不能转换为整型值,该操做将执行失败。

incr key O(1) 将指定key的value原子性的递增1。若是该Key不存在,其初始值为0,在incr以后其值为1。若是value的值不能转换为整型值,该操做将执行失败。 

decrby key decrement O(1) 将指定key的value原子性的减小decrement,其余同decr。

incrby key increment O(1) 将指定key的value原子性的增长increment,其余同incr。 

 1 127.0.0.1:6379> append k1 hello
 2 (integer) 5
 3 127.0.0.1:6379> append k1 world
 4 (integer) 10
 5 127.0.0.1:6379> get k1
 6 "helloworld"
 7 127.0.0.1:6379> strlen k1
 8 (integer) 10
 9 127.0.0.1:6379> set k2 1
10 OK
11 127.0.0.1:6379> incr k2
12 (integer) 2
13 127.0.0.1:6379> get k2
14 "2"
15 127.0.0.1:6379> decr k2
16 (integer) 1
17 127.0.0.1:6379> get k2
18 "1"
19 127.0.0.1:6379> incrby k2 5
20 (integer) 6
21 127.0.0.1:6379> decrby k2 5
22 (integer) 1
23 127.0.0.1:6379> get k2
24 "1"
View Code

2.2 redis之数据类型list

在Redis中,List类型是按照插入顺序排序的字符串链表。和数据结构中的普通链表同样,咱们能够在其头部(left)和尾部(right)添加新的元素,该操做也能够在常量时间内完成。在插入时,若是该键并不存在,Redis将为该键建立一个新的链表。与此相反,若是链表中全部的元素均被移除,那么该键也将会被从数据库中删除。List中能够包含的最大元素数量是4294967295。 

lpush key value [value ...] O(1) 在指定key所对应的List头部插入全部values。若是该Key不存在,则插入以前建立一个与该key关联的空链表。

lpop key O(1) 返回并弹出指定key对应链表的第一个元素。若是该Key不存在,返回nil。

lrange key start stop start和end都是0-len,即0表示链表头部的第一个元素。其中start的值也能够为负值,-1将表示链表中的最后一个元素,即尾部元素,-2表示倒数第二个并以此类推。该命令在获取元素时,start和end位置上的元素也会被取出。若是start的值大于链表中元素的数量,空链表将会被返回。若是end的值大于元素的数量,该命令则获取从start(包括start)开始,链表中剩余的全部元素。 

lpushx key value O(1) 当指定的key存在时,在其所关联的list的头部插入参数中给出的value,不然将不会有任何操做发生。    

lrem key count value O(N) 在指定key关联的链表中,删除前count个值等于value的元素。若是count大于0,从头向尾遍历并删除,若是count小于0,则从尾向头遍历并删除。若是count等于0,则删除链表中全部等于value的元素。若是指定的key不存在,则直接返回0。

llen key O(1) 返回指定key关联的链表中元素的数量,若是该Key不存在,则返回0。。

lset  key index value O(N) 设定链表中指定位置的值为新值,其中0表示第一个元素,即头部元素,-1表示尾部元素。 

 1 127.0.0.1:6379> lpush k1 v1 v2 v3
 2 (integer) 3
 3 127.0.0.1:6379> lrange k1 0 2
 4 1) "v3" 2) "v2" 3) "v1"
 5 127.0.0.1:6379> lpop k1
 6 "v3"
 7 127.0.0.1:6379> lrange k1 0 2
 8 1) "v2" 2) "v1"
 9 127.0.0.1:6379> lpush k1 v4
10 (integer) 3
11 127.0.0.1:6379> lrange k1 0 2
12 1) "v4" 2) "v2" 3) "v1"
13 127.0.0.1:6379> lpush k1 v4
14 (integer) 4
15 127.0.0.1:6379> lpush k1 v4
16 (integer) 5
17 127.0.0.1:6379> lpush k1 v4
18 (integer) 6
19 127.0.0.1:6379> lrange k1 0 5
20 1) "v4" 2) "v4" 3) "v4" 4) "v4" 5) "v2" 6) "v1"
21 127.0.0.1:6379> lrem k1 2 v4  # 删除前两个值为v4的元素
22 (integer) 2
23 127.0.0.1:6379> lrange k1 0 3
24 1) "v4" 2) "v4" 3) "v2" 4) "v1"
25 127.0.0.1:6379> llen k1
26 (integer) 4
27 127.0.0.1:6379> lset k1 1 k5  #设置索引为1的值为k5
28 OK
29 127.0.0.1:6379> lrange k1 0 3
30 1) "v4" 2) "k5" 3) "v2" 4) "v1"
View Code

rpush key value [value ...] O(1) 在指定key所对应的List尾部插入全部values。若是该Key不存在,则插入以前建立一个与该key关联的空链表。

rpop key O(1) 返回并弹出指定key对应链表的最后一个元素。若是该Key不存在,返回nil。

rpushx key value O(1) 当指定的key存在时,在其所关联的list的尾部插入参数中给出的value,不然将不会有任何操做发生。  

 1 127.0.0.1:6379> lrange k1 0 3
 2 1) "v4" 2) "k5" 3) "v2" 4) "v1"
 3 127.0.0.1:6379> rpushx k1 k6
 4 (integer) 5
 5 127.0.0.1:6379> lrange k1 0 4
 6 1) "v4" 2) "k5" 3) "v2" 4) "v1" 5) "k6"
 7 127.0.0.1:6379> rpush k1 k7 k8  #在尾部添加元素
 8 (integer) 7
 9 127.0.0.1:6379> lrange k1 0 6
10 1) "v4" 2) "k5" 3) "v2" 4) "v1" 5) "k6" 6) "k7" 7) "k8"  
11 127.0.0.1:6379> rpop k1  #弹出尾部的元素
12 "k8"
13 127.0.0.1:6379> lrange k1 0 5
14 1) "v4" 2) "k5" 3) "v2" 4) "v1" 5) "k6" 6) "k7"
15 127.0.0.1:6379> 
View Code

2.3 hash

Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。每个Hash能够存储4294967295个键值对。

hset key field value O(1) 为指定的key设置field/value对,若key不存在,则建立新key,并建立field/value对,若该key中已经存在,则用新值覆盖其原有值。

hget key field O(1) 返回指定key中指定field所对应的值,若key或field不存在,返回nil。

hmget key field [field ...] O(N) 获取指定fields关联的一组values。若是请求的field不存在,其值返回nil。

hmset key field value [field value ...] O(N) 逐个依次设置参数中给出的field/value对。若是其中某个field已经存在,则用新值覆盖原有值。若是key不存在,则建立新key,同时设定参数中的field/value。

hsetnx key field value O(1) 只有当key或field不存在时,为指定的key设定field/value对,不然该命令不会进行任何操做。

 1 127.0.0.1:6379> hset k1 f1 v1
 2 (integer) 1
 3 127.0.0.1:6379> hset k1 f2 v2
 4 (integer) 1
 5 127.0.0.1:6379> hget k1 f1
 6 "v1"
 7 127.0.0.1:6379> hmget k1 f1 f2
 8 1) "v1" 2) "v2"
 9 127.0.0.1:6379> hmset k1 f3 v3 f4 v4
10 OK
11 127.0.0.1:6379> hmget k1 f1 f2 f3 f4
12 1) "v1" 2) "v2" 3) "v3" 4) "v4"
13 127.0.0.1:6379> hsetnx k1 f1 v5
14 (integer) 0
15 127.0.0.1:6379> hsetnx k1 f5 v5
16 (integer) 1
17 127.0.0.1:6379> hmget k1 f1 f2 f3 f4 f5
18 1) "v1" 2) "v2" 3) "v3" 4) "v4" 5) "v5"
View Code

hkeys key O(N) 返回指定key的全部fields名。

hvals key O(N) 返回指定Key的全部values名。

hexists key field O(1) 判断指定key中的指定field是否存在。1表示存在,0表示field或key不存在。

hlen key O(1) 获取该key所包含的field的数量。返回key包含的field数量,若是key不存在,返回0。

hdel key field [field ...] O(N) 从指定key的hash中删除指定的多个字段,若是不存在的字段将被忽略。

hincrby key field increment O(1) 增长指定key中指定field对应的value的值。若是key或field不存在,该命令将会建立一个新key或新field。 

 1 127.0.0.1:6379> hkeys k1
 2 1) "f1" 2) "f2" 3) "f3" 4) "f4" 5) "f5"
 3 127.0.0.1:6379> hvals k1
 4 1) "v1" 2) "v2" 3) "v3" 4) "v4" 5) "v5"
 5 127.0.0.1:6379> hexists k1 f1
 6 (integer) 1
 7 127.0.0.1:6379> hlen k1 
 8 (integer) 5
 9 127.0.0.1:6379> hdel k1 f5
10 (integer) 1
11 127.0.0.1:6379> hset k1 f5 1
12 (integer) 1
13 127.0.0.1:6379> hvals k1
14 1) "v1" 2) "v2" 3) "v3" 4) "v4" 5) "1"
15 127.0.0.1:6379> hincrby k1 f5 2
16 (integer) 3
17 127.0.0.1:6379> hvals k1
18 1) "v1" 2) "v2" 3) "v3" 4) "v4" 5) "3"
View Code

2.4 set

在Redis中, Set类型看做为没有排序的字符集合,和List类型同样,咱们也能够在该类型的数据值上执行添加、删除或判断某一元素是否存在等操做。set可包含的最大元素数量是4294967295。set集合中不容许出现重复的元素。 

sadd key member [member ...] O(N) 若该Key不存在,该命令将会建立一个新的set。如有的成员在set中已经存在,该成员将被忽略,而其它成员仍将会被正常插入。

spop key O(1) 随机的移除并返回set中的某一成员。

scard key O(1) 获取set中成员的数量。

sismember key member O(1) 判断参数中指定成员是否已经存在于与key所在的set集合中。

smembers key O(N) 获取与该key关联的set中全部的成员。     

srem key member [member ...] O(N) 从与key关联的set中删除参数中指定的成员,不存在的参数成员将被忽略。

 1 127.0.0.1:6379> sadd k1 m1
 2 (integer) 1
 3 127.0.0.1:6379> sadd k1 m2
 4 (integer) 1
 5 127.0.0.1:6379> scard k1
 6 (integer) 2
 7 127.0.0.1:6379> spop k1
 8 "m2"
 9 127.0.0.1:6379> sadd k1 m3
10 (integer) 1
11 127.0.0.1:6379> sismember k1 m3
12 (integer) 1
13 127.0.0.1:6379> smembers k1
14 1) "m3"
15 2) "m1"
16 127.0.0.1:6379> srem k1 m1
17 (integer) 1
18 127.0.0.1:6379> smembers k1
19 1) "m3"
View Code

sdiff key [key ...] O(N) 返回第一个key所关联的set和其后全部keys所关联的sets中成员的差别。

sinter  key [key ...] O(N*M) 返回参数中全部keys关联的sets中成员的交集。

sunion key [key ...] O(N) 返回参数中全部keys关联的sets中成员的并集。  

127.0.0.1:6379> smembers k1
1) "m2"
2) "m1"
3) "m3"
127.0.0.1:6379> smembers k2
1) "m3"
2) "m1"
3) "m4"
127.0.0.1:6379> sdiff k1 k2
1) "m2"
127.0.0.1:6379> sinter k1 k2
1) "m1"
2) "m3"
127.0.0.1:6379> sunion k1 k2
1) "m3"
2) "m1"
3) "m2"
4) "m4"
View Code

 2.5 sorted set

sorted-set和set类型极为类似,都不容许重复的成员出如今一个Set中。它们之间的主要差异是sorted-set中的每个成员都会有一个分数(score)与之关联,Redis正是经过分数来为集合中的成员进行从小到大的排序。

zadd key score member [score] [member] O(log(N)) 添加参数中指定的全部成员及其分数到指定key的sorted-sett中。

zcard key O(1) 获取与该key相关联的sorted-set中包含的成员数量。

zscore key member O(1) 获取指定Key的指定成员的分数。若是该成员存在,以字符串的形式返回其分数,不然返回nil。

zcount key min max O(log(N)+M) 用于获取分数(score)在min和max之间的成员数量。min和max表示的范围是闭区间范围,即min <= score <= max内的成员将被返回。

zincrby key increment member O(log(N)) 将为指定Key中的指定成员增长指定的分数。

zrange key start stop [WITHSCORES] O(log(N)+M)  返回顺序在start和stop指定范围内的成员列表。

zrangebyscore key min max [WITHSCORES] [LIMIT offset count] O(log(N)+M) 将返回分数在min和max之间的全部成员列表。

zrem key member [member ...] O(M log(N)) 移除参数中指定的成员,其中不存在的成员将被忽略。

zremrangebyscore key min max O(log(N)+M) 删除分数在min和max之间的全部成员,即知足表达式min <= score <= max的全部成员。 

 1 127.0.0.1:6379> zadd k1 1 m1
 2 (integer) 1
 3 127.0.0.1:6379> zadd k1 2 m2
 4 (integer) 1
 5 127.0.0.1:6379> zadd k1 3 m3
 6 (integer) 1
 7 127.0.0.1:6379> zcard k1
 8 (integer) 3
 9 127.0.0.1:6379> zscore k1 m1
10 "1"
11 127.0.0.1:6379> zscore k1 m2
12 "2"
13 127.0.0.1:6379> zcount k1 2 3
14 (integer) 2
15 127.0.0.1:6379> zincrby k1 3 m3
16 "6"
17 127.0.0.1:6379> zrange k1 1 10
18 1) "m2"
19 2) "m3"
20 127.0.0.1:6379> zrange k1 0 10
21 1) "m1"
22 2) "m2"
23 3) "m3"
24 127.0.0.1:6379> zcount k1 0 10
25 (integer) 3
26 127.0.0.1:6379> zrangebyscore k1 0 6
27 1) "m1"
28 2) "m2"
29 3) "m3"
30 127.0.0.1:6379> zrem k1 m1
31 (integer) 1
32 127.0.0.1:6379> zcard k1
33 (integer) 2
34 127.0.0.1:6379> zremrangebyscore k1 2 3
35 (integer) 1
36 127.0.0.1:6379> zremrangebyscore k1 2 10
37 (integer) 1
38 127.0.0.1:6379> zcard k1
39 (integer) 0
View Code

3、redis的相关命令 

keys pattern O(N) 获取全部匹配pattern参数的Keys。须要说明的是,在咱们的正常操做中应该尽可能避免对该命令的调用,由于对于大型数据库而言,该命令是很是耗时的。pattern支持glob-style的通配符格式,如*表示任意一个或多个字符,?表示任意字符,[abc]表示方括号中任意一个字母。
del key [key ...] O(N) 从数据库删除中参数中指定的keys,若是指定键不存在,则直接忽略。
exists key O(1) 判断指定键是否存在。 1表示存在,0表示不存在。
move key db O(1) 将当前数据库中指定的键key移动到参数中指定的数据库中。若该key在目标数据库中已经存在,或者在当前数据库中不存在,该命令将不作任何操做并返回0。 移动成功返回1,不然0。
rename key newkey O(1) 为指定指定的键从新命名,若是两个keys的命令相同,或者是源key不存在,该命令都会返回相关的错误信息。若是newKey已经存在,则直接覆盖。
renamenx key newkey O(1) 若是新值不存在,则将参数中的原值修改成新值。其它条件和rename一致。1表示修改为功,不然0。
expire key seconds O(1) 该命令为指定的key设定超时的秒数,在超过该时间后,key被自动的删除。若是该Key在超时以前被修改,与该键关联的超时将被移除。1表示超时被设置,0则表示Key不存在,或不能被设置。
expireat key timestamp O(1) 该命令的逻辑功能和expire彻底相同,差异是该命令指定的超时时间是绝对时间,而不是相对时间。该时间参数是Unix timestamp格式的,即从1970年1月1日开始所流经的秒数。1表示超时被设置,0则表示Key不存在,或不能被设置。
ttl key O(1) 获取该键所剩的超时描述。若是该键不存在或没有超时设置,则返回-1。
type key O(1) 获取与参数中指定键关联值的类型,该命令将以字符串的格式返回。 返回的字符串为string、list、set、hash和zset,若是key不存在返回none。

 1 127.0.0.1:6379> keys *
 2 (empty list or set)
 3 127.0.0.1:6379> set str string
 4 OK
 5 127.0.0.1:6379> hset hash1 f1 v1
 6 (integer) 1
 7 127.0.0.1:6379> sadd set1 v1
 8 (integer) 1
 9 127.0.0.1:6379> zadd sortedset1 1 v1
10 (integer) 1
11 127.0.0.1:6379> lpush list1 v1 v2
12 (integer) 2
13 127.0.0.1:6379> keys *
14 1) "hash1"
15 2) "sortedset1"
16 3) "list1"
17 4) "str"
18 5) "set1"
19 127.0.0.1:6379> keys s*
20 1) "sortedset1"
21 2) "str"
22 3) "set1"
23 127.0.0.1:6379> exists list1
24 (integer) 1
25 127.0.0.1:6379> rename list1 list2
26 OK
27 127.0.0.1:6379> keys *
28 1) "hash1"
29 2) "sortedset1"
30 3) "str"
31 4) "list2"
32 5) "set1"
33 127.0.0.1:6379> type list2
34 list
35 127.0.0.1:6379> type str
36 string
37 127.0.0.1:6379> set str2 v2
38 OK
39 127.0.0.1:6379> expire str2 10
40 (integer) 1
41 127.0.0.1:6379> ttl str2
42 (integer) 6
43 127.0.0.1:6379> ttl str2
44 (integer) -2
45 127.0.0.1:6379> keys *
46 1) "hash1"
47 2) "sortedset1"
48 3) "str"
49 4) "list2"
50 5) "set1"
51 127.0.0.1:6379> move str 1
52 (integer) 1
53 127.0.0.1:6379> keys *
54 1) "hash1"
55 2) "sortedset1"
56 3) "list2"
57 4) "set1"
58 127.0.0.1:6379> select 1
59 OK
60 127.0.0.1:6379[1]> keys *
61 1) "str"
62 127.0.0.1:6379[1]> select 0
63 OK
64 127.0.0.1:6379> del set1
65 (integer) 1
66 127.0.0.1:6379> keys *
67 1) "hash1"
68 2) "sortedset1"
69 3) "list2"
View Code

4、redis的事务

1). 全部命令顺序执行,期间,Redis不会再为其它客户端的请求提供任何服务,从而保证了事物中的全部命令被原子的执行。
2). 和关系型数据库中的事务不一样的是,在Redis事务中若是有某一条命令执行失败,其后的命令仍然会被继续执行。
3). 咱们能够经过MULTI命令开启一个事务,有关系型数据库开发经验的人能够将其理解为"BEGIN TRANSACTION"语句。在该语句以后执行的命令都将被视为事务以内的操做,最后咱们能够经过执行EXEC/DISCARD命令来提交/回滚该事务内的全部操做。这两个Redis命令可被视为等同于关系型数据库中的COMMIT/ROLLBACK语句。

multi 用于标记事务的开始,其后执行的命令都将被存入命令队列,直到执行exec时,这些命令才会被原子的执行。 始终返回OK
exec 执行在一个事务内命令队列中的全部命令,同时将当前链接的状态恢复为正常状态,即非事务状态。若是在事务中执行了watch命令,那么只有当watch所监控的keys没有被修改的前提下,exec命令才能执行事务队列中的全部命令,不然exec将放弃当前事务中的全部命令。 原子性的返回事务中各条命令的返回结果。若是在事务中使用了watch,一旦事务被放弃,exec将返回NULL-multi-bulk回复。

 1 127.0.0.1:6379> multi
 2 OK
 3 127.0.0.1:6379> set k1 string
 4 QUEUED
 5 #因为k1为字符串类型,因此incr会报错,可是之后其余命令正常执行
 6 127.0.0.1:6379> incr k1
 7 QUEUED
 8 127.0.0.1:6379> set k1 newstring
 9 QUEUED
10 127.0.0.1:6379> get k1
11 QUEUED
12 127.0.0.1:6379> exec
13 1) OK
14 2) (error) ERR value is not an integer or out of range
15 3) OK
16 4) "newstring"
View Code

discard 回滚事务队列中的全部命令,同时再将当前链接的状态恢复为正常状态,即非事务状态。若是watch命令被使用,该命令将unwatch全部的Keys。
watch key [key ...] O(1) 在multi命令执行以前,能够指定待监控的keys,然而在执行exec以前,若是被监控的keys发生修改,exec将放弃执行该事务队列中的全部命令。
unwatch O(1) 取消当前事务中指定监控的keys,若是执行了exec或discard命令,则无需手工执行该命令,由于事务中全部被监控的keys都将自动取消。
 

 1 127.0.0.1:6379> set id 1
 2 OK
 3 127.0.0.1:6379> set name n1
 4 OK
 5 127.0.0.1:6379> set age 12
 6 OK
 7 127.0.0.1:6379> watch id
 8 OK
 9 127.0.0.1:6379> multi 
10 OK
11 127.0.0.1:6379> set name n2
12 QUEUED
13 127.0.0.1:6379> incr age
14 QUEUED
15 127.0.0.1:6379> exec
16 (nil)
17 127.0.0.1:6379> get age
18 "12"
19 127.0.0.1:6379> get name
20 "n1"
View Code

 注意,在提交事务以前,则执行exec命令以前,咱们在另外一个窗口对id进行修改(set id 2),能够看出,该事务没有执行成功

5、redis的主从复制

1). 同一个Master能够同步多个Slaves节点。

2). Slave一样能够接受其它Slaves的链接和同步请求。

3). Master Server是以非阻塞的方式为Slaves提供服务。因此在Master-Slave同步期间,客户端仍然能够提交查询或修改请求。

4). Slave Server一样是以非阻塞的方式完成数据同步。在同步期间,若是有客户端提交查询请求,Redis则返回同步以前的数据。

5). 为了分载Master的读操做压力,Slave服务器能够为客户端提供只读操做的服务,写服务仍然必须由Master来完成。从而实现读写分离

在Slave启动并链接到Master以后,它将主动发送一个SYNC命令。此后Master将启动后台存盘进程,同时收集全部接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次彻底同步。而Slave服务器在接收到数据库文件数据以后将其存盘并加载到内存中。此后,Master继续将全部已经收集到的修改命令,和新的修改命令依次传送给Slaves,Slave将在本次执行这些数据修改命令,从而达到最终的数据同步。若Master和Slave之间的连接出现断连现象,Slave能够自动重连Master,可是在链接成功以后,一次彻底同步将被自动执行。 

同时启动两个Redis服务器,能够考虑在同一台机器上启动两个Redis服务器,分别监听不一样的端口,如6379和6380。复制redis.conf并命名为slave.conf,编辑该配置文件,在84行位置将其中监听的端口改成6380:配置以下port 6380,分配启动两个server,启动时能够将配置文件做为启动命令的参数。命令以下:redis-server redis.conf ,当咱们把两个server都启动时,能够进行如下步骤:

1 redis-cli -p 6380
View Code

经过不一样的端口来连接服务端,此时,当前客户端连接的6380端口的服务端,咱们让这个服务端当作slave节点的角色。执行以下命令

slaveof 127.0.0.1 6379
View Code

当返回ok时,这里我Master-Slave创建成功。在监听端口为6379的服务器上咱们用客户端进行操做

1 [root@hbase redis-3.2.5]# src/redis-cli -p 6379
2 127.0.0.1:6379> set k1 v1
3 OK
4 127.0.0.1:6379> hset k2 f2 v2
5 (integer) 1
6 127.0.0.1:6379> 
View Code

在slave节点,获取该值:

1 [root@hbase redis-3.2.5]# src/redis-cli -p 6380
2 127.0.0.1:6380> slaveof 127.0.0.1 6379
3 OK
4 127.0.0.1:6380> keys *
5 1) "k1"
6 2) "k2"
7 127.0.0.1:6380> get k1
8 "v1"
View Code

说明两个节点主从已经同步。实现了主从同步的效果。须要注意的是:上面的方式只是保证了在执行slaveof命令以后,redis_6380成为了redis_6379的slave,一旦服务(redis_6380)从新启动以后,他们之间的复制关系将终止。若是但愿长期保证这两个服务器之间的Replication关系,能够在redis_6380的配置文件中作以下修改:

# slaveof <masterip> <masterport>改成slaveof 127.0.0.1 6379

保存退出。这样就能够保证Redis_6380服务程序在每次启动后都会主动创建与Redis_6379的Replication链接了。

6、redis的持久化 

6.一、Redis提供的持久化机制: 

1). RDB持久化:该机制是指在指定的时间间隔内将内存中的数据集快照写入磁盘。 

2). AOF持久化:该机制将以日志的形式记录服务器所处理的每个写操做,在Redis服务器启动之初会读取该文件来从新构建数据库,以保证启动后数据库中的数据是完整的。

6.二、RDB机制的优点和劣势:

优点:
1). 采用该方式,整个Redis数据库将只包含一个文件,经过这样的备份策略,一旦系统出现灾难性故障,咱们能够很是容易的进行恢复。
2). 性能最大化,对于Redis的服务进程而言,在开始持久化时,它惟一须要作的只是fork出子进程,再由子进程完成这些持久化的工做,这样能够极避免服务进程执行IO操做。
劣势:

1). 若是你想保证数据的高可用性,那么RDB将不是一个很好的选择。由于系统一旦在定时持久化以前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。

2). 因为RDB是经过fork子进程来协助完成数据持久化工做的,所以,若是当数据集较大时,可能会致使整个服务器中止服务必定的时间。

6.三、AOF机制的优点和劣势: 

优点
1). 带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不一样步。事实上,每秒同步也是异步完成的,其效率也是很是高的,所差的是一旦系统出现宕机现象,那么这一秒钟以内修改的数据将会丢失。而每修改同步,咱们能够将其视为同步持久化,即每次发生的数据变化都会被当即记录到磁盘中。能够预见,这种方式在效率上是最低的。

2). 因为该机制对日志文件的写入操做采用的是append模式,所以在写入过程当中即便出现宕机现象,也不会破坏日志文件中已经存在的内容。然而若是咱们本次操做只是写入了一半数据就出现了系统崩溃问题,在Redis下一次启动以前,能够经过redis-check-aof工具来解决数据一致性的问题。

3). 若是日志过大,Redis能够自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会建立一个新的文件用于记录此期间有哪些修改命令被执行。所以在进行rewrite切换时能够更好的保证数据安全性。

4). AOF包含一个格式清晰、易于理解的日志文件用于记录全部的修改操做。事实上,咱们也能够经过该文件完成数据的重建。
劣势
1). 对于相同数量的数据集而言,AOF文件一般要大于RDB文件。
2). 根据同步策略的不一样,AOF在运行效率上每每会慢于RDB。

介绍完理论以后,咱们配置redis的持久化方案:

rdb方案,在redis.conf中以下配置(默认配置) 

1 save 900 1              #在900秒(15分钟)以后,若是至少有1个key发生变化,则dump内存快照。
2 save 300 10            #在300秒(5分钟)以后,若是至少有10个key发生变化,则dump内存快照。
3 save 60 10000        #在60秒(1分钟)以后,若是至少有10000个key发生变化,则dump内存快照。
View Code

aof方案的配置:

1 在Redis的配置文件中存在三种同步方式,它们分别是:
2 appendfsync always     #每次有数据修改发生时都会写入AOF文件。
3 appendfsync everysec  #每秒钟同步一次,该策略为AOF的缺省策略。
4 appendfsync no          #从不一样步。高效可是数据不会被持久化。
View Code

7、redis的分片

分片(partitioning)就是将你的数据拆分到多个 Redis 实例的过程,Redis 引入另外一种哈希槽(hash slot)的概念。Redis 集群中内置了 16384 个哈希槽,当须要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法得出结果,而后对 16384 求余数,这样每一个 key 对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大体均等的将哈希槽映射到不一样节点。

原来的redis分片实现:

客户端分片(Client side partitioning),客户端直接选择正确的节点来写入和读取指定键。

代理协助分片(Proxy assisted partitioning),客户端发送请求到一个能够理解 Redis 协议的代理上,而不是直接发送请求到 Redis 实例上。代理会根据配置好的分片模式,来保证转发请求到正确的 Redis 实例,并返回响应给客户端。

查询路由(Query routing),发送查询到一个随机实例,这个实例会保证转发查询到正确的节点。 

新版本Redis的解决办法:

Redis3.0版的一大特性就是支持集群(Cluster)功能。Redis集群是自动分片和高可用的首选方式。集群的特色在于拥有和单机实例一样的功能,同时在网络分区后可以提供必定的可访问性以及对主数据库故障恢复的支持。

======================= 如下概念摘自网络===================

集群节点属性: 

每一个节点在集群中都有一个独一无二的 ID , 该 ID 是一个十六进制表示的 160 位随机数, 在节点第一次启动时由 /dev/urandom 生成。节点会将它的 ID 保存到配置文件, 只要这个配置文件不被删除, 节点就会一直沿用这个 ID 。节点 ID 用于标识集群中的每一个节点。 一个节点能够改变它的 IP 和端口号, 而不改变节点 ID 。 集群能够自动识别出 IP/端口号的变化, 并将这一信息经过 Gossip 协议广播给其余节点知道。

节点握手:

节点老是应答(accept)来自集群链接端口的链接请求, 并对接收到的 PING 数据包进行回复, 即便这个 PING 数据包来自不可信的节点。然而, 除了 PING 以外, 节点会拒绝其余全部并不是来自集群节点的数据包。要让一个节点认可另外一个节点同属于一个集群, 只有如下两种方法:

一、一个节点能够经过向另外一个节点发送 MEET 信息, 来强制让接收信息的节点认可发送信息的节点为集群中的一份子。 一个节点仅在管理员显式地向它发送CLUSTER MEET ip port 命令时, 才会向另外一个节点发送 MEET 信息。

二、若是一个可信节点向另外一个节点传播第三者节点的信息, 那么接收信息的那个节点也会将第三者节点识别为集群中的一份子。 也便是说, 若是 A 认识 B , B 认识 C , 而且 B 向 A 传播关于 C 的信息, 那么 A 也会将 C 识别为集群中的一份子, 并尝试链接 C 。

这意味着若是咱们将一个/一些新节点添加到一个集群中, 那么这个/这些新节点最终会和集群中已有的其余全部节点链接起来。这说明只要管理员使用 CLUSTER MEET 命令显式地指定了可信关系, 集群就能够自动发现其余节点。这种节点识别机制经过防止不一样的 Redis 集群由于 IP 地址变动或者其余网络事件的发生而产生意料以外的联合(mix), 从而使得集群更具健壮性。当节点的网络链接断开时, 它会主动链接其余已知的节点。

MOVED 转向:

一个 Redis 客户端能够向集群中的任意节点(包括从节点)发送命令请求。 节点会对命令请求进行分析, 若是该命令是集群能够执行的命令, 那么节点会查找这个命令所要处理的键所在的槽。若是要查找的哈希槽正好就由接收到命令的节点负责处理, 那么节点就直接执行这个命令。若是所查找的槽不是由该节点处理的话, 节点将查看自身内部所保存的哈希槽到节点 ID 的映射记录, 并向客户端回复一个 MOVED 错误。为了让客户端的转向操做尽量地简单, 节点在 MOVED 错误中直接返回目标节点的 IP 和端口号, 而不是目标节点的 ID 。客户端应该记录(memorize)下“槽 3999 由节点 127.0.0.1:6381 负责处理“这一信息, 这样当再次有命令须要对槽 3999 执行时, 客户端就能够加快寻找正确节点的速度。当集群处于稳定状态时, 全部客户端最终都会保存有一个哈希槽至节点的映射记录(map of hash slots to nodes), 使得集群很是高效: 客户端能够直接向正确的节点发送命令请求, 无须转向、代理或者其余任何可能发生单点故障(single point failure)的实体(entiy)。除了 MOVED 转向错误以外, 一个客户端还应该能够处理稍后介绍的 ASK 转向错误。

集群在线重配置:

Redis 集群支持在集群运行的过程当中添加或者移除节点。实际上, 节点的添加操做和节点的删除操做能够抽象成同一个操做, 那就是, 将哈希槽从一个节点移动到另外一个节点。所以, 实现 Redis 集群在线重配置的核心就是将槽从一个节点移动到另外一个节点的能力。 由于一个哈希槽实际上就是一些键的集合, 因此 Redis 集群在重哈希(rehash)时真正要作的, 就是将一些键从一个节点移动到另外一个节点。要理解 Redis 集群如何将槽从一个节点移动到另外一个节点, 咱们须要对 CLUSTER 命令的各个子命令进行介绍, 这些命理负责管理集群节点的槽转换表(slots translation table)。如下是 CLUSTER 命令可用的子命令:

CLUSTER ADDSLOTS slot1 [slot2] ... [slotN]

CLUSTER DELSLOTS slot1 [slot2] ... [slotN]

CLUSTER SETSLOT slot NODE node

CLUSTER SETSLOT slot MIGRATING node

CLUSTER SETSLOT slot IMPORTING node

最开头的两条命令 ADDSLOTS 和 DELSLOTS 分别用于向节点指派(assign)或者移除节点, 当槽被指派或者移除以后, 节点会将这一信息经过 Gossip 协议传播到整个集群。 ADDSLOTS 命令一般在新建立集群时, 做为一种快速地将各个槽指派给各个节点的手段来使用。CLUSTER SETSLOT slot NODE node 子命令能够将指定的槽 slot 指派给节点 node 。至于 CLUSTER SETSLOT slot MIGRATING node 命令和 CLUSTER SETSLOT slot IMPORTING node 命令, 前者用于将给定节点 node 中的槽 slot 迁移出节点, 然后者用于将给定槽 slot导入到节点 node :当一个槽被设置为 MIGRATING 状态时, 原来持有这个槽的节点仍然会继续接受关于这个槽的命令请求, 但只有命令所处理的键仍然存在于节点时, 节点才会处理这个命令请求。若是命令所使用的键不存在与该节点, 那么节点将向客户端返回一个 -ASK 转向(redirection)错误, 告知客户端, 要将命令请求发送到槽的迁移目标节点。当一个槽被设置为 IMPORTING 状态时, 节点仅在接收到 ASKING 命令以后, 才会接受关于这个槽的命令请求。若是客户端没有向节点发送 ASKING 命令, 那么节点会使用 -MOVED 转向错误将命令请求转向至真正负责处理这个槽的节点。上面关于 MIGRATING 和 IMPORTING 的说明有些难懂, 让咱们用一个实际的实例来讲明一下。假设如今, 咱们有 A 和 B 两个节点, 而且咱们想将槽 8 从节点 A 移动到节点 B , 因而咱们:向节点 B 发送命令 CLUSTER SETSLOT 8 IMPORTING A,向节点 A 发送命令 CLUSTER SETSLOT 8 MIGRATING B,每当客户端向其余节点发送关于哈希槽 8 的命令请求时, 这些节点都会向客户端返回指向节点 A 的转向信息:若是命令要处理的键已经存在于槽 8 里面, 那么这个命令将由节点 A 处理。若是命令要处理的键未存在于槽 8 里面(好比说,要向槽添加一个新的键), 那么这个命令由节点 B 处理。这种机制将使得节点 A 再也不建立关于槽 8 的任何新键。与此同时, 一个特殊的客户端 redis-trib 以及 Redis 集群配置程序(configuration utility)会将节点 A 中槽 8 里面的键移动到节点 B 。

键的移动操做由如下两个命令执行:

CLUSTER GETKEYSINSLOT slot count

上面的命令会让节点返回 count 个 slot 槽中的键, 对于命令所返回的每一个键, redis-trib 都会向节点 A 发送一条 MIGRATE 命令, 该命令会将所指定的键原子地(atomic)从节点 A 移动到节点 B (在移动键期间,两个节点都会处于阻塞状态,以避免出现竞争条件)。

如下为 MIGRATE 命令的运做原理:

MIGRATE target_host target_port key target_database id timeout执行 MIGRATE 命令的节点会链接到 target 节点, 并将序列化后的 key 数据发送给 target , 一旦 target 返回 OK , 节点就将本身的 key 从数据库中删除。从一个外部客户端的视角来看, 在某个时间点上, 键 key 要么存在于节点 A , 要么存在于节点 B , 但不会同时存在于节点 A 和节点 B 。由于 Redis 集群只使用 0 号数据库, 因此当 MIGRATE 命令被用于执行集群操做时, target_database 的值老是 0 。target_database 参数的存在是为了让 MIGRATE 命令成为一个通用命令, 从而能够做用于集群之外的其余功能。咱们对 MIGRATE 命令作了优化, 使得它即便在传输包含多个元素的列表键这样的复杂数据时, 也能够保持高效。不过, 尽管 MIGRATE 很是高效, 对一个键很是多、而且键的数据量很是大的集群来讲, 集群重配置仍是会占用大量的时间, 可能会致使集群没办法适应那些对于响应时间有严格要求的应用程序。

ASK 转向:

在以前介绍 MOVED 转向的时候, 咱们说除了 MOVED 转向以外, 还有另外一种 ASK 转向。当节点须要让一个客户端长期地(permanently)将针对某个槽的命令请求发送至另外一个节点时, 节点向客户端返回 MOVED 转向。另外一方面, 当节点须要让客户端仅仅在下一个命令请求中转向至另外一个节点时, 节点向客户端返回 ASK 转向。好比说, 在咱们上一节列举的槽 8 的例子中, 由于槽 8 所包含的各个键分散在节点 A 和节点 B 中, 因此当客户端在节点 A 中没找到某个键时, 它应该转向到节点 B 中去寻找, 可是这种转向应该仅仅影响一次命令查询, 而不是让客户端每次都直接去查找节点 B : 在节点 A 所持有的属于槽 8 的键没有所有被迁移到节点 B 以前, 客户端应该先访问节点 A , 而后再访问节点 B 。由于这种转向只针对 16384 个槽中的其中一个槽, 因此转向对集群形成的性能损耗属于可接受的范围。由于上述缘由, 若是咱们要在查找节点 A 以后, 继续查找节点 B , 那么客户端在向节点 B 发送命令请求以前, 应该先发送一个 ASKING 命令, 不然这个针对带有IMPORTING 状态的槽的命令请求将被节点 B 拒绝执行。接收到客户端 ASKING 命令的节点将为客户端设置一个一次性的标志(flag), 使得客户端能够执行一次针对 IMPORTING 状态的槽的命令请求。从客户端的角度来看, ASK 转向的完整语义(semantics)以下:

一、若是客户端接收到 ASK 转向, 那么将命令请求的发送对象调整为转向所指定的节点。

二、先发送一个 ASKING 命令,而后再发送真正的命令请求。

三、没必要更新客户端所记录的槽 8 至节点的映射: 槽 8 应该仍然映射到节点 A , 而不是节点 B 。

一旦节点 A 针对槽 8 的迁移工做完成, 节点 A 在再次收到针对槽 8 的命令请求时, 就会向客户端返回 MOVED 转向, 将关于槽 8 的命令请求长期地转向到节点 B 。注意, 即便客户端出现 Bug , 过早地将槽 8 映射到了节点 B 上面, 但只要这个客户端不发送 ASKING 命令, 客户端发送命令请求的时候就会赶上 MOVED 错误, 并将它转向回节点 A 。

 
容错:

节点失效检测,如下是节点失效检查的实现方法:

一、当一个节点向另外一个节点发送 PING 命令, 可是目标节点未能在给定的时限内返回 PING 命令的回复时, 那么发送命令的节点会将目标节点标记为 PFAIL(possible failure,可能已失效)。等待 PING 命令回复的时限称为“节点超时时限(node timeout)”, 是一个节点选项(node-wise setting)。

二、每次当节点对其余节点发送 PING 命令的时候, 它都会随机地广播三个它所知道的节点的信息, 这些信息里面的其中一项就是说明节点是否已经被标记为 PFAIL或者 FAIL 。当节点接收到其余节点发来的信息时, 它会记下那些被其余节点标记为失效的节点。 这称为失效报告(failure report)。

三、若是节点已经将某个节点标记为 PFAIL , 而且根据节点所收到的失效报告显式, 集群中的大部分其余主节点也认为那个节点进入了失效状态, 那么节点会将那个失效节点的状态标记为 FAIL 。

四、一旦某个节点被标记为 FAIL , 关于这个节点已失效的信息就会被广播到整个集群, 全部接收到这条信息的节点都会将失效节点标记为 FAIL 。

简单来讲, 一个节点要将另外一个节点标记为失效, 必须先询问其余节点的意见, 而且获得大部分主节点的赞成才行。由于过时的失效报告会被移除, 因此主节点要将某个节点标记为 FAIL 的话, 必须以最近接收到的失效报告做为根据。

从节点选举:一旦某个主节点进入 FAIL 状态, 若是这个主节点有一个或多个从节点存在, 那么其中一个从节点会被升级为新的主节点, 而其余从节点则会开始对这个新的主节点进行复制。新的主节点由已下线主节点属下的全部从节点中自行选举产生, 如下是选举的条件:

一、这个节点是已下线主节点的从节点。

二、已下线主节点负责处理的槽数量非空。

三、从节点的数据被认为是可靠的, 也便是, 主从节点之间的复制链接(replication link)的断线时长不能超过节点超时时限(node timeout)乘以REDIS_CLUSTER_SLAVE_VALIDITY_MULT 常量得出的积。

若是一个从节点知足了以上的全部条件, 那么这个从节点将向集群中的其余主节点发送受权请求, 询问它们, 是否容许本身(从节点)升级为新的主节点。若是发送受权请求的从节点知足如下属性, 那么主节点将向从节点返FAILOVER_AUTH_GRANTED 受权, 赞成从节点的升级要求:

一、发送受权请求的是一个从节点, 而且它所属的主节点处于 FAIL 状态。

二、在已下线主节点的全部从节点中, 这个从节点的节点 ID 在排序中是最小的。

三、这个从节点处于正常的运行状态: 它没有被标记为 FAIL 状态, 也没有被标记为 PFAIL 状态。

一旦某个从节点在给定的时限内获得大部分主节点的受权, 它就会开始执行如下故障转移操做:

一、经过 PONG 数据包(packet)告知其余节点, 这个节点如今是主节点了。

二、经过 PONG 数据包告知其余节点, 这个节点是一个已升级的从节点(promoted slave)。

三、接管(claiming)全部由已下线主节点负责处理的哈希槽。

四、显式地向全部节点广播一个 PONG 数据包, 加速其余节点识别这个节点的进度, 而不是等待定时的 PING / PONG 数据包。

全部其余节点都会根据新的主节点对配置进行相应的更新:

一、全部被新的主节点接管的槽会被更新。

二、已下线主节点的全部从节点会察觉到 PROMOTED 标志, 并开始对新的主节点进行复制。

三、若是已下线的主节点从新回到上线状态, 那么它会察觉到 PROMOTED 标志, 并将自身调整为现任主节点的从节点。

在集群的生命周期中, 若是一个带有 PROMOTED 标识的主节点由于某些缘由转变成了从节点, 那么该节点将丢失它所带有的 PROMOTED 标识 

======================= 以上概念摘自网络===================

 搭建redis集群环境须要执行的ruby的脚本,因此须要安装ruby的环境。建议用yum进行安装,因为具体的操做环境不相同,因此具体操做过程还需视操做环境而定 

1 [root@root java]# yum install ruby
2 [root@root java]# yum install rubygems
3 [root@root java]# gem install redis
View Code

期间会出现选择选项,键入yes便可。当出现Successfully installed redis-3.3.1  1 gem installed,说明redis集群须要的ruby环境安装成功。开始搭建redis环境

建立redis-cluster文件夹,并在其中建立6379,6380,6381文件夹,修改redis.conf文件,并将其中的端口分别设置成6379,6380,6381,redis.conf中的其余配置为

daemonize yes

cluster-enabled yes

cluster-config-file nodes.conf

cluster-node-timeout 5000

appendonly yes

结构目录以下:

 1 [root@storm1 java]# cd redis-cluster/
 2 [root@storm1 redis-cluster]# ll
 3 total 12
 4 drwxr-xr-x. 2 root root 4096 Nov 14 05:50 6379
 5 drwxr-xr-x. 2 root root 4096 Nov 14 05:51 6380
 6 drwxr-xr-x. 2 root root 4096 Nov 14 05:52 6381
 7 [root@storm1 redis-cluster]# cd 6379
 8 [root@storm1 6379]# cat redis.conf 
 9 port 6379
10 daemonize yes
11 cluster-enabled yes
12 cluster-config-file nodes.conf
13 cluster-node-timeout 5000
14 appendonly yes[root@storm1 6379]# more ../6380/redis.conf 
15 port 6380
16 daemonize yes
17 cluster-enabled yes
18 cluster-config-file nodes.conf
19 cluster-node-timeout 5000
20 appendonly yes
21 [root@storm1 6379]# 
View Code

分别启动这3个redis实例,并建立集群,让三个实例互相通信:

 1 [root@storm1 redis-3.2.5]# src/redis-trib.rb create --replicas 0 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381
 2 >>> Creating cluster
 3 >>> Performing hash slots allocation on 3 nodes...
 4 Using 3 masters:
 5 127.0.0.1:6379
 6 127.0.0.1:6380
 7 127.0.0.1:6381
 8 M: 76d37cdb954e0c293cec5c6bc27015af40d4a59f 127.0.0.1:6379
 9    slots:0-5460 (5461 slots) master
10 M: f18ab812b7f9e933639b3afdab964039ddd3ceba 127.0.0.1:6380
11    slots:5461-10922 (5462 slots) master
12 M: 644f9bca1af9cc9e3f1543ab5f0b434d11ff59b0 127.0.0.1:6381
13    slots:10923-16383 (5461 slots) master
14 Can I set the above configuration? (type 'yes' to accept): yes
15 >>> Nodes configuration updated
16 >>> Assign a different config epoch to each node
17 >>> Sending CLUSTER MEET messages to join the cluster
18 Waiting for the cluster to join....
19 >>> Performing Cluster Check (using node 127.0.0.1:6379)
20 M: 76d37cdb954e0c293cec5c6bc27015af40d4a59f 127.0.0.1:6379
21    slots:0-5460 (5461 slots) master
22    0 additional replica(s)
23 M: 644f9bca1af9cc9e3f1543ab5f0b434d11ff59b0 127.0.0.1:6381
24    slots:10923-16383 (5461 slots) master
25    0 additional replica(s)
26 M: f18ab812b7f9e933639b3afdab964039ddd3ceba 127.0.0.1:6380
27    slots:5461-10922 (5462 slots) master
28    0 additional replica(s)
29 [OK] All nodes agree about slots configuration.
30 >>> Check for open slots...
31 >>> Check slots coverage...
32 [OK] All 16384 slots covered.
View Code

至此redis集群即搭建成功,简单进行测试一下

1 [root@storm1 redis-3.2.5]# src/redis-cli -c -p 6379
2 127.0.0.1:6379> set k1 v1
3 -> Redirected to slot [12706] located at 127.0.0.1:6381
4 OK
5 127.0.0.1:6381> exit
6 [root@storm1 redis-3.2.5]# src/redis-cli -c -p 6381
7 127.0.0.1:6381> keys *
8 1) "k1"
9 127.0.0.1:6381> 
View Code

能够看到,虽然咱们第一次链接的是6379端口,redis cluster 自动帮咱们重定向到 6381 。在6381端口的实例中出现了咱们以前设置的k1,说明整个集群是工做的。

8、redis的管理命令

config get parameter 用于读取服务器的运行时参数,可是并非全部的配置参数均可以经过该命令进行读取。该命令的参数接受glob风格的模式匹配规则,所以若是参数中包含模式元字符,那么全部匹配的参数都将以key/value方式被列出。若是参数是*,那么该命令支持的全部参数都将被列出。

config set parameter value 该命令用于配置Redis服务器的运行时参数,在设置成功以后无需重启即可生效。然而并不是全部的参数均可以经过该命令进行动态设置。
dbsize 返回当前打开的数据库中keys的数量。
flushall  清空当前服务器管理的数据库中的全部keys,不只限于当前打开的数据库。
flushdb  清空当前数据库中的全部keys。
info  获取和服务器运行情况相关的一些列统计数字。
save 设置RDB持久化模式的保存策略。
shutdown  中止全部的客户端,同时以阻塞的方式执行内存数据持久化。若是AOF模式被启用,则将缓存中的数据flush到AOF文件。退出服务器。
slaveof host port 该命令用于修改slave服务器的主从复制设置。
slowlog subcommand [argument] 该命令主要用于读取执行时间较长的命令。因为slowlog队列不会被持久化到磁盘,所以Redis在收集命令时不会对性能产生很大的影响。一般咱们能够将参数"slowlog-log-slower-than"设置为0,以便收集全部命令的执行时间。该命令还包含如下几个子命令:
1). slowlog get N: 从slowlog队列中读取命令信息,N表示最近N条命令的信息。
2). slowlog len:获取slowlog队列的长度。
3). slowlog reset:清空slowlog中的内容。

 1 redis 127.0.0.1:6379> config get port
 2 1) "port"
 3 2) "6379"
 4 redis 127.0.0.1:6379> keys *
 5 1) "k1"
 6 redis 127.0.0.1:6379> flushdb
 7 OK
 8 redis 127.0.0.1:6379> keys *
 9 (empty list or set)
10 redis 127.0.0.1:6379> dbsize
11 (integer) 0
12 redis 127.0.0.1:6379> set k1 v1
13 OK
14 redis 127.0.0.1:6379> dbsize
15 (integer) 1
View Code

9、redis的java操做

maven依赖 

1 <dependency>
2     <groupId>redis.clients</groupId>
3     <artifactId>jedis</artifactId>
4     <version>2.6.2</version>
5     <type>jar</type>
6     <scope>compile</scope>
7 </dependency>
View Code

 java代码:

 1 import redis.clients.jedis.Jedis;
 2 
 3 public class RedisDao {
 4 
 5     public static void main(String[] args) {
 6         Jedis jedis = new Jedis("127.0.0.1", 6379);
 7         jedis.set("k2", "v2");
 8         System.out.println(jedis.get("k2"));
 9         jedis.hset("k3", "f1", "v1");
10         System.out.println(jedis.hget("k3", "f1"));
11         System.out.println(jedis.keys("*"));
12         jedis.close();
13     }
14 }
View Code

10、redis与spring整合 

10.1 引入jedis包和spring包

10.2 spring-mvc.xml 

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 3     http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" default-autowire="byName">
 4 
 5     <bean id="redisClient" class="com.eztcn.commons.redis.RedisClientFactoryBean">
 6         <!-- 单个应用中的连接池最大连接数,默认8 -->
 7         <property name="maxTotal" value="150" />
 8         <!-- 单个应用中的连接池最大空闲数,默认8 -->
 9         <property name="maxIdle" value="50" />
10         <!-- 单个应用中的连接池最大连接数,默认8 -->
11         <property name="minIdle" value="30" />
12         <!-- 设置在每一次取对象时测试ping -->
13         <property name="testOnBorrow" value="false" />
14         <!-- host:port -->
15           <property name="ipConfString" value="192.168.1.60:7001" /> 
16     </bean>
17 </beans>
View Code

 固然须要在spring配置文件中引入该配置文件:<import resource="spring/spring-config-redis.xml" />

10.3 RedisClientFactoryBean.java 

 1 package com.commons.redis;
 2 
 3 import org.apache.commons.lang3.StringUtils;
 4 import org.springframework.beans.factory.FactoryBean;
 5 
 6 public class RedisClientFactoryBean implements FactoryBean<RedisClient> {
 7     private RedisClientConfig redisClientConfig = new RedisClientConfig();
 8 
 9     public RedisClient getObject() throws Exception {
10         if (StringUtils.isNotBlank(this.redisClientConfig.getIpConfString())) {
11             return new RedisClient(this.redisClientConfig);
12         }
13         throw new RedisInitializerException("RedisClient init parameter masterConfString is empty,please check spring config file!");
14     }
15 
16     public Class<?> getObjectType() {
17         return RedisClient.class;
18     }
19 
20     public boolean isSingleton() {
21         return true;
22     }
23 
24     public void setIpConfString(String string) {
25         this.redisClientConfig.setIpConfString(string);
26     }
27 
28     public void setMaxTotal(int maxTotal) {
29         this.redisClientConfig.setMaxTotal(maxTotal);
30     }
31 
32     public void setMaxIdle(int maxIdle) {
33         this.redisClientConfig.setMaxIdle(maxIdle);
34     }
35 
36     public void setMinIdle(int minIdle) {
37         this.redisClientConfig.setMinIdle(minIdle);
38     }
39 
40     public void setTestOnBorrow(boolean flag) {
41         this.redisClientConfig.setTestOnBorrow(flag);
42     }
43 }
View Code

10.4 RedisClientConfig.java

 1 package com.commons.redis;
 2 
 3 import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
 4 
 5 /**
 6  * 
 7  * @描述 : 配置redis的相关属性
 8  * @建立时间: 2015年7月20日上午11:05:53
 9  *
10  */
11 public class RedisClientConfig {
12     private GenericObjectPoolConfig jedisPoolConfig = new GenericObjectPoolConfig();
13     
14     private String ipConfString;
15 
16     /**
17      * 
18      * @描述 : 单个应用中的连接池最大连接数
19      * @建立时间: 2015年7月20日上午11:11:10
20      *
21      * @param maxTotal
22      */
23     public void setMaxTotal(int maxTotal) {
24         this.jedisPoolConfig.setMaxTotal(maxTotal);
25     }
26 
27     /**
28      * @描述 :单个应用中的连接池最大空闲数 
29      * @建立时间: 2015年7月20日上午11:11:28
30      *
31      * @param maxIdle
32      */
33     
34     
35     public void setMaxIdle(int maxIdle) {
36         this.jedisPoolConfig.setMaxIdle(maxIdle);
37     }
38 
39     
40     /**
41      * @描述 : 单个应用中的连接池最大连接数
42      * @建立时间: 2015年7月20日上午11:11:43
43      *
44      * @param maxIdle
45      */
46     public void setMinIdle(int minIdle) {
47         this.jedisPoolConfig.setMinIdle(minIdle);
48     }
49 
50     /**
51      * @描述 : 设置在每一次取对象时测试ping 
52      * @建立时间: 2015年7月20日上午11:11:58
53      *
54      * @param flag
55      */
56     public void setTestOnBorrow(boolean flag) {
57         this.jedisPoolConfig.setTestOnBorrow(flag);
58     }
59 
60     public GenericObjectPoolConfig getJedisPoolConfig() {
61         return this.jedisPoolConfig;
62     }
63 
64     public String getIpConfString() {
65         return this.ipConfString;
66     }
67 
68     public void setIpConfString(String ipConfString) {
69         this.ipConfString = ipConfString;
70     }
71 }
View Code

10.5 RedisClient.java

  1 package com.commons.redis;
  2 
  3 import java.util.List;
  4 import java.util.Map;
  5 import java.util.Set;
  6 
  7 import org.apache.commons.lang3.StringUtils;
  8 import org.apache.commons.logging.Log;
  9 import org.apache.commons.logging.LogFactory;
 10 
 11 import redis.clients.jedis.BinaryClient;
 12 import redis.clients.jedis.Jedis;
 13 import redis.clients.jedis.JedisPool;
 14 
 15 public class RedisClient {
 16     private static final Log LOG = LogFactory.getLog(RedisClient.class);
 17     private RedisClientConfig redisClientConfig;
 18     private JedisPool jedisPool;
 19 
 20     public RedisClient(RedisClientConfig redisClientConfig) {
 21         this.redisClientConfig = redisClientConfig;
 22         init();
 23     }
 24 
 25     /**
 26      * 
 27      * @描述 : 初始化,配置ip和端口
 28      * @建立时间: 2015年7月20日下午1:43:29
 29      *
 30      */
 31     private void init() {
 32         LOG.info("redis client init start~");
 33         String ip = "";
 34         int port;
 35         if (StringUtils.isNotBlank(this.redisClientConfig.getIpConfString())) {
 36             String[] ipPortArray = this.redisClientConfig.getIpConfString().split(":");
 37             if (ipPortArray.length == 1) {
 38                 throw new RedisInitializerException(ipPortArray + " is not include host:port or host:port after split \":\"");
 39             }
 40             ip = ipPortArray[0];
 41             port = Integer.valueOf(ipPortArray[1]).intValue();
 42         } else {
 43             throw new RuntimeException("init throw exception");
 44         }
 45         LOG.info("write redis client connect ip:" + ip + ",port:" + port);
 46         this.jedisPool = new JedisPool(this.redisClientConfig.getJedisPoolConfig(), ip, port);
 47     }
 48 
 49     /**
 50      * 
 51      * @描述 : 设置键值对
 52      * @建立时间: 2015年7月20日下午1:44:10
 53      *
 54      * @param key
 55      * @param value
 56      * @return
 57      * @throws RedisAccessException
 58      */
 59     public String set(String key, String value) throws RedisAccessException {
 60         Jedis client = null;
 61         try {
 62             client = jedisPool.getResource();
 63             return client.set(key, value);
 64         } catch (Exception e) {
 65             LOG.error(e.getMessage(), e);
 66             throw new RedisAccessException(e);
 67         } finally {
 68             if (null != client) {
 69                 jedisPool.returnResourceObject(client);
 70             }
 71         }
 72     }
 73 
 74     /**
 75      * 
 76      * @描述 : 将值 value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位)。若是 key 已经存在, SETEX
 77      *     命令将覆写旧值。
 78      * @建立时间: 2015年7月20日下午1:44:36
 79      *
 80      * @param key
 81      * @param seconds
 82      * @param value
 83      * @return
 84      * @throws RedisAccessException
 85      */
 86     public String set(String key, int seconds, String value) throws RedisAccessException {
 87         Jedis client = null;
 88         try {
 89             client = jedisPool.getResource();
 90             return client.setex(key, seconds, value);
 91         } catch (Exception e) {
 92             LOG.error(e.getMessage(), e);
 93             throw new RedisAccessException(e);
 94         } finally {
 95             if (null != client) {
 96                 jedisPool.returnResourceObject(client);
 97             }
 98         }
 99     }
100 
101     /**
102      * 
103      * @描述 : 若是 key 已经存在而且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。 若是 key 不存在,
104      *     APPEND 就简单地将给定 key 设为 value ,就像执行 SET key value 同样。
105      * @建立时间: 2015年7月20日下午1:45:55
106      *
107      * @param key
108      * @param value
109      * @return
110      * @throws RedisAccessException
111      */
112     public Long append(String key, String value) throws RedisAccessException {
113         Jedis client = null;
114         try {
115             client = jedisPool.getResource();
116             return client.append(key, value);
117         } catch (Exception e) {
118             LOG.error(e.getMessage(), e);
119             throw new RedisAccessException(e);
120         } finally {
121             if (null != client) {
122                 jedisPool.returnResourceObject(client);
123             }
124         }
125     }
126 
127     /**
128      * 
129      * @描述 : 返回 key 所关联的字符串值。若是 key 不存在那么返回特殊值 null 。 假如 key
130      *     储存的值不是字符串类型,返回一个错误,由于 GET 只能用于处理字符串值。
131      * @建立时间: 2015年7月20日下午1:47:10
132      *
133      * @param key
134      * @return
135      * @throws RedisAccessException
136      */
137     public String get(String key) throws RedisAccessException {
138         Jedis client = null;
139         try {
140             client = jedisPool.getResource();
141             return client.get(key);
142         } catch (Exception e) {
143             LOG.error(e.getMessage(), e);
144             throw new RedisAccessException(e);
145         } finally {
146             if (null != client) {
147                 jedisPool.returnResourceObject(client);
148             }
149         }
150     }
151 
152     /**
153      * 
154      * @描述 : 删除给定的一个或多个 key 。 不存在的 key 会被忽略。
155      * @建立时间: 2015年7月20日下午1:48:37
156      *
157      * @param key
158      * @return
159      * @throws RedisAccessException
160      */
161     public Long del(String key) throws RedisAccessException {
162         Jedis client = null;
163         try {
164             client = jedisPool.getResource();
165             return client.del(key);
166         } catch (Exception e) {
167             LOG.error(e.getMessage(), e);
168             throw new RedisAccessException(e);
169         } finally {
170             if (null != client) {
171                 jedisPool.returnResourceObject(client);
172             }
173         }
174     }
175 
176     /**
177      * 
178      * @描述 : 检查给定 key 是否存在。
179      * @建立时间: 2015年7月20日下午1:48:48
180      *
181      * @param key
182      * @return
183      * @throws RedisAccessException
184      */
185     public Boolean exists(String key) throws RedisAccessException {
186         Jedis client = null;
187         try {
188             client = jedisPool.getResource();
189             return client.exists(key);
190         } catch (Exception e) {
191             LOG.error(e.getMessage(), e);
192             throw new RedisAccessException(e);
193         } finally {
194             if (null != client) {
195                 jedisPool.returnResourceObject(client);
196             }
197         }
198     }
199 
200     /**
201      * @描述 : 为给定 key 设置生存时间,当 key 过时时(生存时间为 0 ),它会被自动删除。
202      * @建立时间: 2015年7月20日下午1:49:29
203      *
204      * @param key
205      * @param seconds
206      * @return
207      * @throws RedisAccessException
208      */
209     public Long expire(String key, int seconds) throws RedisAccessException {
210         Jedis client = null;
211         try {
212             client = jedisPool.getResource();
213             return client.expire(key, seconds);
214         } catch (Exception e) {
215             LOG.error(e.getMessage(), e);
216             throw new RedisAccessException(e);
217         } finally {
218             if (null != client) {
219                 jedisPool.returnResourceObject(client);
220             }
221         }
222     }
223     
224     
225     
226     /**
227      * @描述 : 为给定 key 设置生存时间,当 key 过时时(生存时间为 0 ),它会被自动删除。
228      * @建立时间: 2015年7月20日下午1:49:29
229      *
230      * @param key
231      * @param seconds
232      * @return
233      * @throws RedisAccessException
234      */
235     public Long expireAt(String key, long unixTime) throws RedisAccessException {
236         Jedis client = null;
237         try {
238             client = jedisPool.getResource();
239             return client.expireAt(key,unixTime);
240         } catch (Exception e) {
241             LOG.error(e.getMessage(), e);
242             throw new RedisAccessException(e);
243         } finally {
244             if (null != client) {
245                 jedisPool.returnResourceObject(client);
246             }
247         }
248     }
249 
250     /**
251      * 
252      * @描述 : 将给定 key 的值设为 value ,并返回 key 的旧值(old value)。当 key
253      *     存在但不是字符串类型时,返回一个错误。
254      * @建立时间: 2015年7月20日下午1:50:28
255      *
256      * @param key
257      * @param value
258      * @return
259      * @throws RedisAccessException
260      */
261     public String getSet(String key, String value) throws RedisAccessException {
262         Jedis client = null;
263         try {
264             client = jedisPool.getResource();
265             return client.getSet(key, value);
266         } catch (Exception e) {
267             LOG.error(e.getMessage(), e);
268             throw new RedisAccessException(e);
269         } finally {
270             if (null != client) {
271                 jedisPool.returnResourceObject(client);
272             }
273         }
274     }
275 
276     /**
277      * 
278      * @描述 : 将 key 的值设为 value ,当且仅当 key 不存在。若给定的 key 已经存在,则 SETNX 不作任何动做。
279      * @建立时间: 2015年7月20日下午1:52:07
280      *
281      * @param key
282      * @param value
283      * @return
284      * @throws RedisAccessException
285      */
286     public Long setnx(String key, String value) throws RedisAccessException {
287         Jedis client = null;
288         try {
289             client = jedisPool.getResource();
290             return client.setnx(key, value);
291         } catch (Exception e) {
292             LOG.error(e.getMessage(), e);
293             throw new RedisAccessException(e);
294         } finally {
295             if (null != client) {
296                 jedisPool.returnResourceObject(client);
297             }
298         }
299     }
300 
301     /**
302      * 
303      * @描述 : 将哈希表 key 中的域 field 的值设为 value 。 若是 key 不存在,一个新的哈希表被建立并进行 HSET操做。
304      *     若是域 field 已经存在于哈希表中,旧值将被覆盖。
305      * @建立时间: 2015年7月20日下午1:53:23
306      *
307      * @param key
308      * @param field
309      * @param value
310      * @return
311      * @throws RedisAccessException
312      */
313     public Long hset(String key, String field, String value) throws RedisAccessException {
314         Jedis client = null;
315         try {
316             client = jedisPool.getResource();
317             return client.hset(key, field, value);
318         } catch (Exception e) {
319             LOG.error(e.getMessage(), e);
320             throw new RedisAccessException(e);
321         } finally {
322             if (null != client) {
323                 jedisPool.returnResourceObject(client);
324             }
325         }
326     }
327 
328     /**
329      * 
330      * @描述 :返回哈希表 key 中给定域 field 的值。
331      * @建立时间: 2015年7月20日下午1:54:24
332      *
333      * @param key
334      * @param field
335      * @return
336      * @throws RedisAccessException
337      */
338     public String hget(String key, String field) throws RedisAccessException {
339         Jedis client = null;
340         try {
341             client = jedisPool.getResource();
342             return client.hget(key, field);
343         } catch (Exception e) {
344             LOG.error(e.getMessage(), e);
345             throw new RedisAccessException(e);
346         } finally {
347             if (null != client) {
348                 jedisPool.returnResourceObject(client);
349             }
350         }
351     }
352 
353     /**
354      * 
355      * @描述 : 将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在。若域 field
356      *     已经存在,该操做无效。 若是 key 不存在,一个新哈希表被建立并执行 HSETNX 命令。
357      * @建立时间: 2015年7月20日下午1:54:44
358      *
359      * @param key
360      * @param field
361      * @param value
362      * @return
363      * @throws RedisAccessException
364      */
365     public Long hsetnx(String key, String field, String value) throws RedisAccessException {
366         Jedis client = null;
367         try {
368             client = jedisPool.getResource();
369             return client.hsetnx(key, field, value);
370         } catch (Exception e) {
371             LOG.error(e.getMessage(), e);
372             throw new RedisAccessException(e);
373         } finally {
374             if (null != client) {
375                 jedisPool.returnResourceObject(client);
376             }
377         }
378     }
379 
380     /**
381      * 
382      * @描述 :同时将多个 field-value (域-值)对设置到哈希表 key 中。此命令会覆盖哈希表中已存在的域。 若是 key
383      *     不存在,一个空哈希表被建立并执行 HMSET 操做。
384      * @建立时间: 2015年7月20日下午1:58:26
385      *
386      * @param key
387      * @param hash
388      * @return
389      * @throws RedisAccessException
390      */
391     public String hmset(String key, Map<String, String> hash) throws RedisAccessException {
392         Jedis client = null;
393         try {
394             client = jedisPool.getResource();
395             return client.hmset(key, hash);
396         } catch (Exception e) {
397             LOG.error(e.getMessage(), e);
398             throw new RedisAccessException(e);
399         } finally {
400             if (null != client) {
401                 jedisPool.returnResourceObject(client);
402             }
403         }
404     }
405 
406     /**
407      * 
408      * @描述 : 返回哈希表 key 中,一个或多个给定域的值。若是给定的域不存在于哈希表,那么返回一个 null 值。 由于不存在的 key
409      *     被看成一个空哈希表来处理,因此对一个不存在的 key 进行 HMGET 操做将返回一个只带有 null 值的表。
410      * @建立时间: 2015年7月20日下午1:57:32
411      *
412      * @param key
413      * @param fields
414      * @return
415      * @throws RedisAccessException
416      */
417     public List<String> hmget(String key, String[] fields) throws RedisAccessException {
418         Jedis client = null;
419         try {
420             client = jedisPool.getResource();
421             return client.hmget(key, fields);
422         } catch (Exception e) {
423             LOG.error(e.getMessage(), e);
424             throw new RedisAccessException(e);
425         } finally {
426             if (null != client) {
427                 jedisPool.returnResourceObject(client);
428             }
429         }
430     }
431 
432     /**
433      * 
434      * @描述 :删除哈希表 key 中的一个或多个指定域,不存在的域将被忽略。
435      * @建立时间: 2015年7月20日下午1:59:32
436      *
437      * @param key
438      * @param fields
439      * @return
440      * @throws RedisAccessException
441      */
442     public Long hdel(String key, String[] fields) throws RedisAccessException {
443         Jedis client = null;
444         try {
445             client = jedisPool.getResource();
446             return client.hdel(key, fields);
447         } catch (Exception e) {
448             LOG.error(e.getMessage(), e);
449             throw new RedisAccessException(e);
450         } finally {
451             if (null != client) {
452                 jedisPool.returnResourceObject(client);
453             }
454         }
455     }
456 
457     /**
458      * 
459      * @描述 : 返回哈希表 key 中域的数量。
460      * @建立时间: 2015年7月20日下午2:00:13
461      *
462      * @param key
463      * @return
464      * @throws RedisAccessException
465      */
466     public Long hlen(String key) throws RedisAccessException {
467         Jedis client = null;
468         try {
469             client = jedisPool.getResource();
470             return client.hlen(key);
471         } catch (Exception e) {
472             LOG.error(e.getMessage(), e);
473             throw new RedisAccessException(e);
474         } finally {
475             if (null != client) {
476                 jedisPool.returnResourceObject(client);
477             }
478         }
479     }
480 
481     /**
482      * 
483      * @描述 :返回哈希表 key 中的全部域。
484      * @建立时间: 2015年7月20日下午2:00:59
485      *
486      * @param key
487      * @return
488      * @throws RedisAccessException
489      */
490     public Set<String> hkeys(String key) throws RedisAccessException {
491         Jedis client = null;
492         try {
493             client = jedisPool.getResource();
494             return client.hkeys(key);
495         } catch (Exception e) {
496             LOG.error(e.getMessage(), e);
497             throw new RedisAccessException(e);
498         } finally {
499             if (null != client) {
500                 jedisPool.returnResourceObject(client);
501             }
502         }
503     }
504 
505     /**
506      * 
507      * @描述 : 返回哈希表 key 中全部域的值。
508      * @建立时间: 2015年7月20日下午2:01:06
509      *
510      * @param key
511      * @return
512      * @throws RedisAccessException
513      */
514     public List<String> hvals(String key) throws RedisAccessException {
515         Jedis client = null;
516         try {
517             client = jedisPool.getResource();
518             return client.hvals(key);
519         } catch (Exception e) {
520             LOG.error(e.getMessage(), e);
521             throw new RedisAccessException(e);
522         } finally {
523             if (null != client) {
524                 jedisPool.returnResourceObject(client);
525             }
526         }
527     }
528 
529     /**
530      * 
531      * @描述 : 返回哈希表 key 中,全部的域和值。在返回值里,紧跟每一个域名(field
532      *     name)以后是域的值(value),因此返回值的长度是哈希表大小的两倍。
533      * @建立时间: 2015年7月20日下午2:01:36
534      *
535      * @param key
536      * @return
537      * @throws RedisAccessException
538      */
539     public Map<String, String> hgetAll(String key) throws RedisAccessException {
540         Jedis client = null;
541         try {
542             client = jedisPool.getResource();
543             return client.hgetAll(key);
544         } catch (Exception e) {
545             LOG.error(e.getMessage(), e);
546             throw new RedisAccessException(e);
547         } finally {
548             if (null != client) {
549                 jedisPool.returnResourceObject(client);
550             }
551         }
552     }
553 
554     /**
555      * 
556      * @描述 :查看哈希表 key 中,给定域 field 是否存在。
557      * @建立时间: 2015年7月20日下午2:02:38
558      *
559      * @param key
560      * @param field
561      * @return
562      * @throws RedisAccessException
563      */
564     public Boolean hexists(String key, String field) throws RedisAccessException {
565         Jedis client = null;
566         try {
567             client = jedisPool.getResource();
568             return client.hexists(key, field);
569         } catch (Exception e) {
570             LOG.error(e.getMessage(), e);
571             throw new RedisAccessException(e);
572         } finally {
573             if (null != client) {
574                 jedisPool.returnResourceObject(client);
575             }
576         }
577     }
578 
579     /**
580      * 
581      * @描述 : 将一个或多个值 value 插入到列表 key 的表尾(最右边)。
582      * @建立时间: 2015年7月20日下午2:02:44
583      *
584      * @param key
585      * @param values
586      * @return
587      * @throws RedisAccessException
588      */
589     public Long rpush(String key, String[] values) throws RedisAccessException {
590         Jedis client = null;
591         try {
592             client = jedisPool.getResource();
593             return client.rpush(key, values);
594         } catch (Exception e) {
595             LOG.error(e.getMessage(), e);
596             throw new RedisAccessException(e);
597         } finally {
598             if (null != client) {
599                 jedisPool.returnResourceObject(client);
600             }
601         }
602     }
603 
604     /**
605      * 
606      * @描述 : 将值 value 插入到列表 key 的表尾,当且仅当 key 存在而且是一个列表。
607      * @建立时间: 2015年7月20日下午2:03:20
608      *
609      * @param key
610      * @param value
611      * @return
612      * @throws RedisAccessException
613      */
614     public Long rpushx(String key, String value) throws RedisAccessException {
615         Jedis client = null;
616         try {
617             client = jedisPool.getResource();
618             return client.rpushx(key, new String[] { value });
619         } catch (Exception e) {
620             LOG.error(e.getMessage(), e);
621             throw new RedisAccessException(e);
622         } finally {
623             if (null != client) {
624                 jedisPool.returnResourceObject(client);
625             }
626         }
627     }
628 
629     /**
630      * 
631      * @描述 : 将一个或多个值 value 插入到列表 key 的表头
632      * @建立时间: 2015年7月20日下午2:04:13
633      *
634      * @param key
635      * @param values
636      * @return
637      * @throws RedisAccessException
638      */
639     public Long lpush(String key, String[] values) throws RedisAccessException {
640         Jedis client = null;
641         try {
642             client = jedisPool.getResource();
643             return client.lpush(key, values);
644         } catch (Exception e) {
645             LOG.error(e.getMessage(), e);
646             throw new RedisAccessException(e);
647         } finally {
648             if (null != client) {
649                 jedisPool.returnResourceObject(client);
650             }
651         }
652     }
653 
654     /**
655      * 
656      * @描述 : 将值 value 插入到列表 key 的表头,当且仅当 key 存在而且是一个列表。 和 LPUSH 命令相反,当 key 不存在时,
657      *     LPUSHX 命令什么也不作。
658      * @建立时间: 2015年7月20日下午2:05:09
659      *
660      * @param key
661      * @param value
662      * @return
663      * @throws RedisAccessException
664      */
665     public Long lpushx(String key, String value) throws RedisAccessException {
666         Jedis client = null;
667         try {
668             client = jedisPool.getResource();
669             return client.lpushx(key, new String[] { value });
670         } catch (Exception e) {
671             LOG.error(e.getMessage(), e);
672             throw new RedisAccessException(e);
673         } finally {
674             if (null != client) {
675                 jedisPool.returnResourceObject(client);
676             }
677         }
678     }
679 
680     /**
681      * 
682      * @描述 : 返回列表 key 的长度。若是 key 不存在,则 key 被解释为一个空列表,返回 0 . 若是 key
683      *     不是列表类型,返回一个错误。
684      * @建立时间: 2015年7月20日下午2:05:25
685      *
686      * @param key
687      * @return
688      * @throws RedisAccessException
689      */
690     public Long llen(String key) throws RedisAccessException {
691         Jedis client = null;
692         try {
693             client = jedisPool.getResource();
694             return client.llen(key);
695         } catch (Exception e) {
696             LOG.error(e.getMessage(), e);
697             throw new RedisAccessException(e);
698         } finally {
699             if (null != client) {
700                 jedisPool.returnResourceObject(client);
701             }
702         }
703     }
704 
705     /**
706      * 
707      * @描述 : 返回列表 key 中,下标为 index 的元素。
708      * @建立时间: 2015年7月20日下午2:05:37
709      *
710      * @param key
711      * @param index
712      * @return
713      * @throws RedisAccessException
714      */
715     public String lindex(String key, long index) throws RedisAccessException {
716         Jedis client = null;
717         try {
718             client = jedisPool.getResource();
719             return client.lindex(key, index);
720         } catch (Exception e) {
721             LOG.error(e.getMessage(), e);
722             throw new RedisAccessException(e);
723         } finally {
724             if (null != client) {
725                 jedisPool.returnResourceObject(client);
726             }
727         }
728     }
729 
730     /**
731      * 
732      * @描述 : 将列表 key 下标为 index 的元素的值设置为 value 。当 index 参数超出范围,或对一个空列表( key
733      *     不存在)进行 LSET 时,返回一个错误。
734      * @建立时间: 2015年7月20日下午2:07:06
735      *
736      * @param key
737      * @param index
738      * @param value
739      * @return
740      * @throws RedisAccessException
741      */
742     public String lset(String key, long index, String value) throws RedisAccessException {
743         Jedis client = null;
744         try {
745             client = jedisPool.getResource();
746             return client.lset(key, index, value);
747         } catch (Exception e) {
748             LOG.error(e.getMessage(), e);
749             throw new RedisAccessException(e);
750         } finally {
751             if (null != client) {
752                 jedisPool.returnResourceObject(client);
753             }
754         }
755     }
756 
757     /**
758      * 
759      * @描述 : 移除并返回列表 key 的头元素。
760      * @建立时间: 2015年7月20日下午2:07:10
761      *
762      * @param key
763      * @return
764      * @throws RedisAccessException
765      */
766     public String lpop(String key) throws RedisAccessException {
767         Jedis client = null;
768         try {
769             client = jedisPool.getResource();
770             return client.lpop(key);
771         } catch (Exception e) {
772             LOG.error(e.getMessage(), e);
773             throw new RedisAccessException(e);
774         } finally {
775             if (null != client) {
776                 jedisPool.returnResourceObject(client);
777             }
778         }
779     }
780 
781     /**
782      * 
783      * @描述 : 移除并返回列表 key 的尾元素。
784      * @建立时间: 2015年7月20日下午2:07:13
785      *
786      * @param key
787      * @return
788      * @throws RedisAccessException
789      */
790     public String rpop(String key) throws RedisAccessException {
791         Jedis client = null;
792         try {
793             client = jedisPool.getResource();
794             return client.rpop(key);
795         } catch (Exception e) {
796             LOG.error(e.getMessage(), e);
797             throw new RedisAccessException(e);
798         } finally {
799             if (null != client) {
800                 jedisPool.returnResourceObject(client);
801             }
802         }
803     }
804 
805     /**
806      * 
807      * @描述 : 将值 value 插入到列表 key 当中,位于值 pivot 以前或以后。当 pivot 不存在于列表 key 时,不执行任何操做。
808      *     key 不存在时, key 被视为空列表,不执行任何操做。 若是 key 不是列表类型,返回一个错误。
809      * @建立时间: 2015年7月20日下午2:07:37
810      *
811      * @param key
812      * @param where
813      * @param pivot
814      * @param value
815      * @return
816      * @throws RedisAccessException
817      */
818     public Long linsert(String key, BinaryClient.LIST_POSITION where, String pivot, String value) throws RedisAccessException {
819         Jedis client = null;
820         try {
821             client = jedisPool.getResource();
822             return client.linsert(key, where, pivot, value);
823         } catch (Exception e) {
824             LOG.error(e.getMessage(), e);
825             throw new RedisAccessException(e);
826         } finally {
827             if (null != client) {
828                 jedisPool.returnResourceObject(client);
829             }
830         }
831     }
832     
833     /**
834      * @描述 : 将 key 中储存的数字值增一。若是 key 不存在,那么 key 的值会先被初始化为 0 ,而后再执行 INCR 操做。
835      * @建立时间: 2014-6-16下午2:31:58
836      * 
837      * @param key
838      * @return
839      * @throws RedisAccessException
840      */
841     public Long incr(String key) throws RedisAccessException {
842         Jedis client = null;
843         try {
844             client = jedisPool.getResource();
845             return client.incr(key);
846         } catch (Exception e) {
847             LOG.error(e.getMessage(), e);
848             throw new RedisAccessException(e);
849         } finally {
850             if (null != client) {
851                 jedisPool.returnResourceObject(client);
852             }
853         }
854     }
855     
856     
857     /**
858      * @描述 :  将 key 所储存的值加上增量 increment 。若是 key 不存在,那么 key 的值会先被初始化为 0 ,而后再执行  INCRBY 命令。
859      * @建立时间: 2014-6-16下午2:31:58
860      * 
861      * @param key
862      * @return
863      * @throws RedisAccessException
864      */
865     public double incrBy(String key,long value) throws RedisAccessException {
866         Jedis client = null;
867         try {
868             client = jedisPool.getResource();
869             return client.incrBy(key, value);
870         } catch (Exception e) {
871             LOG.error(e.getMessage(), e);
872             throw new RedisAccessException(e);
873         } finally {
874             if (null != client) {
875                 jedisPool.returnResourceObject(client);
876             }
877         }
878     }
879 
880 }
View Code

OK,这个关于redis的相关内容更新完毕! 

本文地址: http://www.cnblogs.com/gzy-blog/p/6058849.html

相关文章
相关标签/搜索