Redis——Redis简介

Redis是目前最流行的键值对(key-value)数据库,以出色的性能著称,官方提供的数据是可以支持100000以上的+QPS。Redis具有高性能的主要原因如下:

  • Redis是基于内存的存储数据库,绝大部分的命令处理只是纯粹的内存操作,内存的读写速度非常快。
  • Redis是单进程线程的服务(实际上一个正在运行的Redis Server肯定不止一个线程,但只有一个线程来处理网络请求),避免了不必要的上下文切换,同时不存在加锁/释放锁等同步操作。
  • Redis使用多路I/O复用模型(select、poll、epoll),可以高效处理大量并发连接。
  • Redis中的数据结构是专门设计的,增、删、改、查等操作相对简单。

1、Redis简介

Redis(REmote DIctionary Server)是一个使用ANSI C编写的、开源的、支持网络的、基于内存的、可选持久化的键值对存储系统。在2013年5月之前,Redis的开发由VMware赞助;2013年5月至2015年6月,由Pivotal赞助;从2015年6月起,Redis的开发由Redis Labs赞助。根据数据库使用排行网站db-engines.com上的排名,Redis是目前最流行的键值对存储系统。

Redis由Salvatore Sanfilippo在2009年发布初始版本,开源后不断发展壮大,目前的最新版为Redis 7.0。

Redis在互联网数据存储方面应用广泛,主要具有以下优点:

  • Redis是内存型的数据库,也就是说Redis中的key-value对是存储在内存中的,因而效率比磁盘型的快。
  • Redis的工作模式为单线程(Redis6之前,从Redis6开始支持多线程),不需要线程间的同步操作。Redis采用单线程主要因为其瓶颈在内存和带宽上,而不是CPU。
  • Redis中key-value的value不仅可以是字符串,也可以是复杂的数据类型,如链表、集合、散列表等。
  • Redis支持数据持久化,可以采用RDB、AOF、RDB&AOF三种方案。计算机重启后可以在磁盘中进行数据恢复。
  • Redis支持主从结构,可以利用从实例进行数据备份。

2、Redis 5.0的新特性

相较于Redis 4.0, Redis 5.0增加了很多新的特性,限于篇幅,本节主要介绍几个较重要的特性,具体内容可以参考官方文档:

  • 新增Streams数据类型,这是Redis 5.0最重要的改进之一。可以把Streams当作消息队列
  • 新的模块API、定时器、集群及字典。
  • RDB中持久化存储LFU和LRU的信息。
  • 将集群管理功能完全用C语言集成到redis-cli中,Redis 3.x和Redis 4.x的集群管理是通过Ruby脚本实现的。
  • 有序集合新增命令ZPOPMIN/ZPOPMAX。
  • 改进HyperLogLog的实现。
  • 新增Client Unblock和Client ID。
  • 新增LOLWUT命令。
  • Redis主从复制中的从不再称为Slave,改称Replicas。
  • Redis 5.0引入动态哈希,以平衡CPU的使用率和相应性能,可以通过配置文件进行配置。Redis 5.0默认使用动态哈希。
  • Redis核心代码进行了部分重构和优化。

3、Redis常用数据类

Redis的数据存储结构是key-value对,定义key时要注意以下几点:

  • key不要太长,尽量不要超过1024Byte,太长的话不仅消耗内存,而且会降低查找的效率。
  • key也不要太短,太短的话,key的可读性会降低。
  • 一个项目中,key单词与单词之间以:分开,例如SET user-name:loginnamewangwu。

这里主要简单介绍Redis的5种数据类型,即String、Hash、List、Set及Sorted Set。

3.1、String类型

String类型是Redis最基本的数据类型,一个key对应一个value。String类型是二进制安全的,即Redis的String类型可以包含任何数据,例如扩展名为.jpg的图片或者序列化的对象。

1、SET

SET命令的基本语法如下:

SET key value 

SET用于将字符串值value关联到key。如果key已经持有其他值,SET就覆盖其他值。返回值:总是返回OK,因为SET不可能失败。

实例1:对字符串类型的key执行SET命令:
在这里插入图片描述
实例2:对非字符串类型的key执行SET命令:

127.0.0.1:6379> LPUSH greet_list "hello"  # 建立一个列表 
(integer) 1 

127.0.0.1:6379> TYPE greet_list 
list 

127.0.0.1:6379> SET greet_list "world"    # 覆盖列表类型 
OK 
127.0.0.1:6379> TYPE greet_list 
string 

2、SETNX

SETNX命令的基本语法如下:

SETNX key value

SETNX是Set If Not Exists(如果不存在,则SET)的简写。SETNX用于将key的值设为String类型的value,当key不存在时,返回1;若key已经存在,则SETNX不执行任何操作,返回0。返回值:设置成功,返回1;设置失败,返回0。

实例如下:

127.0.0.1:6379> EXISTS language            # language不存在 
(integer) 0 
127.0.0.1:6379> SETNX language "java"      # language设置成功 
(integer) 1 
127.0.0.1:6379> SETNX language "python"    # language设置失败 
(integer) 0 
127.0.0.1:6379> GET language               # language没有被覆盖 
"java" 

第一次设置language时没有对应的值,所以SETNX修改生效,返回值为1;第二次设置language时已经有了对应的值java,所以本次修改不生效,返回值为0。

3、SETEX

SETEX命令的基本语法如下:

SETEX key seconds value

SETEX用于设置key对应的值为String类型的value,并指定此key对应的有效期,有效期的过期时间以秒(seconds)为单位。如果key对应的值已经存在,那么SETEX将覆盖旧值。这个命令类似于以下两个命令:

SET key value       #设置值
EXPIRE key seconds  # 设置过期时间

不同之处在于,SETEX命令是一个原子性操作,设置值和设置过期时间两个操作会在同一时间内完成。该命令经常用在缓存操作中。返回值:设置成功时返回OK;当seconds参数不合法时,返回一个错误。

实例1:key不存在:

127.0.0.1:6379> SETEX color 60 red      # 设置color的过期时间为60s 
OK 
127.0.0.1:6379> GET color               # 获得color值 
"red" 
127.0.0.1:6379> TTL color               # 获得color剩余的过期时间 
(integer) 49 
127.0.0.1:6379> GET color 
"red" 
127.0.0.1:6379> GET color               # 60s后,color值为空 
(nil) 

本例我们添加了一个color-red对,并指定它的有效期是60s。然后使用TTL命令查看color的过期时间,最后一次调用color是在60s以后,所以取不到color对应的值。

实例2:key已经存在,key对应的值将被覆盖:

127.0.0.1:6379> SET color "red" 
OK 
127.0.0.1:6379> SETEX color 60 "green" 
OK 
127.0.0.1:6379> GET color 
"green" 

在本例中已经设置了color对应的值,可以使用SETEX覆盖color对应的值。使用SETEX设置过期时间60s,在60s内color对应的值为green。

4、SETRANGE

SETRANGE命令的基本语法如下:

SETRANGE key offset value

通过SETRANGE用value重写key所存储的字符串值,从偏移量offset开始。不存在的key当作空白字符串处理。返回值:被SETRANGE修改之后,字符串的长度。

实例1:对非空字符串执行SETRANGE命令:
例如我们希望将xpws2006的163邮箱替换为QQ邮箱,我们可以这么做。

127.0.0.1:6379> SET email "xpws2006@163.com" 
OK 
127.0.0.1:6379> SETRANGE email 9 "qq.com" 
(integer) 16
127.0.0.1:6379> GET email 
"xpws2006@qq.com" 

实例2:对空字符串/不存在的key执行SETRANGE命令:

127.0.0.1:6379> EXISTS empty_string 
(integer) 0 
127.0.0.1:6379> SETRANGE empty_string 5 "Redis"  # 对不存在的key使用SETRANGE 
(integer) 10 
127.0.0.1:6379> GET empty_string  # 空白处被零比特“\x00”填充 
"\x00\x00\x00\x00\x00Redis" 

5、MSET

MSET命令的基本语法如下:

MSET key value [key value ...]

通过MSET可一次设置多个key的值,执行成功返回OK,表示所有值都被设置了;执行失败返回0,表示没有任何值被设置。MSET是一个原子性操作,所有的key都在同一时间内被设置。返回值:成功返回OK,失败返回0。

实例如下:

127.0.0.1:6379> MSET name1 "xinping1" name2 "xinping2" 
OK
127.0.0.1:6379> KEYS *                   # 确保指定的两个键值对被插入
1) "name2" 
2) "name1" 
127.0.0.1:6379> MSET name2 "xinping3"    # MSET覆盖旧值 
OK 
127.0.0.1:6379> GET name2 
"xinping2" 

6、MSETNX

MSETNX命令的基本语法如下:

MSETNX key value [key value ...]

MSETNX用于设置一个或多个key的值,执行成功返回OK,表示所有值都被设置了;执行失败返回0,表示没有任何值被设置,不会覆盖已经存在的key。

MSETNX是原子性的,因此它可以用作设置多个不同的key,表示不同字段(field)的唯一性逻辑对象(Unique Logic Object),所有字段要么全被设置,要么全不被设置。

返回值:如果所有key都成功设置,那么返回1;如果所有key都设置失败(最少有一个key已经存在),那么返回0。

实例1:对不存在的key执行MSETNX命令:

