标签 Redis 下的文章

Redis持久化

概述

Redis的强大性能很大程度上都是因为所有数据都是存储在内存中的,然而当Redis重启后,所有存储在内存中的数据将会丢失,在很多情况下是无法容忍这样的事情的。所以,我们需要将内存中的数据持久化!典型的需要持久化数据的场景如下:

  • 将Redis作为数据库使用;
  • 将Redis作为缓存服务器使用,但是缓存miss后会对性能造成很大影响,所有缓存同时失效时会造成服务雪崩,无法响应。

本文介绍Redis所支持的两种数据持久化方式。

Redis数据持久化

Redis支持两种数据持久化方式:RDB方式和AOF方式。前者会根据配置的规则定时将内存中的数据持久化到硬盘上,后者则是在每次执行写命令之后将命令记录下来。两种持久化方式可以单独使用,但是通常会将两者结合使用。

RDB方式

RDB方式的持久化是通过快照的方式完成的。当符合某种规则时,会将内存中的数据全量生成一份副本存储到硬盘上,这个过程称作”快照”,Redis会在以下几种情况下对数据进行快照:

  • 根据配置规则进行自动快照;
  • 用户执行SAVE, BGSAVE命令;
  • 执行FLUSHALL命令;
  • 执行复制(replication)时。
  • 执行快照的场景
根据配置自动快照

Redis允许用户自定义快照条件,当满足条件时自动执行快照,快照规则的配置方式如下:

save 900 1
save 300 10
save 60 10000

每个快照条件独占一行,他们之间是或(||)关系,只要满足任何一个就进行快照。上面配置save后的第一个参数T是时间,单位是秒,第二个参数M是更改的键的个数,含义是:当时间T内被更改的键的个数大于M时,自动进行快照。比如save 900 1的含义是15分钟内(900s)被更改的键的个数大于1时,自动进行快照操作。

执行SAVE或BGSAVE命令

除了让Redis自动进行快照外,当我们需要重启,迁移,备份Redis时,我们也可以手动执行SAVE或BGSAVE命令主动进行快照操作。

  • SAVE命令:当执行SAVE命令时,Redis同步进行快照操作,期间会阻塞所有来自客户端的请求,所以放数据库数据较多时,应该避免使用该命令;
  • BGSAVE命令: 从命令名字就能看出来,这个命令与SAVE命令的区别就在于该命令的快照操作是在后台异步进行的,进行快照操作的同时还能处理来自客户端的请求。执行BGSAVE命令后Redis会马上返回OK表示开始进行快照操作,如果想知道快照操作是否已经完成,可以使用LASTSAVE命令返回最近一次成功执行快照的时间,返回结果是一个Unix时间戳。
执行FLUSHALL命令

当执行FLUSHALL命令时,Redis会清除数据库中的所有数据。需要注意的是:不论清空数据库的过程是否触发 了自动快照的条件,只要自动快照条件不为空,Redis就会执行一次快照操作,当没有定义自动快照条件时,执行FLUSHALL命令不会进行快照操作。

执行复制

当设置了主从模式时,Redis会在复制初始化是进行自动快照。

快照原理

Redis默认会将快照文件存储在Redis当前进程的工作目录的dump.rdb文件中,可以通过配置文件中的dir和dbfilename两个参数分别指定快照文件的存储路径和文件名,例如:

dbfilename dump.rdb
dir /opt/soft/redis-3.0.4/cache

快照执行的过程如下:

  • Redis使用fork函数复制一份当前进程(父进程)的副本(子进程);
  • 父进程继续处理来自客户端的请求,子进程开始将内存中的数据写入硬盘中的临时文件;
  • 当子进程写完所有的数据后,用该临时文件替换旧的RDB文件,至此,一次快照操作完成。

需要注意的是:

