大家好,欢迎来到IT知识分享网。
Redis是目前最流行的键值对(key-value)数据库,以出色的性能著称,官方提供的数据是可以支持以上的+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修改之后,字符串的长度。
127.0.0.1:6379> SET email "" OK 127.0.0.1:6379> SETRANGE email 9 ".com" (integer) 16 127.0.0.1:6379> GET email ""
实例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 "" OK 127.0.0.1:6379> GET email "" 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 ""
GETRANGE的取值范围不超过实际字符串长度,超过部分会被忽略:
127.0.0.1:6379> GETRANGE email 0 199 ""
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
返回值:加上增量之后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
返回值:列表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。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/154758.html