127.0.0.1:6379> MSETNX key1 "a" key2 "b" 
(integer)1
127.0.0.1:6379> GET key1 
"a" 
127.0.0.1:6379> GET key2 
"b" 

实例2:对已存在的key执行MSETNX命令:

127.0.0.1:6379> MSET key1 "a" key2 "b" 
OK 
127.0.0.1:6379> GET key1 
"a" 
127.0.0.1:6379> GET key2 
"b" 
127.0.0.1:6379> MSETNX key2 "new_b" key3 "c"   # key2已经存在,所以操作失败 
(integer) 0 
127.0.0.1:6379> EXISTS key3              # 因为命令是原子性的,所以key3没有被设置 
(integer) 0 
127.0.0.1:6379> MGET key1 key2 key3      # key2没有被修改 
1) "a" 
2) "b" 
3) (nil) 
127.0.0.1:6379> GET key3 
(nil) 

7、APPEND

APPEND命令的基本语法如下:

APPEND key value 

如果key已经存在并且是一个字符串,那么可以通过APPEND将value追加到key关联的值后面。如果key不存在,就简单地将key设为value,就像执行SET key value一样。

返回值:追加value之后,key中字符串的长度。

实例1:对不存在的key执行APPEND命令:

127.0.0.1:6379> EXISTS myphone # 确保myphone不存在 
(integer) 0 
 
127.0.0.1:6379> APPEND myphone "huawei"  # 对不存在的key执行APPEND命令,等同于SET 
myphone "huawei" 
(integer) 6 # 字符串的长度

实例2:对已存在的key执行APPEND命令:

127.0.0.1:6379> APPEND myphone " p20" 
(integer) 10  # 长度从6个字符增加到10个字符 
 
127.0.0.1:6379> GET myphone  # 查看整个字符串 
"Huawei p20" 

8、GET

GET命令的基本语法如下:

GET key

GET用于返回key所关联的字符串值。如果key不存在则返回特殊值nil。

假如key存储的值不是字符串类型,会返回一个错误,因为GET只能用于处理字符串值。

返回值:key的值。如果key不存在,返回nil。

实例1:获取一个库中已存在的phone,可以得到它对应的value:

127.0.0.1:6379> SET phone "huawei p20" 
OK 
127.0.0.1:6379> GET phone 
"huawei p20" 

实例2:获取一个库中不存在的phone2,那么它会返回一个nil,表示没有这个key-value对:

127.0.0.1:6379> GET phone2 
(nil)

9、MGET

MGET key [key ...]

MGET用于返回一个或多个key的值。如果key不存在,那么返回特殊值nil。因此,该命令永远不会执行失败。

返回值:执行成功则返回一个包含所有key的值的列表,执行失败则返回nil。

实例如下:

#用MSET一次存储多个值 
127.0.0.1:6379> MSET name "xinping"  age 25 
OK 
127.0.0.1:6379> MGET name age 
1) "xinping" 
2) "25" 
127.0.0.1:6379> EXISTS fake_key
(integer) 0 
# 当MGET中有不存在key的情况 
127.0.0.1:6379> MGET name fake_key 
1) "xinping" 
2) (nil) 

10、GETRANGE

GETRANGE命令的基本语法如下:

GETRANGE key start end

GETRANGE用于获取指定key中字符串值的子字符串,子字符串的截取范围由start和end两个偏移量决定(包括start和end在内)。负数偏移量表示从字符串的最后开始计数,-1表示字符串中最后一个字符,-2表示字符串中倒数第二个字符,其他负数依此类推。

返回值:截取的子字符串。

实例如下:

127.0.0.1:6379> SET email "xpws2006@163.com" 
OK 
127.0.0.1:6379> GET email 
"xpws2006@163.com" 
127.0.0.1:6379> GETRANGE email 0 7 
"xpws2006"

GETRANGE email 0 7截取子字符串的索引是0~7,包括0和7。

截取子字符串-7~-1,包括-7和-1:

127.0.0.1:6379> GETRANGE email -7 -1 
"163.com"

截取子字符串从第一个字符到最后一个字符:

127.0.0.1:6379> GETRANGE email 0 -1 
"xpws2006@163.com"

GETRANGE的取值范围不超过实际字符串长度,超过部分会被忽略:

127.0.0.1:6379> GETRANGE email 0 199 
"xpws2006@163.com"

11、GETSET

GETSET命令的基本语法如下:

GETSET key value

GETSET用于将key的值设为value,并返回key的旧值。

返回值:返回key的旧值。当key没有旧值时,返回nil。

实例如下:

127.0.0.1:6379> SET name xinping 
OK 
127.0.0.1:6379> GET name 
"xinping" 
 
# name对应的值被更新,旧值被返回 
127.0.0.1:6379> GETSET name xinping_new  
"xinping"
127.0.0.1:6379> GET name 
"xinping_new"

接下来看一看,如果key不存在,那么使用GETSET会返回什么值?

127.0.0.1:6379> EXISTS name1 
(integer) 0 
127.0.0.1:6379> GETSET name1 "xinping" 
(nil) 
127.0.0.1:6379> GET name1 
"xinping"

因为name1之前不存在,没有旧值,所以返回nil。

GETSET可以和INCR组合使用,实现一个有原子性复位操作功能的计数器(counter)。

可以用GETSET mycount 0来实现这一目标:

127.0.0.1:6379> INCR mycount 
(integer) 1 
 
# 一个原子操作内完成GET mycount和GETSET mycount 0 
127.0.0.1:6379> GETSET mycount 0   
"1" 
 
127.0.0.1:6379> GET mycount 
"0" 

12、STRLEN

STRLEN命令的基本语法如下:

STRLEN key 

STRLEN用于返回key所存储的字符串的长度。

返回值:字符串的长度。当key不存在时,返回0。

实例1:获取key存储的字符串“hello world”的长度:

127.0.0.1:6379> SET key "hello world" 
OK 
127.0.0.1:6379> STRLEN key 
(integer) 11

实例2:当key不存在时,它获取的字符串长度为0:

127.0.0.1:6379> STRLEN nonexisting  
(integer) 0

13、DECR

DECR命令的基本语法如下:

DECR key

DECR用于将key中存储的数值减1。如果key不存在,则以0为key的初始值,然后执行DECR命令,设置key对应的值为-1。

返回值:执行DECR命令之后key的值。

实例1:对存在的key执行DECR命令:

127.0.0.1:6379> SET age 23 
OK 
127.0.0.1:6379> DECR age 
(integer) 22 

实例2:对不存在的key执行DECR命令:

127.0.0.1:6379> EXISTS count 
(integer) 0 
127.0.0.1:6379> DECR count 
(integer) -1 

实例3:对存在但不是数值的key执行DECR命令:

127.0.0.1:6379> SET name "xinping" 
OK 
127.0.0.1:6379> DECR company 
(error) ERR value is not an integer or out of range

14、DECRBY

DECRBY命令的基本语法如下:

DECRBY key decrement

DECRBY用于将key所存储的值减去减量decrement,也就是指定数值。如果key不存在,则以0为key的初始值,然后执行DECRBY命令。

返回值:减去减量之后key的值。

实例1:对存在的key执行DECRBY命令:

127.0.0.1:6379> SET count 100 
OK 
127.0.0.1:6379> DECRBY count 20 
(integer) 80

也可以通过INCRBY一个负值来实现同样的效果:

127.0.0.1:6379> GET count 
"80" 
127.0.0.1:6379> INCRBY count  -20 
(integer) 60 
127.0.0.1:6379> GET count 
"60" 

实例2:对不存在的key执行DECRBY命令:

127.0.0.1:6379> EXISTS pages 
(integer) 0 
127.0.0.1:6379> DECRBY pages 10 
(integer) -10

15、INCR

INCR命令的基本语法如下:

INCR key

INCR用于将key中存储的数值增1。如果key不存在,则以0为key的初始值,然后执行INCR命令,设置key为1。

返回值:执行INCR命令之后key的值。

实例如下:

127.0.0.1:6379> SET age 20
OK 
127.0.0.1:6379> INCR age 
(integer) 21 
127.0.0.1:6379> GET age 
"21"

16、INCRBY

INCRBY命令的基本语法如下:

INCRBY key increment

INCRBY用于将key所存储的值加上增量increment。
如果key不存在,则以0为key的初始值,然后执行INCRBY命令。

返回值:加上增量之后key的值。

实例1:key存在且是数字:

127.0.0.1:6379> SET age 21 # 设置age为21 
OK 
127.0.0.1:6379> INCRBY age 5 # 给age加上5 
(integer) 26 
127.0.0.1:6379> GET age 
"26" 

实例2:key不存在:

127.0.0.1:6379> EXISTS counter 
(integer) 0 
127.0.0.1:6379> INCRBY counter 30 
(integer) 30 
127.0.0.1:6379> GET counter 
"30"

实例3:key不是数字,那么返回一个错误:

127.0.0.1:6379> SET book "how to master redis" 
OK 
127.0.0.1:6379> INCRBY book 100 
(error) ERR value is not an integer or out of range

3.2、Hash类型

Redis的Hash类型是一个String类型的域(field)和value的映射表,Hash类型特别适用于存储对象,例如Username、Password和Age等。

Redis中的每个Hash类型数据都可以存储2^32-1个field-value对。

1、HSET

HSET命令的基本语法如下:

HSET key field value