在执行fork是时候操作系统(类Unix操作系统)会使用写时复制(copy-on-write)策略,即fork函数发生的一刻,父进程和子进程共享同一块内存数据,当父进程需要修改其中的某片数据(如执行写命令)时,操作系统会将该片数据复制一份以保证子进程不受影响,所以RDB文件存储的是执行fork操作那一刻的内存数据。所以RDB方式理论上是会存在丢数据的情况的(fork之后修改的的那些没有写进RDB文件)。

通过上述的介绍可以知道,快照进行时时不会修改RDB文件的,只有完成的时候才会用临时文件替换老的RDB文件,所以就保证任何时候RDB文件的都是完整的。这使得我们可以通过定时备份RDB文件来实现Redis数据的备份。RDB文件是经过压缩处理的二进制文件,所以占用的空间会小于内存中数据的大小,更有利于传输。

Redis启动时会自动读取RDB快照文件,将数据从硬盘载入到内存,根据数量的不同,这个过程持续的时间也不尽相同,通常来讲,一个记录1000万个字符串类型键,大小为1GB的快照文件载入到内存需要20-30秒的时间。

示例

下面演示RDB方式持久化,首先使用配置有如下快照规则:

save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir /opt/soft/redis-3.0.4/cache

的配置文件/opt/soft/redis-3.0.4/conf/redis.conf启动Redis服务:

然后通过客户端设置一个键值:

[root@localhost~]$ /opt/soft/redis-3.0.4/src/redis-cli -p 6379
127.0.0.1:6379> set test-rdb HelloWorld
OK
127.0.0.1:6379> get test-rdb
"HelloWorld"
127.0.0.1:6379>

现在强行kill Redis服务:

现在到/opt/soft/redis-3.0.4/cache目录看,目录下出现了Redis的快照文件dump.rdb:

[root@localhost/opt/soft/redis-3.0.4/cache]$ ls
dump.rdb

现在重新启动Redis:

然后再用客户端连接,检查之前设置的key是否还存在:

[qifuguang@Mac~]$ /opt/soft/redis-3.0.4/src/redis-cli -p 6379
127.0.0.1:6379> get test-rdb
"HelloWorld"
127.0.0.1:6379>

可以发现,之前设置的key在Redis重启之后又通过快照文件dump.rdb恢复了。

AOF方式

在使用Redis存储非临时数据时,一般都需要打开AOF持久化来降低进程终止导致的数据丢失,AOF可以将Redis执行的每一条写命令追加到硬盘文件中,这已过程显然会降低Redis的性能,但是大部分情况下这个影响是可以接受的,另外,使用较快的硬盘能提高AOF的性能。

开启AOF

默认情况下,Redis没有开启AOF(append only file)持久化功能,可以通过在配置文件中作如下配置启用:

appendonly yes

开启之后,Redis每执行一条写命令就会将该命令写入硬盘中的AOF文件。AOF文件保存路径和RDB文件路径是一致的,都是通过dir参数配置,默认文件名是:appendonly.aof,可以通过配置appendonlyfilename参数修改,例如:

appendonlyfilename appendonly.aof
AOF持久化的实现

AOF纯文本的形式记录了Redis执行的写命令,例如在开启AOF持久化的情况下执行如下命令:

[root@localhost/opt/soft/redis-3.0.4]$ ./src/redis-cli
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> set aof1 value1
OK
127.0.0.1:6379> set aof2 value2
OK
127.0.0.1:6379>

然后查看/opt/soft/redis-3.0.4/cache/appendonly.aof文件:

[root@localhost/opt/soft/redis-3.0.4/cache]$ cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$4
aof1
$6
value1
*3
$3
set
$4
aof2
$6
value2

文件中的内容正是Redis刚才执行的命令的内容,内容的格式就先不展开叙述了。

AOF文件重写

假设Redis执行了如下命令:

[root@localhost/opt/soft/redis-3.0.4]$ ./src/redis-cli
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379>
127.0.0.1:6379> set k v1
OK
127.0.0.1:6379> set k v2
OK
127.0.0.1:6379> set k v3
OK
127.0.0.1:6379>

如果这所有的命令都写到AOF文件的话,将是一个比较蠢行为,因为前面两个命令会被第三个命令覆盖,所以AOF文件完全不需要保存前面两个文件,事实上Redis确实就是这么做的。删除AOF文件中无用的命令的过程成为”AOF重写”,AOF重写可以在配置文件中做相应的配置,当满足配置的条件时,自动进行AOF重写操作。配置如下:

auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

第一行的意思是,目前的AOF文件的大小超过上一次重写时的AOF文件的百分之多少时再次进行重写,如果之前没有重写过,则以启动时AOF文件大小为依据。
第二行的意思是,当AOF文件的大小大于64MB时才进行重写,因为如果AOF文件本来就很小时,有几个无效的命令也是无伤大雅的事情。
这两个配置项通常一起使用。

我们还可以手动执行BDREWRITEAOF命令主动让Redis重写AOF文件,执行重写命令之后查看现在的AOF文件:

[root@localhost/opt/soft/redis-3.0.4]$ cat cache/appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
SET
$4
aof2
$6
value2
*3
$3
SET
$1
k
$2
v3
*3
$3
SET
$4
aof1
$6
value1

可以看到,文件中并没有再记录set k v1这样的无效命令。

同步硬盘数据

虽然每次执行更改数据库的内容时,AOF都会记录执行的命令,但是由于操作系统本身的硬盘缓存的缘故,AOF文件的内容并没有真正地写入硬盘,在默认情况下,操作系统会每隔30s将硬盘缓存中的数据同步到硬盘,但是为了防止系统异常退出而导致丢数据的情况发生,我们还可以在Redis的配置文件中配置这个同步的频率:

# appendfsync always
appendfsync everysec
# appendfsync no

第一行表示每次AOF写入一个命令都会执行同步操作,这是最安全也是最慢的方式;
第二行表示每秒钟进行一次同步操作,一般来说使用这种方式已经足够;
第三行表示不主动进行同步操作,这是最不安全的方式。

原文链接

Redis事务介绍

概述

相信学过Mysql等其他数据库的同学对事务这个词都不陌生,事务表示的是一组动作,这组动作要么全部执行,要么全部不执行。为什么会有这样的需求呢?看看下面的场景:

  • 微博是一个弱关系型社交网络,用户之间有关注和被关注两种关系,比如两个用户A和B,如果A关注B,则B的粉丝中就应该有A。关注这个动作需要两个步骤完成:在A的关注者中添加B;在B的粉丝中添加A。 这两个动作要么都执行成功,要么都不执行。否则就可能会出现A关注了B,但是B的粉丝中没有A的不可容忍的情况。
  • 转账汇款,假设现在有两个账户A和B,现在需要将A中的一万块大洋转到B的账户中,这个动作也需要两个步骤完成:从A的账户中划走一万块;在B的账户中增加一万块。这两个动作要么全部执行成功,要么全部不执行,否则自会有人问候你的!!!

Redis作为一种高效的分布式数据库,同样支持事务。

Redis事务

Redis中的事务(transaction)是一组命令的集合。事务同命令一样都是Redis最小的执行单位,一个事务中的命令要么都执行,要么都不执行。Redis事务的实现需要用到 MULTI  EXEC 两个命令,事务开始的时候先向Redis服务器发送 MULTI 命令,然后依次发送需要在本次事务中处理的命令,最后再发送 EXEC 命令表示事务命令结束。

举个例子,使用redis-cli连接redis,然后在命令行工具中输入如下命令:

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set url http://qifuguang.me
QUEUED
127.0.0.1:6379> set title winwill2012
QUEUED
127.0.0.1:6379> set desc java
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) OK
3) OK
127.0.0.1:6379>
127.0.0.1:6379> get url
"http://qifuguang.me"
127.0.0.1:6379> get title
"winwill2012"
127.0.0.1:6379> get desc
"java"
127.0.0.1:6379>