HSET用于将散列表key中的field的值设置为value。

返回值:如果散列表key中的field不存在并且设置成功,则返回1;如果散列表key中的field已经存在并且新值覆盖了旧值,则返回0。

实例如下:

127.0.0.1:6379> HSET user name "xinping"          # 创建一个新域 
(integer) 1 
127.0.0.1:6379> HSET user name "wangwu"           # 覆盖一个旧域 
(integer) 0 

2、HSETNX

HSETNX命令的基本语法如下:

HSETNX key field value

HSETNX用于将散列表key中的field的值设置为value。如果key不存在,那么一个新散列表将被创建并执行HSETNX命令,先创建key。NX是Not Exist的意思。如果field已经存在,则返回0,该命令无效。

返回值:如果设置field成功,则返回1;如果field已经存在,则返回0。

实例如下:

127.0.0.1:6379> HSETNX nosql name "redis" 
(integer) 1 
127.0.0.1:6379> HSETNX nosql name "redis"        # 命令无效,name已存在 
(integer) 0

3、HMSET

HMSET命令的基本语法如下:

HMSET key field value [field value ...]

HMSET用于同时将多个field-value对设置到散列表key中,此命令会覆盖散列表中已存在的field。

返回值:如果命令执行成功,则返回OK。

实例1:将多个field-value对设置到散列表key中:

127.0.0.1:6379> HMSET website taobao "www.taobao.com" jd "www.jd.com" 
OK 
127.0.0.1:6379> HGET website taobao 
"www.taobao.com" 
127.0.0.1:6379> HGET website jd 
"www.jd.com"

实例2:将String类型转为Hash类型时,会出现类型转换错误:

127.0.0.1:6379> SET user 20 
OK 
127.0.0.1:6379> HMSET user name wangwu age 21 
(error) WRONGTYPE Operation against a key holding the wrong kind of value

4、HGET

HGET命令的基本语法如下:

HGET key field

HGET用于返回散列表key中field的值。

返回值:field的值。当field不存在或是key不存在时,返回nil。

实例如下:

127.0.0.1:6379> HMSET user name "xinping" age 25 
OK 
127.0.0.1:6379> HGET user name 
"xinping" 
127.0.0.1:6379> HGET user age 
"25" 
127.0.0.1:6379> HGET user address 
(nil) 

由于散列表key中没有address,因此取到的是nil。

5、HMGET

HMGET命令的基本语法如下:

HMGET key field [field ...]

HMGET用于返回散列表key中一个或多个field的值。

返回值:一个或多个给定field的值。

实例如下:

127.0.0.1:6379> HMSET pet dog "wangwang" cat "miaomiao" # 一次在散列表中保存多个值 
OK 
127.0.0.1:6379> HMGET pet dog cat fake_pet # 返回值的顺序和传入参数的顺序一样 
1) "wangwang" 
2) "miaomiao" 
3) (nil)

由于散列表key中没有fake_pet,因此取到的是nil。

6、HGETALL

HGETALL命令的基本语法如下:

HGETALL key

HGETALL用于返回散列表key中所有的域和值。在返回值里,紧跟每个域名(Field Name)之后的是域的值,所以返回值的长度是散列表长度的两倍。

返回值:以列表形式返回散列表key的域和值。若key不存在,则返回空列表(Empty List)。

实例如下:

127.0.0.1:6379> HSET hash_name jd "www.jd.com" 
(integer) 1 
127.0.0.1:6379> HSET hash_name taobao "www.taobao.com" 
(integer) 1 
127.0.0.1:6379> HGETALL hash_name 
1) "jd"                 # 域 
2) "www.jd.com"         # 值 
3) "taobao"             # 域 
4) "www.taobao.com"     # 值

7、HDEL

HDEL命令的基本语法如下:

HDEL key field [field ...]

HDEL用于删除散列表key中的一个或多个field,不存在的field将被忽略。

返回值:被成功删除的field的数量。

实例如下:

# 设置散列表的测试数据 
127.0.0.1:6379> HMSET abbr a "apple" b "banana" c "cat" d "dog" 
OK 
127.0.0.1:6379> HGETALL abbr 
1) "a" 
2) "apple" 
3) "b" 
4) "banana" 
5) "c" 
6) "cat" 
7) "d" 
8) "dog" 
 
# 删除单个field 
127.0.0.1:6379> HDEL abbr a 
(integer) 1 
 
# 删除不存在的field 
127.0.0.1:6379> HDEL abbr not-exists-field 
(integer) 0 
 
# 删除多个field 
127.0.0.1:6379> HDEL abbr b c 
(integer) 2 
 
127.0.0.1:6379> HGETALL abbr 
1) "d" 
2) "dog" 

8、HLEN

HLEN命令的基本语法如下:

HLEN key 

HLEN用于返回散列表key中field的数量。

返回值:散列表key中field的数量。当key不存在时,返回0。

实例如下:

127.0.0.1:6379> HSET user name "xinping" 
(integer) 1 
127.0.0.1:6379> HSET user age 25 
(integer) 1 
127.0.0.1:6379> HLEN user 
(integer) 2

9、HEXISTS

HEXISTS命令的基本语法如下:

HEXISTS key field

HEXISTS用于查看散列表key中field是否存在。

返回值:查看散列表key中,field如果存在则返回1,如果不存在则返回0。

实例如下:

127.0.0.1:6379> HEXISTS phone brand 
(integer) 0 
 
127.0.0.1:6379> HSET phone brand "xiaomi" 
(integer) 1 
 
127.0.0.1:6379> HEXISTS phone brand 
(integer) 1

10、HINCRBY

HINCRBY命令的基本语法如下:

HINCRBY key field increment

HINCRBY用于将散列表key中的field的值加上增量increment。增量increment可以是负数,即对field进行减法操作。

返回值:执行HINCRBY命令之后,散列表key中field的值。

实例1:给指定的field加上正数:

127.0.0.1:6379> HEXISTS page counter 
(integer) 0 
127.0.0.1:6379> HINCRBY page counter 20 
(integer) 20 
127.0.0.1:6379> HGET page counter 
"20"

实例2:给指定的field加上负数:

127.0.0.1:6379> HGET counter page_view 
"200" 
 
127.0.0.1:6379> HINCRBY counter page_view -50 
(integer) 150 
 
127.0.0.1:6379> HGET counter page_view 
"150"

实例3:尝试对字符串值的field执行HINCRBY命令:

127.0.0.1:6379> HSET user name "xinping"       # 对field设定一个字符串值 
(integer) 1 
127.0.0.1:6379> HGET user name 
"xinping" 
127.0.0.1:6379> HINCRBY user name 1            # 命令执行失败,错误 
(error) ERR hash value is not an integer 
127.0.0.1:6379> HGET user name                 # 原值不变 
"xinping"

11、HKEYS

HKEYS命令的基本语法如下:

HKEYS key

HKEYS用于返回散列表key中的所有域。

返回值:一个列表,该列表包含散列表key中的所有域。当key不存在时,返回一个空列表。

实例:返回散列表key中的所有域:

127.0.0.1:6379> HMSET website jd "www.jd.com"  taobao "www.taobao.com" 
OK 
127.0.0.1:6379> HKEYS website 
1) "jd" 
2) "taobao"

散列表website中有两个域。

12、HVALS

HVALS命令的基本语法如下:

HVALS key

HVALS用于返回散列表key中的所有值。

返回值:当散列表key存在时,返回一个列表,该列表包含散列表key中的所有值;当散列表key不存在时,返回一个空列表。

实例:返回散列表key中的所有值:

127.0.0.1:6379> HMSET website jd "www.jd.com"  taobao "www.taobao.com" 
OK 
127.0.0.1:6379> HVALS website 
1) "www.jd.com" 
2) "www.taobao.com"

3.3、List类型

在Redis中,List类型是按照元素的插入顺序排序的字符串列表。在插入时,如果key并不存在,Redis将为该key创建一个新的列表。List类型中可以包含的最大元素数量是4 294 967 295。

1、LPUSH

LPUSH命令的基本语法如下:

LPUSH key value [value ...]

LPUSH用于将一个或多个value插入列表key的表头,可以作为栈,特点是先进后出。

返回值:执行LPUSH命令后,列表key的长度。

实例:对空列表执行LPUSH命令:

127.0.0.1:6379> DEL mykey                 # 删除一个key为mykey的列表 
(integer) 0 
127.0.0.1:6379> LPUSH mykey a 
(integer) 1 
127.0.0.1:6379> LPUSH mykey b 
(integer) 2 
127.0.0.1:6379> LPUSH mykey c 
(integer) 3
127.0.0.1:6379> LPUSH mykey d 
(integer) 4

使用LPUSH将3个值插入名为mykey的列表当中,也可以一次插入多个值到列表,效果是一样的。

127.0.0.1:6379> DEL mykey 
(integer) 1 
127.0.0.1:6379> LPUSH mykey a b c d 
(integer) 4

2、LPUSHX

LPUSHX命令的基本语法如下:

LPUSHX key value

LPUSHX用于将value插入key,key存在并且是一个列表。和LPUSH命令相反,当key不存在时,LPUSHX什么也不做。

返回值:执行LPUSHX命令之后,列表key的长度。

实例1:对空列表执行LPUSHX命令:

127.0.0.1:6379> LLEN mylist       # mylist是一个空列表 
(integer) 0 
127.0.0.1:6379> LPUSHX mylist 1   # 尝试执行LPUSHX命令,失败,因为列表为空 
(integer) 0

实例2:对非空列表执行LPUSHX命令:

127.0.0.1:6379> LPUSH mylist 1    # 先用LPUSH创建一个有一个元素的列表 
(integer) 1 
127.0.0.1:6379> LPUSHX mylist 2   # 这次LPUSHX命令执行成功 
(integer) 2 
127.0.0.1:6379> LRANGE mylist 0 -1 
1) "2" 
2) "1"

3、RPUSH

RPUSH命令的基本语法如下:

RPUSH key value [value ...]

RPUSH用于将一个或多个value插入列表key的表尾,可以作为队列,特点是先进先出。

实例如下:

# 删除已经存在的key(mylist) 
127.0.0.1:6379> DEL mylist 
(integer) 1 
 
# 添加单个元素 
127.0.0.1:6379> RPUSH  mylist 1 
(integer) 1 
 
# 添加重复元素 
127.0.0.1:6379> RPUSH mylist 2 
(integer) 2
# 列表允许重复元素 
127.0.0.1:6379> LRANGE mylist 0 -1 
1) "1" 
2) "2" 
 
# 添加多个元素 
127.0.0.1:6379> LPUSH mylist a b c 
(integer) 5 
 
127.0.0.1:6379> LRANGE mylist 0 -1 
1) "c" 
2) "b" 
3) "a" 
4) "1" 
5) "2"

4、RPUSHX

RPUSHX命令的基本语法如下:

RPUSHX key value

RPUSHX用于将value插入列表key的表尾,并且列表key存在。和RPUSH相反,当key不存在时,RPUSHX什么也不做。

返回值:执行RPUSHX命令之后,列表key的长度。

实例1:key不存在:

127.0.0.1:6379> LLEN greet 
(integer) 0 
 
127.0.0.1:6379> RPUSHX greet "hello"  # 对不存在的key执行RPUSHX命令,失败 
(integer) 0

实例2:key存在且是一个非空列表:

127.0.0.1:6379> RPUSH greet "hi"  # 先用RPUSH插入一个元素 
(integer) 1 
 
127.0.0.1:6379> RPUSHX greet "hello"  # greet现在是一个列表类型,执行RPUSHX命令成功 
(integer) 2 
 
127.0.0.1:6379> LRANGE greet 0 -1 
1) "hi" 
2) "hello"

5、LPOP

LPOP命令的基本语法如下:

LPOP key

LPOP用于从列表key的头部删除元素,并返回删除元素。

返回值:列表key的头元素。当key不存在时,返回nil。

实例如下:

127.0.0.1:6379> LLEN course
(integer) 0 
127.0.0.1:6379> RPUSH course java 
(integer) 1 
127.0.0.1:6379> RPUSH course python 
(integer) 2 
127.0.0.1:6379> LRANGE course  0 -1 
1) "java" 
2) "python" 
# 删除列表的头元素 
127.0.0.1:6379> LPOP course 
"java" 
127.0.0.1:6379> LRANGE course 0 -1 
1) "python"

6、RPOP

RPOP命令的基本语法如下:
RPOP用于从列表key的尾部删除元素,并返回删除元素。

返回值:列表key的尾元素。当key不存在时,返回nil。

实例如下:

127.0.0.1:6379> LLEN mylist 
(integer) 0 
127.0.0.1:6379> RPUSH mylist "one" 
(integer) 1 
127.0.0.1:6379> RPUSH mylist "two" 
(integer) 2 
127.0.0.1:6379> RPUSH mylist "three" 
(integer) 3 
# 返回被删除的元素 
127.0.0.1:6379> RPOP mylist   
"three" 
# 列表剩下的元素 
127.0.0.1:6379> LRANGE mylist 0 -1   
1) "one" 
2) "two"

7、LLEN

LLEN命令的基本语法如下:

LLEN key

LLEN用于返回列表key的长度。

如果key不存在,则key被解释为一个空列表,返回0。如果key不是List类型,返回一个错误。

返回值:列表key的长度。

实例:返回非空列表的长度:

127.0.0.1:6379> LPUSH course "java" 
(integer) 1 
127.0.0.1:6379> LPUSH course "python"
(integer) 2 
127.0.0.1:6379> LLEN course 
(integer) 2

8、LREM

LREM命令的基本语法如下:

LREM key count value

LREM用于从列表key中删除count个和value相等的元素。

ount的值可以是以下几种:

  • count>0:从列表的表头开始向表尾遍历,删除与value相等的元素,数量为count。
  • count<0:从列表的表尾开始向表头遍历,删除与value相等的元素,数量为count。
  • count=0:删除列表中所有与value相等的元素。

返回值:被删除元素的数量。

因为不存在的key被视作空列表,所以当key不存在时,LREM总是返回0。实例如下:

# 先创建一个列表,元素排列如下 
# morning hello morning hello morning 
 
127.0.0.1:6379> LPUSH greet "morning" 
(integer) 1 
127.0.0.1:6379> LPUSH greet "hello" 
(integer) 2 
127.0.0.1:6379> LPUSH greet "morning" 
(integer) 3 
127.0.0.1:6379> LPUSH greet "hello" 
(integer) 4 
127.0.0.1:6379> LPUSH greet "morning" 
(integer) 5 
 
# 查看所有元素 
127.0.0.1:6379> LRANGE greet 0 4  
1) "morning" 
2) "hello" 
3) "morning" 
4) "hello" 
5) "morning" 
 
# 删除从表头到表尾最先发现的两个morning 
127.0.0.1:6379> LREM greet 2 morning   
(integer) 2       # 两个元素被删除 
 
# 还剩3个元素 
127.0.0.1:6379> LLEN greet   (integer) 3 
 
127.0.0.1:6379> LRANGE greet 0 2 
1) "hello" 
2) "hello" 
3) "morning"

count<0时,按从表尾到表头的顺序删除元素,具体如下:

# 删除从表尾到表头的元素,第一个是morning 
127.0.0.1:6379> LREM greet -1 morning   
(integer) 1 
 
127.0.0.1:6379> LLEN greet 
(integer) 2

count=0时,删除全部元素,具体如下:

127.0.0.1:6379> LRANGE greet 0 1 
1) "hello" 
2) "hello" 
 
# 删除列表中所有hello 
127.0.0.1:6379> LREM greet 0 hello   
(integer) 2       # 两个hello被删除 
 
127.0.0.1:6379> LLEN greet 
(integer) 0 

9、LSET

LSET命令的基本语法如下:

LSET key index value

LSET用于设置列表key中指定索引的元素值,索引从0开始计数。

返回值:执行成功则返回OK,否则返回错误信息。

实例1:对空列表(key不存在)执行LSET命令:

127.0.0.1:6379> EXISTS list 
(integer) 0 
127.0.0.1:6379> LSET list 0 one 
(error) ERR no such key

实例2:对非空列表执行LSET命令:

127.0.0.1:6379> LPUSH list "one" 
(integer) 1 
127.0.0.1:6379> LPUSH list "two" 
(integer) 2 
127.0.0.1:6379> LRANGE list 0 -1 
1) "two" 
2) "one" 
127.0.0.1:6379> LSET list 0 "three" 
OK 
127.0.0.1:6379> LRANGE list 0 -1 
1) "three" 
2) "one"

实例3:索引超出范围:

127.0.0.1:6379> LLEN list # 列表长度为2 
(integer) 2 
127.0.0.1:6379> LSET 3 "three" 
(error) ERR wrong number of arguments for 'lset' command

10、LTRIM

LTRIM命令的基本语法如下:

LTRIM key start stop

LTRIM用于对列表key进行修剪,让列表key只保留指定区间内的元素,不在列表key指定区间之内的元素都将被删除。举个例子,执行命令LTRIM list 0 2,表示只保留列表list的前3个元素,其余元素全部被删除。

返回值:命令执行成功时,返回OK。

实例1:一般情况下的索引:

# 建立一个4个元素的列表 
127.0.0.1:6379> RPUSH list2 1 
(integer) 1 
127.0.0.1:6379> RPUSH list2 2 
(integer) 2 
127.0.0.1:6379> RPUSH list2 3 
(integer) 3 
127.0.0.1:6379> RPUSH list2 4 
(integer) 4 
# 删除索引为0的元素 
127.0.0.1:6379> LTRIM list2 1 -1 
OK 
# “1”被删除 
127.0.0.1:6379> LRANGE list2 0 -1 
1) "2" 
2) "3" 
3) "4"

实例2:stop比元素的最大索引要大:

127.0.0.1:6379> DEL list2 
(integer) 1 
127.0.0.1:6379> RPUSH list2 1 
(integer) 1 
127.0.0.1:6379> RPUSH list2 2 
(integer) 2 
127.0.0.1:6379> RPUSH list2 3 
(integer) 3 
127.0.0.1:6379> RPUSH list2 4 
(integer) 4 
127.0.0.1:6379> LTRIM list2 1 100 
OK 
127.0.0.1:6379> LRANGE list2 0 -1 
1) "2" 
2) "3" 
3) "4"

实例3:start和stop都比最大索引要大,且start<stop:

# 整个列表被清空,等同于DEL list2 
127.0.0.1:6379> LTRIM list2 100 200
OK 
127.0.0.1:6379> LRANGE list2 0 -1 
(empty list or set)