从输出中可以看到,当输入MULTI命令后,服务器返回OK表示事务开始成功,然后依次输入需要在本次事务中执行的所有命令,每次输入一个命令服务器并不会马上执行,而是返回”QUEUED”,这表示命令已经被服务器接受并且暂时保存起来,最后输入EXEC命令后,本次事务中的所有命令才会被依次执行,可以看到最后服务器一次性返回了三个OK,这里返回的结果与发送的命令是按顺序一一对应的,这说明这次事务中的命令全都执行成功了。

再举个例子,在命令行工具中输入如下命令:

127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set a a
QUEUED
127.0.0.1:6379> sett b b
(error) ERR unknown command 'sett'
127.0.0.1:6379> set c c
QUEUED
127.0.0.1:6379> EXEC
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get a
(nil)
127.0.0.1:6379> get b
(nil)
127.0.0.1:6379> get c
(nil)
127.0.0.1:6379>

和前面的例子一样,先输入MULTI最后输入EXEC表示中间的命令属于一个事务,不同的是中间输入的命令有一个错误(set写成了sett),这样因为有一个错误的命令导致事务中的其他命令都不执行了(通过后续的get命令可以验证),可见事务中的所有命令式同呼吸共命运的。

如果客户端在发送EXEC命令之前断线了,则服务器会清空事务队列,事务中的所有命令都不会被执行。而一旦客户端发送了EXEC命令之后,事务中的所有命令都会被执行,即使此后客户端断线也没关系,因为服务器已经保存了事务中的所有命令。

除了保证事务中的所有命令要么全执行要么全不执行外,Redis的事务还能保证一个事务中的命令依次执行而不会被其他命令插入。试想一个客户端A需要执行几条命令,同时客户端B发送了几条命令,如果不使用事务,则客户端B的命令有可能会插入到客户端A的几条命令中,如果想避免这种情况发生,也可以使用事务。

Redis事务错误处理

如果一个事务中的某个命令执行出错,Redis会怎样处理呢?要回答这个问题,首先要搞清楚是什么原因导致命令执行出错:

  1. 语法错误 就像上面的例子一样,语法错误表示命令不存在或者参数错误
    这种情况需要区分Redis的版本,Redis 2.6.5之前的版本会忽略错误的命令,执行其他正确的命令,2.6.5之后的版本会忽略这个事务中的所有命令,都不执行,就比如上面的例子(使用的Redis版本是2.8的)
  2. 运行错误 运行错误表示命令在执行过程中出现错误,比如用GET命令获取一个散列表类型的键值。
    这种错误在命令执行之前Redis是无法发现的,所以在事务里这样的命令会被Redis接受并执行。如果食物里有一条命令执行错误,其他命令依旧会执行(包括出错之后的命令)。比如下例:
    127.0.0.1:6379> MULTI
    OK
    127.0.0.1:6379> set key 1
    QUEUED
    127.0.0.1:6379> SADD key 2
    QUEUED
    127.0.0.1:6379> set key 3
    QUEUED
    127.0.0.1:6379> EXEC
    1) OK
    2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
    3) OK
    127.0.0.1:6379> get key
    "3"
    Redis中的事务并没有关系型数据库中的事务回滚(rollback)功能,因此使用者必须自己收拾剩下的烂摊子。不过由于Redis不支持事务回滚功能,这也使得Redis的事务简洁快速。

回顾上面两种类型的错误,语法错误完全可以在开发的时候发现并作出处理,另外如果能很好地规划Redis数据的键的使用,也是不会出现命令和键不匹配的问题的。

WATCH命令

从上面的例子我们可以看到,事务中的命令要全部执行完之后才能获取每个命令的结果,但是如果一个事务中的命令B依赖于他上一个命令A的结果的话该怎么办呢?就比如说实现类似Java中的i++的功能,先要获取当前值,才能在当前值的基础上做加一操作。这种场合仅仅使用上面介绍的MULTI和EXEC是不能实现的,因为MULTI和EXEC中的命令是一起执行的,并不能将其中一条命令的执行结果作为另一条命令的执行参数,所以这个时候就需要引进Redis事务家族中的另一成员:WATCH命令

换个角度思考上面说到的实现i++的方法,可以这样实现:

  1. 监控i的值,保证i的值不被修改
  2. 获取i的原值
  3. 如果过程中i的值没有被修改,则将当前的i值+1,否则不执行

这样就能够避免竞态条件,保证i++能够正确执行。

WATCH命令可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行,监控一直持续到EXEC命令(事务中的命令是在EXEC之后才执行的,EXEC命令执行完之后被监控的键会自动被UNWATCH)

举个例子:

127.0.0.1:6379> set mykey 1
OK
127.0.0.1:6379> WATCH mykey
OK
127.0.0.1:6379> set mykey 2
OK
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> set mykey 3
QUEUED
127.0.0.1:6379> EXEC
(nil)
127.0.0.1:6379> get mykey
"2"
127.0.0.1:6379>

上面的例子中,首先设置mykey的键值为1,然后使用WATCH命令监控mykey,随后更改mykey的值为2,然后进入事务,事务中设置mykey的值为3,然后执行EXEC运行事务中的命令,最后使用get命令查看mykey的值,发现mykey的值还是2,也就是说事务中的命令根本没有执行(因为WATCH监控mykey的过程中,mykey被修改了,所以随后的事务便会被取消)。

有了WATCH命令,我们就可以自己实现i++功能了,伪代码如下:

def incr($key):
WATCH $key
$value = GET $key
if not $value
$value = 0
$value = $value + 1
    
MULTI
SET $key $value
result = EXEC
return result[0]

因为EXEC返回的是多行字符串,使用result[0]表示返回值的第一个字符串。

注意:由于WATCH命令的作用只是当被监控的键被修改后取消之后的事务,并不能保证其他客户端不修改监控的值,所以当EXEC命令执行失败之后需要手动重新执行整个事务。

执行EXEC命令之后会取消监控使用WATCH命令监控的键,如果不想执行事务中的命令,也可以使用UNWATCH命令来取消监控。

原文链接:http://qifuguang.me/2015/09/30/Redis事务介绍/

Redis五种数据类型介绍

概述

Redis的键值可以使用物种数据类型:字符串,散列表,列表,集合,有序集合。本文详细介绍这五种数据类型的使用方法。本文命令介绍部分只是列举了基本的命令,至于具体的使用示例,可以参考Redis官方文档:Redis命令大全

字符串类型

字符串是Redis中最基本的数据类型,它能够存储任何类型的字符串,包含二进制数据。可以用于存储邮箱,JSON化的对象,甚至是一张图片,一个字符串允许存储的最大容量为512MB。字符串是其他四种类型的基础,与其他几种类型的区别从本质上来说只是组织字符串的方式不同而已。

基本命令

字符串操作

  1. SET 赋值,用法: SET key value
  2. GET 取值,用法: GET key
  3. INCR 递增数字,仅仅对数字类型的键有用,相当于Java的i++运算,用法: INCR key
  4. INCRBY 增加指定的数字,仅仅对数字类型的键有用,相当于Java的i+=3,用法:INCRBY key increment,意思是key自增increment,increment可以为负数,表示减少。
  5. DECR 递减数字,仅仅对数字类型的键有用,相当于Java的i–,用法:DECR key
  6. DECRBY 减少指定的数字,仅仅对数字类型的键有用,相当于Java的i-=3,用法:DECRBY key decrement,意思是key自减decrement,decrement可以为正数,表示增加。
  7. INCRBYFLOAT 增加指定浮点数,仅仅对数字类型的键有用,用法:INCRBYFLOAT key increment
  8. APPEND 向尾部追加值,相当于Java中的”hello”.append(“ world”),用法:APPEND key value
  9. STRLEN 获取字符串长度,用法:STRLEN key
  10. MSET 同时设置多个key的值,用法:MSET key1 value1 [key2 value2 ...]
  11. MGET 同时获取多个key的值,用法:MGET key1 [key2 ...]