实例4:start>stop:

# 新建一个列表list2 
127.0.0.1:6379> DEL list2 
(integer) 1 
127.0.0.1:6379> RPUSH list2 1 
(integer) 1 
127.0.0.1:6379> RPUSH list2 2 
(integer) 2 
127.0.0.1:6379> RPUSH list2 3 
(integer) 3 
127.0.0.1:6379> RPUSH list2 4 
(integer) 4 
 
# 列表list2同样被清空 
127.0.0.1:6379> LTRIM list2 1000 4 
OK 
127.0.0.1:6379> LRANGE list2 0 -1 
(empty list or set) 
 
127.0.0.1:6379> LRANGE alpha 0 -1 # 再新建一个列表 
1) "h" 
2) "u" 
3) "a" 
4) "n" 
5) "g" 
6) "z"

11、LINDEX

LINDEX命令的基本语法如下:

LINDEX key index 

返回值:列表key中索引为index的元素。

实例如下:

127.0.0.1:6379> RPUSH list3 "a" 
(integer) 1 
127.0.0.1:6379> RPUSH list3 "b" 
(integer) 2 
127.0.0.1:6379> LRANGE list3  0 -1 
1) "a" 
2) "b" 
127.0.0.1:6379> LINDEX list3 0 
"a" 
127.0.0.1:6379> LINDEX list3 -1 
"b" 
# index不在列表list3的区间范围内会返回nil
127.0.0.1:6379> LINDEX list3 3 
(nil)

12、LINSERT

LINSERT命令的基本语法如下:

LINSERT key BEFORE|AFTER pivot value

LINSERT用于将value插入列表key当中,位于pivot之前或之后。

当pivot不存在于列表key时,不执行任何操作。如果key不是List类型,返回一个错误。

返回值:如果执行LINSERT命令成功,则返回执行之后的列表长度;如果没有找到pivot,则返回-1;如果key不存在或为空列表,则返回0。

实例如下:

127.0.0.1:6379> RPUSH mylist "Hello" 
(integer) 1 
127.0.0.1:6379> RPUSH mylist "World" 
(integer) 2 
 
127.0.0.1:6379> LINSERT mylist BEFORE "World" "There" 
(integer) 3 
 
127.0.0.1:6379> LRANGE mylist 0 -1 
1) "Hello" 
2) "There" 
3) "World" 
 
# 对一个非空列表插入,查找一个不存在的pivot 
127.0.0.1:6379> LINSERT mylist BEFORE "go" "let's"   
(integer) -1    # 失败 
 
127.0.0.1:6379> EXISTS fake_list  # 对一个空列表执行LINSERT命令 
(integer) 0 
 
127.0.0.1:6379> LINSERT fake_list BEFORE "none" "a" 
(integer) 0 # 失败

13、RPOPLPUSH

RPOPLPUSH命令的基本语法如下:

RPOPLPUSH source destination

RPOPLPUSH用于将元素从第一个列表的表尾移动到第二个列表的表头,并返回被移除的元素。整个操作是原子性的,如果第一个列表是空或者不存在则返回nil。

举个例子,有两个列表source和destination,列表source有元素a、b、c,列表destination有元素x、y、z,执行RPOPLPUSH source destination之后,列表source包含元素a、b,列表destination包含元素c、x、y、z,并且元素c被返回。如果列表source不存在,则返回nil,并且不执行其他操作。如果列表source和列表destination相同,则列表source中的表尾元素被移动到表头,并返回该元素。

返回值:被移除的元素。

实例如下:

# 生成列表 
127.0.0.1:6379> DEL list1 
(integer) 0 
127.0.0.1:6379> DEL list2 
(integer) 0 
127.0.0.1:6379> RPUSH list1 a 
(integer) 1 
127.0.0.1:6379> RPUSH list1 b 
(integer) 2 
127.0.0.1:6379> RPUSH list1 c 
(integer) 3 
127.0.0.1:6379> RPUSH list1 d 
(integer) 4 
# 查看所有元素 
127.0.0.1:6379> LRANGE list1 0 -1 
1) "a" 
2) "b" 
3) "c" 
4) "d" 
# 情况1:列表source和列表destination不同 
127.0.0.1:6379> RPOPLPUSH list1 list2 
"d" 
127.0.0.1:6379> LRANGE list1 0 -1 
1) "a" 
2) "b" 
3) "c" 
127.0.0.1:6379> LRANGE list2 0 -1 
1) "d" 
# 再执行一次RPOPLPUSH操作,把列表List1的尾部元素、添加到列表List2的头部 
127.0.0.1:6379> RPOPLPUSH list1 list2 
"c" 
127.0.0.1:6379> LRANGE list1 0 -1 
1) "a" 
2) "b" 
127.0.0.1:6379> LRANGE list2 0 -1 
1) "c" 
2) "d" 
 
# 情况2:列表source和列表destination相同 
127.0.0.1:6379> RPOPLPUSH list1 list1 
"b" 
# 把列表list1原来的表尾元素“c”放到表头 
127.0.0.1:6379> LRANGE list1 0 -1 
1) "c" 
2) "d"

3.4、Set类型

Redis的Set类型是String类型的无序集合。集合中的元素是唯一的,不能出现重复的元素。

1、SADD

SADD key member [member ...]

SADD用于将一个或多个member加入集合key当中。假如key不存在,则创建一个只包含member的集合。当key不是set类型时,返回一个错误。

返回值:被添加到集合key中的新元素的数量。

实例如下:

# 添加单个元素 
127.0.0.1:6379> SADD letter a 
(integer) 1 
 
# 添加重复元素 
127.0.0.1:6379> SADD letter a 
(integer) 0 
 
# 添加多个元素 
127.0.0.1:6379> SADD letter b c 
(integer) 2 
 
# 查看集合 
127.0.0.1:6379> SMEMBERS letter 
1) "c" 
2) "b" 
3) "a"

本例中,我们向集合letter中添加3个元素,但是重复元素a没有添加成功,最后用SMEMBERS查看集合的所有元素。

2、SREM

SREM命令的基本语法如下:

SREM key member [member ...]

SREM用于删除集合key中的一个或多个member,如果member不存在则会被忽略。当key不是Set类型时,返回一个错误。

返回值:执行SREM命令成功后,返回集合key中被成功删除的元素数量。

实例如下:

# 添加测试元素 
127.0.0.1:6379> SADD myset "one" 
(integer) 1 
127.0.0.1:6379> SADD myset "two" 
(integer) 1 
127.0.0.1:6379> SADD myset "three" 
(integer) 1 
127.0.0.1:6379> 
127.0.0.1:6379> SMEMBERS myset 
1) "three" 
2) "two"
3) "one" 
 
# 删除单个元素 
127.0.0.1:6379> SREM myset "one" 
(integer) 1 
 
# 删除不存在的元素 
127.0.0.1:6379> SREM myset "none" 
(integer) 0 
 
# 删除多个元素 
127.0.0.1:6379> SREM myset three two 
(integer) 2 
127.0.0.1:6379> SMEMBERS myset 
(empty list or set)

本例中,我们先向集合myset中添加了3个元素,再执行SREM命令来删除one和none。由于集合myset中有元素one,因此one被删除,而集合myset中没有none,所以SREM命令执行失败。

3、SMEMBERS

SMEMBERS命令的基本语法如下:

SMEMBERS key

SMEMBERS的返回集合key中的所有元素。

返回值:集合key中的所有元素。

实例1:空集合:

# 不存在的key视为空集合 
127.0.0.1:6379> EXISTS not_exists_key     
(integer) 0 
 
127.0.0.1:6379> SMEMBERS not_exists_key 
(empty list or set)

实例2:非空集合:

127.0.0.1:6379> SADD programming_language python 
(integer) 1 
 
127.0.0.1:6379> SADD programming_language ruby 
(integer) 1 
 
127.0.0.1:6379> SADD programming_language c 
(integer) 1 
 
127.0.0.1:6379> SMEMBERS programming_language 
1) "c" 
2) "ruby" 
3) "python"

4、SCARD

SCARD命令的基本语法如下:

SCARD key

SCARD返回集合key中元素的数量。

返回值:集合key中元素的数量。当key不存在时,返回0。

实例如下:

127.0.0.1:6379> SADD myset2 a b c 
(integer) 3 
127.0.0.1:6379> SCARD myset2 
(integer) 3 
127.0.0.1:6379> SMEMBERS myset2 
1) "c" 
2) "b" 
3) "a"

5、SMOVE

SMOVE命令的基本语法如下:

SMOVE source destination member

SMOVE用于将member从集合source移动到集合destination,也就是从第一个集合中删除member并添加到第二个对应集合中。SMOVE命令是原子性操作。如果集合source不存在,则SMOVE不执行任何操作,仅返回0。否则member从集合source中被删除,并添加到集合destination中。当集合destination已经包含member时,SMOVE只是简单地将集合source中的member删除。当source或destination不是Set类型时,返回一个错误。

返回值:如果member被成功删除,那么返回1;如果member不是集合source的元素,并且没有任何对集合destination的操作,那么返回0。

实例如下:

127.0.0.1:6379> DEL myset2 
(integer) 1 
127.0.0.1:6379> SADD myset2 a b c 
(integer) 3 
127.0.0.1:6379> SMEMBERS myset2 
1) "c" 
2) "b" 
3) "a" 
127.0.0.1:6379> SMOVE myset2 myset3 a 
(integer) 1 
127.0.0.1:6379> SMEMBERS myset2 
1) "c" 
2) "b" 
127.0.0.1:6379> SMEMBERS myset3 
1) "a"

通过本例可以看到,集合myset2中的元素a被移到集合myset3中了。

6、SPOP

SPOP命令的基本语法如下:

SPOP key

SPOP用于随机返回并删除名称为key的集合中的一个元素。

返回值:被删除的随机元素。当key不存在或key是空集时,返回nil。

实例如下:

127.0.0.1:6379> DEL myset3 
(integer) 1 
127.0.0.1:6379> SADD myset3 "one" 
(integer) 1 
127.0.0.1:6379> SADD myset3 "two" 
(integer) 1 
127.0.0.1:6379> SADD myset3 "three" 
(integer) 1 
127.0.0.1:6379> SPOP myset3 
"one" 
127.0.0.1:6379> SMEMBERS myset3 
1) "three" 
2) "two"

本例中,我们向集合myset3中添加了3个元素后,再执行SPOP命令来随机删除一个元素,可以看到元素one被删除了。

7、SRANDMEMBER

SRANDMEMBER命令的基本语法如下:

SRANDMEMBER key

SRANDMEMBER用于随机返回名称为key的集合中的一个元素,但是不删除元素。

返回值:被选中的随机元素。当key不存在或key是空集时,返回nil。

实例如下:

127.0.0.1:6379> SADD myset4 "a" 
(integer) 1 
127.0.0.1:6379> SADD myset4 "b" 
(integer) 1 
127.0.0.1:6379> SADD myset4 "c" 
(integer) 1 
127.0.0.1:6379> SADD myset4 "d" 
(integer) 1 
127.0.0.1:6379> SMEMBERS myset4 
1) "d" 
2) "c" 
3) "b" 
4) "a" 
 
127.0.0.1:6379> SRANDMEMBER myset4 
"a" 
127.0.0.1:6379> SRANDMEMBER myset4 
"d" 
 
127.0.0.1:6379> SMEMBERS myset4 
1) "d"
2) "c" 
3) "b" 
4) "a"

8、SINTER

SINTER命令的基本语法如下:

SINTER key [key ...]

SINTER用于返回集合key中的交集。

返回值:交集元素的列表。

实例如下:

127.0.0.1:6379> SADD myset4 "a" 
(integer) 1 
127.0.0.1:6379> SADD myset4 "b" 
(integer) 1 
127.0.0.1:6379> SADD myset5 "b" 
(integer) 1 
127.0.0.1:6379> SADD myset5 "c" 
(integer) 1 
127.0.0.1:6379> SMEMBERS myset4 
1) "b" 
2) "a" 
127.0.0.1:6379> SMEMBERS myset5 
1) "c" 
2) "b" 
127.0.0.1:6379> SINTER myset4 myset5 
1) "b"

通过本例的结果可以看出,集合myset4和集合myset5的交集元素b被找出来了。

9、SINTERSTORE

SINTERSTORE命令的基本语法如下:

SINTERSTORE destination key [key ...]

此命令等同于SINTER,但它将结果保存到集合destination,而不是简单地返回结果。

返回值:交集中的元素数量。

实例如下:

127.0.0.1:6379> SADD myset6 "a" 
(integer) 1 
127.0.0.1:6379> SADD myset6 "b" 
(integer) 1 
127.0.0.1:6379> SADD myset7 "b" 
(integer) 1 
127.0.0.1:6379> SADD myset7 "c" 
(integer) 1 
127.0.0.1:6379> SMEMBERS myset6 
1) "b" 
2) "a" 
127.0.0.1:6379> SMEMBERS myset7
1) "c" 
2) "b" 
127.0.0.1:6379> SINTERSTORE myset8 myset6 myset7 
(integer) 1 
127.0.0.1:6379> SMEMBERS myset8 
1) "b"

通过本例的结果我们可以看出,集合myset6和集合myset7的交集被保存到集合myset8中了。

10、SUNION

SUNION命令的基本语法如下:

SUNION key [key ...]

SUNION用于返回所有集合key的并集。不存在的key被视为空集。

返回值:并集元素的列表。

实例如下:

127.0.0.1:6379> DEL myset1 
(integer) 0 
127.0.0.1:6379> DEL myset2 
(integer) 1 
127.0.0.1:6379> SADD myset1 a 
(integer) 1 
127.0.0.1:6379> SADD myset1 b 
(integer) 1 
127.0.0.1:6379> SADD myset2 b 
(integer) 1 
127.0.0.1:6379> SADD myset2 c 
(integer) 1 
127.0.0.1:6379> SUNION myset1 myset2 
1) "c" 
2) "b" 
3) "a"

通过本例的结果可以看出,集合myset1和集合myset2的并集被找出来了。

11、SUNIONSTORE

SUNIONSTORE命令的基本语法如下:

SUNIONSTORE destination key [key ...]

此命令等同于SUNION,但它将结果保存到集合destination,而不是简单地返回结果。如果集合destination已经存在,则将其覆盖。集合destination可以是集合key本身。

返回值:并集中的元素数量。

实例如下:

127.0.0.1:6379> DEL myset1 
(integer) 1 
127.0.0.1:6379> DEL myset2 
(integer) 1 
127.0.0.1:6379> DEl myset3 
(integer) 0
127.0.0.1:6379> SADD myset1 a 
(integer) 1 
127.0.0.1:6379> SADD myset1 b 
(integer) 1 
127.0.0.1:6379> SADD myset2 b 
(integer) 1 
127.0.0.1:6379> SADD myset2 c 
(integer) 1 
127.0.0.1:6379> SUNIONSTORE myset3 myset1 myset2 
(integer) 3 
127.0.0.1:6379> SMEMBERS myset3 
1) "c" 
2) "b" 
3) "a"

通过本例的结果可以看出,集合myset1和集合myset2的并集被保存到集合myset3中了。

12、SDIFF

SDIFF命令的基本语法如下:

SDIFF key [key ...]

SDIFF用于返回集合key的差集。不存在的key被视为空集。

返回值:差集元素的列表。

实例如下:

127.0.0.1:6379> SMEMBERS myset1 
1) "b" 
2) "a" 
127.0.0.1:6379> SMEMBERS myset2 
1) "c" 
2) "b" 
127.0.0.1:6379> SDIFF myset1 myset2 
1) "a"

从这个结果可以看出,集合myset2与集合myset1的差集元素是c。

13、SDIFFSTORE

SDIFFSTORE命令的基本语法如下:

SDIFFSTORE destination key [key ...]

此命令等同于SDIFF,但它将结果保存到集合destination,而不是简单地返回结果。

返回值:差集中的元素数量。

实例如下:

127.0.0.1:6379> DEL myset1 
(integer) 1 
127.0.0.1:6379> DEL myset2
(integer) 1 
127.0.0.1:6379> DEl myset3 
(integer) 1 
127.0.0.1:6379> SADD myset1 a 
(integer) 1 
127.0.0.1:6379> SADD myset1 b 
(integer) 1 
127.0.0.1:6379> SADD myset2 b 
(integer) 1 
127.0.0.1:6379> SADD myset2 c 
(integer) 1 
127.0.0.1:6379> SMEMBERS myset1 
1) "b" 
2) "a" 
127.0.0.1:6379> SMEMBERS myset2 
1) "c" 
2) "b" 
127.0.0.1:6379> SDIFFSTORE myset3 myset1 myset2 
(integer) 1 
127.0.0.1:6379> SMEMBERS myset3 
1) "a"

3.5、Sorted Set类型

Sorted Set类型是Set类型的一个加强版本,它在Set类型的基础上增加了一个顺序属性。这一属性在添加、修改元素的时候可以指定,每次指定后有序集合会自动按新的值调整顺序。

有序集合中的元素是唯一的,但分数(Score)却可以重复。

1、ZADD

ZADD命令的基本语法如下:

ZADD key score member [[score member] [score member] ...]

ZADD用于将一个或多个member和score加入有序集合key当中。

返回值:被成功添加的新元素的数量。

实例如下:

# 添加单个元素 
127.0.0.1:6379> ZADD myzset1 1 "one" 
(integer) 1 
 
# 添加多个元素 
127.0.0.1:6379> ZADD myzset1 2 "two" 3 "three" 
(integer) 2 
 
# 显示有序集合myzset1  
127.0.0.1:6379> ZRANGE myzset1 0 -1 WITHSCORES 
1) "one" 
2) "1" 
3) "two"
4) "2" 
5) "three" 
6) "3"

使用Redis的内存可视化工具Redis Desktop Manager查看有序集合myzset1在Redis中的存储结构,如下图所示:
在这里插入图片描述

# 添加已存在元素,但是改变score 
127.0.0.1:6379> ZADD myzset1 6 "one" 
(integer) 0 
 
127.0.0.1:6379> ZRANGE myzset1 0 -1 WITHSCORES 
1) "two" 
2) "2" 
3) "three" 
4) "3" 
5) "one" 
6) "6"

在本例中,我们向有序集合myzset1中添加了元素one、two和three,并且元素one被设置了两次,那么将以最后一次的设置为准。最后我们将所有元素都显示出来,注意观察元素的score,如下图所示:
在这里插入图片描述