位操作

  1. GETBIT 获取一个键值的二进制位的指定位置的值(0/1),用法:GETBIT key offset
  2. SETBIT 设置一个键值的二进制位的指定位置的值(0/1),用法:SETBIT key offset value
  3. BITCOUNT 获取一个键值的一个范围内的二进制表示的1的个数,用法:BITCOUNT key [start end]
  4. BITOP 该命令可以对多个字符串类型键进行位运算,并将结果存储到指定的键中,BITOP支持的运算包含:OR,AND,XOR,NOT,用法:BITOP OP desKey key1 key2
  5. BITPOS 获取指定键的第一个位值为0或者1的位置,用法:BITPOS key 0/1 [start, end]

散列类型

散列类型相当于Java中的HashMap,他的值是一个字典,保存很多key,value对,每对key,value的值个键都是字符串类型,换句话说,散列类型不能嵌套其他数据类型。一个散列类型键最多可以包含2的32次方-1个字段。

基本命令

  1. HSET 赋值,用法:HSET key field value
  2. HMSET 一次赋值多个字段,用法:HMSET key field1 value1 [field2 values]
  3. HGET 取值,用法:HSET key field
  4. HMGET 一次取多个字段的值,用法:HMSET key field1 [field2]
  5. HGETALL 一次取所有字段的值,用法:HGETALL key
  6. HEXISTS 判断字段是否存在,用法:HEXISTS key field
  7. HSETNX 当字段不存在时赋值,用法:HSETNX key field value
  8. HINCRBY 增加数字,仅对数字类型的值有用,用法:HINCRBY key field increment
  9. HDEL 删除字段,用法:HDEL key field
  10. HKEYS 获取所有字段名,用法:HKEYS key
  11. HVALS 获取所有字段值,用法:HVALS key
  12. HLEN 获取字段数量,用法:HLEN key

列表类型

列表类型(list)用于存储一个有序的字符串列表,常用的操作是向队列两端添加元素或者获得列表的某一片段。列表内部使用的是双向链表(double linked list)实现的,所以向列表两端添加元素的时间复杂度是O(1),获取越接近列表两端的元素的速度越快。但是缺点是使用列表通过索引访问元素的效率太低(需要从端点开始遍历元素)。所以列表的使用场景一般如:朋友圈新鲜事,只关心最新的一些内容。借助列表类型,Redis还可以作为消息队列使用。

基本命令

  1. LPUSH 向列表左端添加元素,用法:LPUSH key value
  2. RPUSH 向列表右端添加元素,用法:RPUSH key value
  3. LPOP 从列表左端弹出元素,用法:LPOP key
  4. RPOP 从列表右端弹出元素,用法:RPOP key
  5. LLEN 获取列表中元素个数,用法:LLEN key
  6. LRANGE 获取列表中某一片段的元素,用法:LRANGE key start stop,index从0开始,-1表示最后一个元素
  7. LREM 删除列表中指定的值,用法:LREM key count value,删除列表中前count个值为value的元素,当count>0时从左边开始数,count<0时从右边开始数,count=0时会删除所有值为value的元素
  8. LINDEX 获取指定索引的元素值,用法:LINDEX key index
  9. LSET 设置指定索引的元素值,用法:LSET key index value
  10. LTRIM 只保留列表指定片段,用法:LTRIM key start stop,包含start和stop
  11. LINSERT 像列表中插入元素,用法:LINSERT key BEFORE|AFTER privot value,从左边开始寻找值为privot的第一个元素,然后根据第二个参数是BEFORE还是AFTER决定在该元素的前面还是后面插入value
  12. RPOPLPUSH 将元素从一个列表转义到另一个列表,用法:RPOPLPUSH source destination

集合类型

集合在概念在高中课本就学过,集合中每个元素都是不同的,集合中的元素个数最多为2的32次方-1个,集合中的元素师没有顺序的。