2、ZREM

ZREM命令的基本语法如下:

ZREM key member [member ...]

ZREM用于删除有序集合key中的一个或多个member,不存在的member将被忽略。

返回值:有序集合key中被成功删除的元素数量。

实例如下:

# 生成有序集合测试数据 
127.0.0.1:6379> ZADD myzset2 1 "one" 
(integer) 1 
127.0.0.1:6379> ZADD myzset2 2 "two" 
(integer) 1 
127.0.0.1:6379> ZADD myzset2 3 "three" 
(integer) 1 
127.0.0.1:6379> ZADD myzset2 4 "four" 
(integer) 1 
127.0.0.1:6379> ZRANGE myzset2 0 -1 WITHSCORES 
1) "one" 
2) "1" 
3) "two"
4) "2" 
5) "three" 
6) "3" 
7) "four" 
8) "4" 
 
# 删除单个元素 
127.0.0.1:6379> ZREM myzset2 "two" 
(integer) 1 
127.0.0.1:6379> ZRANGE myzset2 0 -1 
1) "one" 
2) "three" 
3) "four" 
 
# 删除多个元素 
127.0.0.1:6379> ZREM myzset2 one three 
(integer) 2 
127.0.0.1:6379> ZRANGE myzset2 0 -1 
1) "four" 
 
# 删除不存在的元素 
127.0.0.1:6379> ZREM myzset2 "five" 
(integer) 0

3、ZCARD

ZCARD命令的基本语法如下:

ZCARD key

ZCARD用于返回有序集合key中的元素个数。

返回值:当有序集合key存在时,返回有序集合key的元素个数;当有序集合key不存在时,返回0。

实例如下:

# 添加一个元素 
127.0.0.1:6379> ZADD salary 5000 wangwu 
(integer) 1 
 
# 再添加一个元素 
127.0.0.1:6379> ZADD salary 6000 lisi 
(integer) 1 
 
127.0.0.1:6379> ZCARD salary 
(integer) 2 
 
# 对不存在的key执行ZCARD命令 
127.0.0.1:6379> EXISTS non_exists_key  
(integer) 0 
127.0.0.1:6379> ZCARD non_exists_key 
(integer) 0

从本例可以看出,有序集合salary的元素个数是2。

4、ZCOUNT

ZCOUNT命令的基本语法如下:

ZCOUNT key min max

ZCOUNT用于返回有序集合key中score值在min和max之间(默认包括score值等于min或max)的元素数量,也就是返回有序集合key中score值在给定区间的元素数量。

返回值:score值在min和max之间的元素数量。

实例如下:

# 添加有序集合的元素 
127.0.0.1:6379> DEL salary 
(integer) 1 
127.0.0.1:6379> ZADD salary 3000 wangwu 
(integer) 1 
127.0.0.1:6379> ZADD salary 4000 lisi 
(integer) 1 
127.0.0.1:6379> ZADD salary 5000 zhangsan 
(integer) 1 
 
# 显示所有元素及其score值 
127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES 
1) "wangwu" 
2) "3000" 
3) "lisi" 
4) "4000" 
5) "zhangsan" 
6) "5000" 
 
# 计算score值为3000~5000的元素数量 
127.0.0.1:6379> ZCOUNT salary 3000 5000 
(integer) 3 
 
# 计算score值为4000~5000元素数量 
127.0.0.1:6379> ZCOUNT salary 4000 5000 
(integer) 2

5、ZSCORE

ZSCORE命令的基本语法如下:

ZSCORE key member

ZSCORE用于返回有序集合key中member的score值。如果member不是有序集合key的元素,或有序集合key不存在,则返回nil。

返回值:member的score值,以字符串形式表示。

实例如下:

# 显示有序集合中所有元素及其score值 
127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES 
1) "wangwu" 
2) "3000" 
3) "lisi"
4) "4000" 
5) "zhangsan" 
6) "5000" 
 
# 注意score值以字符串形式表示 
127.0.0.1:6379> ZSCORE salary wangwu 
"3000"

在本例中,我们成功地获取了wangwu的score值。

6、ZINCRBY

ZINCRBY命令的基本语法如下:

ZINCRBY key increment member

ZINCRBY用于将有序集合key的member的score值加上增量increment。也可以通过传递一个负数增量increment,让score值减去相应的值。比如ZINCRBY key-5member,就是让member的score值减去5。当key不存在,或member不是key的元素时,ZINCRBY key increment member等同于ZADD key increment member。

返回值:member的新score值,以字符串形式表示。

实例如下:

127.0.0.1:6379> ZSCORE salary wangwu 
"3000" 
127.0.0.1:6379> ZINCRBY salary 5000 wangwu 
"8000" 
127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES 
1) "lisi" 
2) "4000" 
3) "zhangsan" 
4) "5000" 
5) "wangwu" 
6) "8000"

7、ZRANGE

ZRANGE命令的基本语法如下:

ZRANGE key start stop [WITHSCORES]

ZRANGE用于返回有序集合key中指定区间内的元素。

返回值:在指定区间内,带有score值的有序集合key的元素的列表。

实例如下:

127.0.0.1:6379> ZADD salary2 5000 wangwu 
(integer) 1 
127.0.0.1:6379> ZADD salary2 10000 lisi 
(integer) 1 
127.0.0.1:6379> ZADD salary2 3500 zhangsan 
(integer) 1 
 
# 显示整个有序集合元素 
127.0.0.1:6379> ZRANGE salary2 0 -1 WITHSCORES
1) "zhangsan" 
2) "3500" 
3) "wangwu" 
4) "5000" 
5) "lisi" 
6) "10000"

我们查看有序集合salary2,如下图所示:
在这里插入图片描述

# 显示有序集合索引为1~2的元素 
127.0.0.1:6379> ZRANGE salary2 1 2 WITHSCORES 
1) "wangwu" 
2) "5000" 
3) "lisi" 
4) "10000" 
 
# 测试stop超出最大索引时的情况 
127.0.0.1:6379> ZRANGE salary2 0 10 WITHSCORES 
1) "zhangsan" 
2) "3500" 
3) "wangwu" 
4) "5000" 
5) "lisi" 
6) "10000" 
 
# 测试当给定区间不存在时的情况 
127.0.0.1:6379> ZRANGE salary2 10 20 
(empty list or set)

8、ZREVRANGE

ZREVRANGE命令的基本语法如下:

ZREVRANGE key start stop [WITHSCORES]

ZREVRANGE用于返回有序集合key中索引从start到stop的所有元素。其中元素按score值递减(从大到小)排列。

返回值:指定区间内,带有score值(可选)的有序集合key的元素的列表。

实例如下:

# 递增排列有序集合 
127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES 
1) "lisi" 
2) "4000" 
3) "zhangsan" 
4) "5000" 
5) "wangwu" 
6) "8000" 
 
# 递减排列有序集合 
127.0.0.1:6379> ZREVRANGE salary 0 -1 WITHSCORES 
1) "wangwu" 
2) "8000" 
3) "zhangsan" 
4) "5000"
5) "lisi" 
6) "4000"

从本例可以看出,使用ZREVRANGE可以使有序集合salary中的元素按score值递减排列,再取出全部元素。

9、ZREVRANGEBYSCORE

ZREVRANGEBYSCORE命令的基本语法如下:

ZREVRANGEBYSCORE key max min [WITHSCORES] [LIMIT offset count]

ZREVRANGEBYSCORE用于返回有序集合key中score值介于max和min之间(默认包括score值等于max或min)的所有的元素。其中有序集合key中的元素按score值递减排列。

返回值:指定区间内,带有score值的有序集合key的元素的列表。

实例如下:

127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES 
1) "lisi" 
2) "4000" 
3) "zhangsan" 
4) "5000" 
5) "wangwu" 
6) "8000" 
 
# 删除有序集合中score值为4000~5000的元素 
127.0.0.1:6379> ZREMRANGEBYSCORE salary 4000 5000 
(integer) 2 
 
127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES 
1) "wangwu" 
2) "8000"

在本例中,我们将有序集合salary中的元素按score值递减排列,并将score值为4000~5000的元素删除。

10、ZRANK

ZRANK命令的基本语法如下:

ZRANK key member

ZRANK用于返回有序集合key中member的排名。其中有序集合key中的元素按score值递增(从小到大)排列。

返回值:如果member是有序集合key的元素,则返回member的排名;如果member不是有序集合key的元素,则返回nil。

实例如下:

# 显示有序集合中所有元素及其score值 
127.0.0.1:6379> ZADD salary3 5000 wangwu 
(integer) 1 
127.0.0.1:6379> ZADD salary3 10000 lisi 
(integer) 1 
127.0.0.1:6379> ZADD salary3 4000 zhangsan 
(integer) 1
127.0.0.1:6379> ZRANGE salary3 0 -1 WITHSCORES 
1) "zhangsan" 
2) "4000" 
3) "wangwu" 
4) "5000" 
5) "lisi" 
6) "10000" 
 
# 显示lisi的score值的排名,按照从小到大的顺序,则其排名第二 
127.0.0.1:6379> ZRANK salary3 lisi 
(integer) 2

11、ZREVRANK

ZREVRANK命令的基本语法如下:

ZREVRANK key member

ZREVRANK用于返回有序集合key中member的排名。其中有序集合key中的元素按score值递减排列。

排名以0为底,也就是说,score值最大的成员排名为0。

返回值:如果member是有序集合key的元素,则返回member的排名;如果member不是有序集合key的元素,则返回nil。

实例如下:

# 添加有序集合元素 
127.0.0.1:6379> ZADD salary5 3000 wangwu 
(integer) 1 
127.0.0.1:6379> ZADD salary5 10000 lisi 
(integer) 1 
127.0.0.1:6379> ZADD salary5 5000 zhangsan 
(integer) 1 
127.0.0.1:6379> ZRANGE salary5 0 -1 WITHSCORES 
1) "wangwu" 
2) "3000" 
3) "zhangsan" 
4) "5000" 
5) "lisi" 
6) "10000" 
 
# wangwu的score值排第二 
127.0.0.1:6379> ZREVRANK salary5 wangwu 
(integer) 2 
 
# lisi的score值最大 
127.0.0.1:6379> ZREVRANK salary5 lisi 
(integer) 0

在本例中,对有序集salary5中的元素按score值递减排列,lisi是第一个元素,索引是0。

12、ZREMRANGEBYRANK

ZREMRANGEBYRANK命令的基本语法如下:

ZREMRANGEBYRANK key start stop

ZREMRANGEBYRANK用于删除有序集合key中指定区间内的所有元素。区间以索引参数start和stop指出,包含start和stop在内。索引参数start和stop都以0为底,以0表示有序集合key的第一个元素,以1表示有序集合key的第二个元素,其他正数依此类推。也可以使用负数索引,以-1表示最后一个元素,-2表示倒数第二个元素,其他负数依此类推。

返回值:被删除元素的数量。

实例如下:

127.0.0.1:6379> ZRANGE salary5 0 -1 WITHSCORES 
1) "wangwu" 
2) "3000" 
3) "zhangsan" 
4) "5000" 
5) "lisi" 
6) "10000" 
 
# 删除索引为0~1元素 
127.0.0.1:6379> ZREMRANGEBYRANK salary5 0 1 
(integer) 2 
 
# 显示有序集合内所有元素及其score值,有序集合只剩下一个元素 
127.0.0.1:6379> ZRANGE salary5 0 -1 WITHSCORES 
1) "lisi" 
2) "10000"

在本例中,我们将有序集合salary5中的元素按score值递增排列并将索引为0~1的元素删除了。

13、ZREMRANGEBYSCORE

ZREMRANGEBYSCORE命令的基本语法如下:

ZREMRANGEBYSCORE key min max

ZREMRANGEBYSCORE用于删除有序集合key中所有score值介于min和max之间(默认包括score值等于min或max)的元素。

返回值:被删除元素的数量:

实例如下:

# 添加有序集合元素 
127.0.0.1:6379> ZADD salary6 3000 wangwu 
(integer) 1 
127.0.0.1:6379> ZADD salary6 10000 lisi 
(integer) 1 
127.0.0.1:6379> ZADD salary6 5000 zhangsan 
(integer) 1 
 
# 显示有序集合内所有元素及其score值 
127.0.0.1:6379> ZRANGE salary6 0 -1 WITHSCORES 
1) "wangwu" 
2) "3000"
3) "zhangsan" 
4) "5000" 
5) "lisi" 
6) "10000" 
 
# 删除所有score值为2500~5500的元素 
127.0.0.1:6379> ZREMRANGEBYSCORE salary6 2500 5500 
(integer) 2 
 
# 剩下的有序集合元素 
127.0.0.1:6379> ZRANGE salary6 0 -1 WITHSCORES 
1) "lisi" 
2) "10000"

在本例中,我们将有序集合salary6中的元素按score值递增排列,并将score值为2500~5500的元素删除了。

14、ZINTERSTORE

ZINTERSTORE命令的基本语法如下:

ZINTERSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]]  [AGGREGATE SUM|MIN|MAX]

ZINTERSTORE用于计算给定的多个有序集合key的交集,其中有序集合key的数量必须由numkeys参数指定,并将该交集(结果集)存储到集合destination。

返回值:存储到集合destination的结果集的基数。

实例如下:

127.0.0.1:6379> ZADD test1 70 "Li Lei" 
(integer) 1 
127.0.0.1:6379> ZADD test1 70 "Han Meimei" 
(integer) 1 
127.0.0.1:6379> ZADD test1 99.5 "Tom" 
(integer) 1 
 
127.0.0.1:6379> ZADD test2 88 "Li Lei" 
(integer) 1 
127.0.0.1:6379> ZADD test2 75 "Han Meimei" 
(integer) 1 
127.0.0.1:6379> ZADD test2 99.5 "Tom" 
(integer) 1 
 
127.0.0.1:6379> ZINTERSTORE test3 2 test test2 
(integer) 3 
 
# 显示有序集合内所有元素及其score值 
127.0.0.1:6379> ZRANGE test3 0 -1 WITHSCORES   
1) "Han Meimei" 
2) "145" 
3) "Li Lei" 
4) "158" 
5) "Tom" 
6) "199"

15、ZUNIONSTORE

ZUNIONSTORE命令的基本语法如下:

ZUNIONSTORE destination numkeys key [key ...] [WEIGHTS weight [weight ...]]  [AGGREGATE SUM|MIN|MAX]

ZUNIONSTORE用于计算给定的多个有序集合key的并集,其中有序集合key的数量必须由numkeys参数指定,并将该并集(结果集)存储到集合destination。WEIGHTS选项与前面设定的有序集合key对应,key中每一个score都要乘以对应的权重。

AGGREGATE选项指定并集结果的聚合方式:

  • SUM:将所有集合中某一个元素的score值之和作为结果集中该元素的score值。
  • MIN:将所有集合中某一个元素的score值中最小值作为结果集中该元素的score值。
  • MAX:将所有集合中某一个元素score值中最大值作为结果集中该元素的score值。

返回值:存储到集合destination的结果集的基数。

实例如下:

127.0.0.1:6379> ZADD programmer 2000 peter 3500 jack 5000 tom 
(integer) 3 
127.0.0.1:6379> ZADD manager 2000 herry 3500 mary 4000 bob 
(integer) 3 
127.0.0.1:6379> ZRANGE programmer 0 -1 WITHSCORES 
1) "peter" 
2) "2000" 
3) "jack" 
4) "3500" 
5) "tom" 
6) "5000" 
 
127.0.0.1:6379> ZRANGE manager 0 -1 WITHSCORES 
1) "herry" 
2) "2000" 
3) "mary" 
4) "3500" 
5) "bob" 
6) "4000" 
 
# 公司决定给经理(manager)加薪,而不给程序员(programmer)加薪 
127.0.0.1:6379> ZUNIONSTORE salary 2 programmer manager WEIGHTS 1 3   
(integer) 6 
 
127.0.0.1:6379> ZRANGE salary 0 -1 WITHSCORES 
1) "peter" 
2) "2000" 
3) "jack" 
4) "3500" 
5) "tom" 
6) "5000" 
7) "herry" 
8) "6000"
9) "mary" 
10) "10500" 
11) "bob" 
12) "12000"

3.6、Redis HyperLogLog

Redis 2.8.9中添加了HyperLogLog。Redis的HyperLogLog是用来做基数统计的,主要使用场景是海量数据的计算。HyperLogLog的优点是,在输入元素的数量非常多时,计算基数所需的空间总是很小。HyperLogLog只会根据输入元素来计算基数,而不会存储元素本身。基数就是不重复元素的个数。例如数据集{1,3,5,7,5,7,8},那么这个数据集的基数集为{1,3,5,7,8},基数为5。HyperLogLog可以看作一种算法,它提供了不精确的基数计数方案。

HyperLogLog一开始就是为了大数据量的统计而发明的,很适合那种数据量很大,又允许有一点误差的计算,例如页面用户访问量。HyperLogLog提供了不精确的去重技术方案,标准误差是0.81%,这对于页面用户访问量的统计是可以接受的。因为访问量可能非常大,但是访问量统计对准确率要求没那么高,没必要做到绝对准确,HyperLogLog正好符合这种要求,不会占用太多存储空间,同时性能也不错。总之,Redis的HyperLogLog特别适用对海量数据进行统计,对内存占用有要求,并且能够接受一定的错误率的场景。

1、Redis HyperLogLog常用命令

在这里插入图片描述

2、Redis HyperLogLog实例

分别统计页面page1、page2的用户访客数。

# 用户user1,user2,user3访问了页面page1 
127.0.0.1:6379> PFADD page1 user1 
(integer) 1 
127.0.0.1:6379> PFADD page1 user2 
(integer) 1 
127.0.0.1:6379> PFADD page1 user3 
(integer) 1 
127.0.0.1:6379> PFCOUNT page1 
(integer) 3 
# 用户user3,user4访问了页面page2 
127.0.0.1:6379> PFADD page2 user3 user4   
(integer) 1 
127.0.0.1:6379> PFCOUNT page2
(integer) 2

统计两个页面page1和page2的用户访客数,就需要使用PFMERGE命令合并统计了。

127.0.0.1:6379> PFMERGE page1-page2 page1 page2 
OK 
127.0.0.1:6379> PFCOUNT page1-page2 
(integer) 4

从统计结果可以看出,页面page1和page2的访客数为4。

  • 27
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值