基本命令

  1. SADD 添加元素,用法:SADD key value1 [value2 value3 ...]
  2. SREM 删除元素,用法:SREM key value2 [value2 value3 ...]
  3. SMEMBERS 获得集合中所有元素,用法:SMEMBERS key
  4. SISMEMBER 判断元素是否在集合中,用法:SISMEMBER key value
  5. SDIFF 对集合做差集运算,用法:SDIFF key1 key2 [key3 ...],先计算key1和key2的差集,然后再用结果与key3做差集
  6. SINTER 对集合做交集运算,用法:SINTER key1 key2 [key3 ...]
  7. SUNION 对集合做并集运算,用法:SUNION key1 key2 [key3 ...]
  8. SCARD 获得集合中元素的个数,用法:SCARD key
  9. SDIFFSTORE 对集合做差集并将结果存储,用法:SDIFFSTORE destination key1 key2 [key3 ...]
  10. SINTERSTORE 对集合做交集运算并将结果存储,用法:SINTERSTORE destination key1 key2 [key3 ...]
  11. SUNIONSTORE 对集合做并集运算并将结果存储,用法:SUNIONSTORE destination key1 key2 [key3 ...]
  12. SRANDMEMBER 随机获取集合中的元素,用法:SRANDMEMBER key [count],当count>0时,会随机中集合中获取count个不重复的元素,当count<0时,随机中集合中获取|count|和可能重复的元素。
  13. SPOP 从集合中随机弹出一个元素,用法:SPOP key

有序集合类型

有序集合类型与集合类型的区别就是他是有序的。有序集合是在集合的基础上为每一个元素关联一个分数,这就让有序集合不仅支持插入,删除,判断元素是否存在等操作外,还支持获取分数最高/最低的前N个元素。有序集合中的每个元素是不同的,但是分数却可以相同。有序集合使用散列表和跳跃表实现,即使读取位于中间部分的数据也很快,时间复杂度为O(log(N)),有序集合比列表更费内存。

基本命令

  1. ZADD 添加元素,用法:ZADD key score1 value1 [score2 value2 score3 value3 ...]
  2. ZSCORE 获取元素的分数,用法:ZSCORE key value
  3. ZRANGE 获取排名在某个范围的元素,用法:ZRANGE key start stop [WITHSCORE],按照元素从小到大的顺序排序,从0开始编号,包含start和stop对应的元素,WITHSCORE选项表示是否返回元素分数
  4. ZREVRANGE 获取排名在某个范围的元素,用法:ZREVRANGE key start stop [WITHSCORE],和上一个命令用法一样,只是这个倒序排序的。
  5. ZRANGEBYSCORE 获取指定分数范围内的元素,用法:ZRANGEBYSCORE key min max,包含min和max,(min表示不包含min,(max表示不包含max,+inf表示无穷大
  6. ZINCRBY 增加某个元素的分数,用法:ZINCRBY key increment value
  7. ZCARD 获取集合中元素的个数,用法:ZCARD key
  8. ZCOUNT 获取指定分数范围内的元素个数,用法:ZCOUNT key min max,min和max的用法和5中的一样
  9. ZREM 删除一个或多个元素,用法:ZREM key value1 [value2 ...]
  10. ZREMRANGEBYRANK 按照排名范围删除元素,用法:ZREMRANGEBYRANK key start stop
  11. ZREMRANGEBYSCORE 按照分数范围删除元素,用法:ZREMRANGEBYSCORE key min max,min和max的用法和4中的一样
  12. ZRANK 获取正序排序的元素的排名,用法:ZRANK key value
  13. ZREVRANK 获取逆序排序的元素的排名,用法:ZREVRANK key value
  14. ZINTERSTORE 计算有序集合的交集并存储结果,用法:ZINTERSTORE destination numbers key1 key2 [key3 key4 ...] WEIGHTS weight1 weight2 [weight3 weight4 ...] AGGREGATE SUM | MIN | MAX,numbers表示参加运算的集合个数,weight表示权重,aggregate表示结果取值
  15. ZUNIONSTORE 计算有序几个的并集并存储结果,用法和14一样,不再赘述。

原文链接:http://qifuguang.me/2015/09/29/Redis五种数据类型介绍/