Redis五种基本数据类型介绍
五种基本数据类型
参考资料:https://redis.io/docs/latest/commands/
String
简介
-
string,字符串类型,本质是字节数组。包括三种形式:普通字符串;整数字符串;浮点数字符串。
-
特点:
-
二进制安全。任意二进制序列都被视作纯粹的字节数组,可以被正确的存储和读取,不会因为二进制序列中包含特定的值(如零值字节
\0)而进行特殊处理(如截断)。相比之下,c语言字符串以\0作为字符串的结尾,是非二进制安全的。 -
O(1)时间复杂度内获取字符串的字节长度。
-
支持动态扩容。
-
预分配空间机制。
-
兼容c语言字符串。
-
上限为512mb。
-
6.0版本以前这个值在源码中写死。
// v5.0.5 src/t_string.c static int checkStringLength(client *c, long long size) { if (size > 512*1024*1024) { addReplyError(c,"string exceeds maximum allowed size (512MB)"); return C_ERR; } return C_OK; } -
6.0版本(v6.0.7)以后,可通过redis.conf中的
proto-max-bulk-len 512mb进行配置。一般不建议修改,否则可能出现“大key”问题。// v6.0.7 src/t_string.c static int checkStringLength(client *c, long long size) { if (!(c->flags & CLIENT_MASTER) && size > server.proto_max_bulk_len) { addReplyError(c,"string exceeds maximum allowed size (proto-max-bulk-len)"); return C_ERR; } return C_OK; }
-
-
常用命令
-
SET:写入key和string类型的value。(新增或修改)
- 语法:
SET key value [EX seconds|PX milliseconds] [NX|XX] [GET]。EX设置剩余存活时间,单位为秒(PX同理,单位为毫秒)。NX,not exists,表示当key不存在时写入,等同于新增。XX表示当key已经存在时写入,等同于修改。GET表示返回旧值。
- 时间复杂度:O(1)。表示不随 数据库的键数量增长。
- Example:
127.0.0.1:6379> set name rose OK 127.0.0.1:6379> set name lily get "rose" - 语法:
-
GET:获取key的value,value为string类型。
- 语法:
GET key。key不存在则返回nil。 - 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> get name "lily" 127.0.0.1:6379> get age (nil) - 语法:
-
MSET:批量写多个key和string类型的value。
- 语法:
MSET key value [key value ...]。- 注意:
MSET命令没有ex、nx、xx等选项。
- 注意:
- 时间复杂度:O(n)。n表示键值对的数量。
- Example:
127.0.0.1:6379> mset name rose age 22 OK 127.0.0.1:6379> get name "rose" 127.0.0.1:6379> get age "22" - 语法:
-
MGET:批量读取多个key的value,value为string类型。
- 语法:
MGET key [key ...]。 - 时间复杂度:O(n)。n表示键的数量。
- Example:
127.0.0.1:6379> mget name age 1) "rose" 2) "22" - 语法:
-
SETEX:写入key和string类型的value,并设置键值对的剩余存活时间。
- 语法:
SETEX key seconds value。- 等同:
SET key value EX seconds。
- 等同:
- 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> setex name 10 value OK 127.0.0.1:6379> ttl name (integer) 7 127.0.0.1:6379> ttl name (integer) -2 - 语法:
-
SETNX:写入key和string类型的value,且key不存在。相当于新增操作。
- 语法:
SETNX key value。 - 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> setnx name rose (integer) 1 127.0.0.1:6379> setnx name lily (integer) 0 127.0.0.1:6379> get name "rose" - 语法:
-
MSETNX:写入多个key和string类型的value,且key都不存在。相当于批量新增操作。
- 语法:
MSETNX key value [key value ...]。- 由于redis的命令具有原子性,所以当且仅当所有key都不存在时才执行成功,若其中有一个key存在,则该命令执行失败,所有key、value都写入失败。
- 时间复杂度:O(n)。n表示键值对的数目。
- Example:
127.0.0.1:6379> msetnx name rose age 18 (integer) 1 127.0.0.1:6379> msetnx name lily gender female (integer) 0 127.0.0.1:6379> mget name age gender 1) "rose" 2) "18" 3) (nil) - 语法:
-
INCR:value自增1,value为整数字符串。
- 语法:
INCR key。- 若key不存在,则新增key,value为0,然后再自增1。
- 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> get name (nil) 127.0.0.1:6379> incr name (integer) 1 127.0.0.1:6379> get name "1" 127.0.0.1:6379> incr name (integer) 2 127.0.0.1:6379> get name "2" - 语法:
-
INCRBY:value按指定步长自增,value为整数字符串。
- 语法:
INCRBY key increment。- key不存在,则新增key,value为0,再自增increment。
INCRBY key -1等同于DECR key。INCRBY key -5等同于DECRBY key 5。
- 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> incrby name 2 (integer) 2 127.0.0.1:6379> get name "2" 127.0.0.1:6379> incrby name 10 (integer) 12 127.0.0.1:6379> get name "12" 127.0.0.1:6379> incrby name -5 (integer) 7 127.0.0.1:6379> get name "7" - 语法:
-
INCRBYFLOAT:value按指定步长自增,value为浮点数字符串。
- 语法:
INCRBYFLOAT key increment。- key不存在,则处理方式与与
INCR和INCRBY相同。 - increment是浮点数/整数。
- key是浮点数/整数字符串。
- 对比:
INCRBY只能处理整数字符串和整数步长;INCRBYFLOAT可以处理整数/浮点数字符串,以及整数/浮点数步长。
- key不存在,则处理方式与与
- 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> incrbyfloat age 10 "10" 127.0.0.1:6379> get age "10" 127.0.0.1:6379> incrbyfloat age -0.5 "9.5" 127.0.0.1:6379> get age "9.5" - 语法:
-
APPEND:追加写。
- 语法:
APPEND key value。- 若key不存在,则新增key,并设置value为空字符串,再追加写。相当于
SET。
- 若key不存在,则新增key,并设置value为空字符串,再追加写。相当于
- 时间复杂度:O(1)。
- EXample:
127.0.0.1:6379> exists name (integer) 0 127.0.0.1:6379> append name rose (integer) 4 127.0.0.1:6379> get name "rose" 127.0.0.1:6379> append name lily (integer) 8 127.0.0.1:6379> get name "roselily" - 语法:
-
GETRANGE:获取子串。
- 语法:
GETRANGE key start end。- start和end表示字符串下标。值为-1表示最后一个,-2表示倒数第二个。
- 时间复杂度:O(n)。n表示子串长度。
- 时间复杂度描述的是算法的执行时间如何随某个(或某些)特定输入规模的增大而增长。
- 讨论时间复杂度之前,必须先明确输入的“规模变量”。
- Example:
127.0.0.1:6379> getrange name 0 -1 "roselily" 127.0.0.1:6379> getrange name 4 -1 "lily" - 语法:
-
STRLEN:返回字符串值的字节长度。
- 语法:
STRLEN key。 - 时间复杂度:O(1)。
- 底层结构SDS中显式地存储了字符串的字节长度。
- Example:
127.0.0.1:6379> set name rose OK 127.0.0.1:6379> strlen name (integer) 4 127.0.0.1:6379> append name rose (integer) 8 127.0.0.1:6379> strlen name (integer) 8 - 语法:
应用场景
- 缓存对象:将对象序列化为json字符串,存储在string类型。
- 计数器:使用
INCR命令实现计数。 - 分布式锁:
SETNX。 - 存储session信息:将session信息序列化为字符串存储在string类型中。
- 存储小文件:利用二进制安全的特性可以存储任意类型的数据,比如小图标、图片验证码等。
List
简介
-
本质是双向链表,可正向/反向检索。
-
特点:
- 有序。按照插入的顺序构成有序。
- 元素可重复。
常用命令
-
LPUSH:左端添加元素。
-
语法:
LPUSH key element [element ...]。- 返回值为列表中的元素个数。
-
时间复杂度:添加一个元素O(1),添加n个元素O(n)。
-
Example:
127.0.0.1:6379> lpush stus rose lily (integer) 2 127.0.0.1:6379> lpush stus mary jane (integer) 4 127.0.0.1:6379> lrange stus 0 -1 1) "jane" 2) "mary" 3) "lily" 4) "rose" -
-
RPUSH:右端添加元素。
- 语法:
RPUSH key element [element ...]。 - 时间复杂度:O(1)/O(n),n表示元素个数。
- Example:
127.0.0.1:6379> rpush names rose may (integer) 2 127.0.0.1:6379> rpush names lily rachel (integer) 4 127.0.0.1:6379> lrange names 0 -1 1) "rose" 2) "may" 3) "lily" 4) "rachel" - 语法:
-
LPOP:左端弹出元素。
-
语法:
LPOP key [count]。- count表示移除的元素个数,默认为1。
- 返回值为移除的元素。
- 值在键在,值消键亡。
-
时间复杂度:O(1)/O(n),n是移除的元素数。
-
Example:
127.0.0.1:6379> lpush name jane lucy daisy lily susan (integer) 5 127.0.0.1:6379> lrange name 0 -1 1) "susan" 2) "lily" 3) "daisy" 4) "lucy" 5) "jane" 127.0.0.1:6379> lpop name "susan" 127.0.0.1:6379> lpop name 2 1) "lily" 2) "daisy" 127.0.0.1:6379> lrange name 0 -1 1) "lucy" 2) "jane" -
-
RPOP:右端弹出元素。
-
语法:
RPOP key [count]。- count表示移除的元素个数,默认为1。
- 返回值为移除的元素。
- 值在键在,值消键亡。
-
时间复杂度:O(1)/O(n),n是移除的元素个数。
-
Example:
127.0.0.1:6379> lrange nums 0 -1 1) "1" 2) "2" 3) "3" 4) "4" 5) "5" 127.0.0.1:6379> rpop nums "5" 127.0.0.1:6379> rpop nums 2 1) "4" 2) "3" 127.0.0.1:6379> lrange nums 0 -1 1) "1" 2) "2" 127.0.0.1:6379> rpop nums 2 1) "2" 2) "1" 127.0.0.1:6379> exists nums (integer) 0 -
-
BLPOP:从左端阻塞式弹出元素。
-
语法:
BLPOP key [key ...] timeout。- 列表中有值,则弹出;无值,则阻塞连接,直到有值弹出或超时。
- timeout是阻塞等待的秒数。
- 返回值为被移除元素的键值。
-
时间复杂度:O(1)。
-
Example:
127.0.0.1:6379> lpush name lily rose (integer) 2 127.0.0.1:6379> blpop name 0 1) "name" 2) "rose" 127.0.0.1:6379> blpop name 5 1) "name" 2) "lily" 127.0.0.1:6379> blpop name 5 (nil) (5.06s) -
-
BRPOP:从右端阻塞式弹出元素。
-
语法:
BRPOP key [key ...] timeout。- 有值就弹,无值等待。
- timeout是等待秒数。
- 返回值为被移除元素的键和值。
-
时间复杂度:O(1)。
-
Example:
127.0.0.1:6379> lpush nums 1 2 3 (integer) 3 127.0.0.1:6379> lrange nums 0 -1 1) "3" 2) "2" 3) "1" 127.0.0.1:6379> brpop nums 0 1) "nums" 2) "1" 127.0.0.1:6379> brpop nums 0 1) "nums" 2) "2" 127.0.0.1:6379> brpop nums 0 1) "nums" 2) "3" 127.0.0.1:6379> brpop nums 2 (nil) (2.08s) 127.0.0.1:6379> exists nums (integer) 0 -
-
LRANGE:返回指定下标区间内的元素。
- 语法:
LRANGE key start stop。- start/stop表示元素下标,左端从0开始。-1表示最后一个元素,-2表示倒数第二个元素。
- 返回列表中下标区间为[start, stop]的全部元素。
- 时间复杂度:O(s+n),s表示start的偏移量,n表示返回的元素个数。
- Example:
127.0.0.1:6379> rpush nums 1 2 3 4 5 (integer) 5 127.0.0.1:6379> lrange nums 0 -1 1) "1" 2) "2" 3) "3" 4) "4" 5) "5" 127.0.0.1:6379> lrange nums 0 -2 1) "1" 2) "2" 3) "3" 4) "4" 127.0.0.1:6379> lrange nums 3 -2 1) "4" - 语法:
-
LLEN:获取列表元素个数。
-
语法:
LLEN key。 -
时间复杂度:O(1)。
- list的底层数据结构quicklist中直接存储了列表长度。
-
Example:
127.0.0.1:6379> llen nums (integer) 5 -
-
LINSERT:在指定元素之前/后插入新元素。
-
语法:
LINSERT key <BEFORE | AFTER> pivot element。- before/after表示在pivot之前/之后插入元素。
- pivot是参照的元素值。
- element是插入的新元素。
- 返回值正整数表示插入后的列表长度;返回值为0表示该key不存在;返回值-1表示pivot不存在。
-
时间复杂度:O(n),n表示检索pivot需要遍历的元素个数。
-
Example:
127.0.0.1:6379> linsert nums before "2" "1.5" (integer) 6 127.0.0.1:6379> lrange nums 0 -1 1) "1" 2) "1.5" 3) "2" 4) "3" 5) "4" 6) "5" 127.0.0.1:6379> linsert nums after "4" "4.5" (integer) 7 127.0.0.1:6379> lrange nums 0 -1 1) "1" 2) "1.5" 3) "2" 4) "3" 5) "4" 6) "4.5" 7) "5" -
-
LREM:从左向右或从右向左移除count个特定值的元素。
-
语法:
LREM key count element。- count=0表示移除所有等于element的元素;count>0表示从左向右移除前count个等于element的元素;count<0表示从右向左移除前-count个等于element的元素。
- 返回值为移除元素的个数。
-
时间复杂度:O(n),n表示列表长度。
-
Example:
127.0.0.1:6379> rpush nums 1 2 3 1 1 4 5 1 6 (integer) 9 127.0.0.1:6379> lrange nums 0 -1 1) "1" 2) "2" 3) "3" 4) "1" 5) "1" 6) "4" 7) "5" 8) "1" 9) "6" 127.0.0.1:6379> lrem nums 0 1 (integer) 4 127.0.0.1:6379> lrange nums 0 -1 1) "2" 2) "3" 3) "4" 4) "5" 5) "6" 127.0.0.1:6379> rpush nums2 1 2 3 1 1 4 (integer) 6 127.0.0.1:6379> lrange num2 0 -1 (empty array) 127.0.0.1:6379> lrem nums2 2 1 (integer) 2 127.0.0.1:6379> lrange numsw 0 -1 (empty array) 127.0.0.1:6379> lrange nums2 0 -1 1) "2" 2) "3" 3) "1" 4) "4" 127.0.0.1:6379> rpush nums3 1 2 3 1 1 5 6 1 (integer) 8 127.0.0.1:6379> lrem nums3 -2 1 (integer) 2 127.0.0.1:6379> lrange nums3 0 -1 1) "1" 2) "2" 3) "3" 4) "1" 5) "5" 6) "6" -
-
LSET:修改指定下标的元素值。
-
语法:
LSET key index element。- index是要修改元素的下标。
-
时间复杂度:O(n),n表示index的大小。
-
Example:
127.0.0.1:6379> rpush nums 1 2 3 (integer) 3 127.0.0.1:6379> lset nums 0 1.0 OK 127.0.0.1:6379> lset nums -1 3.0 OK 127.0.0.1:6379> lset nums -2 2.0 OK 127.0.0.1:6379> lrange nums 0 -1 1) "1.0" 2) "2.0" 3) "3.0" -
-
LINDEX:根据下标查找元素。
- 语法:
LINDEX key index。- index表示元素下标。左端从0开始。-1 表示最后一个,-2表示倒数第二个。
- 时间复杂度:O(n),n表示index的大小。
- Example:
127.0.0.1:6379> lrange nums 0 -1 1) "1" 2) "2" 3) "3" 4) "4" 5) "5" 127.0.0.1:6379> lindex nums 0 "1" 127.0.0.1:6379> lindex nums -1 "5" 127.0.0.1:6379> lindex nums 4 "5" 127.0.0.1:6379> lindex nums 2 "3" - 语法:
应用场景
- 栈:出入同侧。LPUSH+LPOP,或RPUSH+RPOP。
- 队列:出入异侧。LPUSH+RPOP,或RPUSH+LPOP。
- 阻塞队列:出入异侧,阻塞弹出。LPUSH+BRPOP,或RPUSH+BLPOP。
- 消息队列。
HASH
简介
- value是哈希表,由多对field value组成。
常用命令
-
HSET:在hash中写入<field, value>。
- 语法:
HSET key field value [field value ...]- 返回值为写入的field数量。
- 时间复杂度:O(1)。(如果有多个<field, value>,则为O(n))。
- Example:
127.0.0.1:6379> hset h1 f1 v1 f2 v2 (integer) 2 127.0.0.1:6379> hget h1 f1 "v1" 127.0.0.1:6379> hget h1 f2 "v2" - 语法:
-
HGET:从hash中获取指定field的value。
- 语法:
HGET key field - 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> hset h1 f1 v1 (integer) 1 127.0.0.1:6379> hget h1 f1 "v1" 127.0.0.1:6379> hget h1 f3 (nil) - 语法:
-
HMSET:在hash中批量写入<field, value>。
- 语法:
HMSET key field value [field value ...]。- 从4.0版本开始,被
HSET代替。
- 从4.0版本开始,被
- 时间复杂度:O(n),n是写入field,value的数量。
- Example:
127.0.0.1:6379> hmset h1 f1 v1 f2 v2 f3 v3 OK 127.0.0.1:6379> hgetall h1 1) "f1" 2) "v1" 3) "f2" 4) "v2" 5) "f3" 6) "v3" - 语法:
-
HMGET:从hash中读取多个field的value。
- 语法:
HMGET key field [field ...]。 - 时间复杂度:O(n),n为field的数量。
- Example:
127.0.0.1:6379> hmget h1 f1 f3 1) "v1" 2) "v3" - 语法:
-
HGETALL:获取hash中所有<field, value>。
- 语法:
HGETALL key。 - 时间复杂度:O(n),n表示hash中的字段数量。
- Example:
127.0.0.1:6379> hgetall h1 1) "f1" 2) "v1" 3) "f2" 4) "v2" 5) "f3" 6) "v3" - 语法:
-
HKEYS:获取hash中所有field。
- 语法:
HKEYS key。 - 时间复杂度:O(n),n表示hash中的字段数量。
- Example:
127.0.0.1:6379> hkeys h1 1) "f1" 2) "f2" 3) "f3" - 语法:
-
HVALS:获取hash中所有value。
- 语法:
HVALS key。 - 时间复杂度:O(n),n表示hash中的字段数量。
- Example:
127.0.0.1:6379> hvals h1 1) "v1" 2) "v2" 3) "v3" - 语法:
-
HSETNX:向hash中新增<field, value>。
- 语法:
HSETNX key field value。- 当且仅当field不存在时才执行成功。
- 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> hgetall h1 1) "f1" 2) "v1" 3) "f2" 4) "v2" 5) "f3" 6) "v3" 127.0.0.1:6379> hsetnx h1 f1 v11 (integer) 0 127.0.0.1:6379> hgetall h1 1) "f1" 2) "v1" 3) "f2" 4) "v2" 5) "f3" 6) "v3" 127.0.0.1:6379> hsetnx h1 f4 v4 (integer) 1 127.0.0.1:6379> hgetall h1 1) "f1" 2) "v1" 3) "f2" 4) "v2" 5) "f3" 6) "v3" 7) "f4" 8) "v4" - 语法:
-
HINCRBY:对value按照指定步长自增。
- 语法:
HINCRBY key field increment。- 返回值为自增后的新值。
- 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> hset h1 f1 5 (integer) 1 127.0.0.1:6379> hget h1 f1 "5" 127.0.0.1:6379> hincrby h1 f1 5 (integer) 10 127.0.0.1:6379> hincrby h1 f1 -2 (integer) 8 - 语法:
-
HEXISTS:判断hash中是否存在某field。
- 语法:
HEXISTS key field。 - 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> hexists h1 f1 (integer) 1 127.0.0.1:6379> hexists h1 f5 (integer) 0 - 语法:
-
HLEN:返回hash中的字段个数。
- 语法:
HLEN key。 - 时间复杂度:O(1)。
- ziplist编码格式下,需要遍历整个hash来获取字段总数。但是由于ziplist保存的字段数目有限,所以可以看作常数级时间复杂度。
- hashtable编码格式下,显式地维护了记录键值对个数的字段。
- Example:
127.0.0.1:6379> hset h1 f1 1 f2 2 f3 3 (integer) 3 127.0.0.1:6379> hlen h1 (integer) 3 - 语法:
应用场景
- 缓存对象:key为对象id,<field, value>存储对象中的字段和值。
- 相比于string类型缓存对象的优点:可以直接查看或修改某一字段的值,而不需要像string类型那样读取整个json字符串的值。
- 计数器组合:利用
HINCRBY命令可以实现多个计数器。 - 配置项管理:利用<field, value>存储配置项。
- 实现可重入的分布式锁:利用
HSETNX加锁,key表示锁的名称,field表示持有者id,value表示计数器,记录加锁次数。
Set
简介
- 集合类型,可看作“只关注key,value为空的哈希表”。
- 特点:
- 无序。
- 元素不可重复。
- 支持集合运算:并、交、差集。
常用命令
-
SADD:向集合中写入元素。
- 语法:
SADD key member [member ...]。 - 时间复杂度:O(1)。(若批量添加多个元素,则为O(n),n是添加的元素个数。)
- Example:
127.0.0.1:6379> sadd s1 1 2 3 (integer) 3 127.0.0.1:6379> smembers s1 1) "1" 2) "2" 3) "3" - 语法:
-
SREM:从集合中删除元素。
- 语法:
SREM key member [member ...]。 - 时间复杂度:O(1)。(若批量删除多个元素,则为O(n)。)
- Example:
127.0.0.1:6379> smembers s1 1) "1" 2) "2" 3) "3" 127.0.0.1:6379> srem s1 3 (integer) 1 127.0.0.1:6379> smembers s1 1) "1" 2) "2" - 语法:
-
SCARD:返回集合元素总数。
-
语法:
SCARD key。- card是Cardinality(基数)的缩写,是集合论的数学术语,表示集合中元素的数量。
-
时间复杂度:O(1)。
- 底层数据结构intset / hashtable中显式地维护了用来记录元素个数的字段。
-
Example:
127.0.0.1:6379> smembers s1 1) "1" 2) "2" 127.0.0.1:6379> scard s1 (integer) 2 -
-
SISMEMBER:判断某元素是否存在。
- 语法:
SISMEMBER key member。 - 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> smembers s1 1) "1" 2) "2" 127.0.0.1:6379> sismember s1 2 (integer) 1 127.0.0.1:6379> sismember s1 3 (integer) 0 - 语法:
-
SMEMBERS:返回集合中所有元素。
- 语法:
SMEMBERS key。 - 时间复杂度:O(n),n表示集合的元素总数。
- Example:
127.0.0.1:6379> smembers s1 1) "1" 2) "2" - 语法:
-
SUNION:求多个集合的并集。
- 语法:
SUNION key [key ...]。 - 时间复杂度:O(n),n表示所有集合的基数之和。
- Example:
127.0.0.1:6379> sadd s1 1 2 3 (integer) 3 127.0.0.1:6379> sadd s2 2 4 5 (integer) 3 127.0.0.1:6379> sunion s1 s2 1) "1" 2) "2" 3) "3" 4) "4" 5) "5" - 语法:
-
SINTER:求多个集合的交集。
-
语法:
SINTER key [key ...]。 -
时间复杂度:最坏的情况是O(m*n),m表示最小的集合基数,n表示集合的数量。
- redis的
SINTER的计算思路是:找到基数最小的集合,作为基准集合;遍历基准集合中的m个元素,每遍历一个元素,就去其他n-1个集合中查找是否存在该元素,若n-1个集合都存在该元素,则将其放入结果集,若有集合中不存在该元素,则跳出循环,继续处理基准集合的下一个元素。
- redis的
-
Example:
127.0.0.1:6379> sadd s1 1 2 3 (integer) 3 127.0.0.1:6379> sadd s2 2 4 5 (integer) 3 127.0.0.1:6379> sinter s1 s2 1) "2" -
-
SDIFF:求多个集合的差集。
-
语法:
SDIFF key [key ...]- SDIFF s1 s2 s3,表示集合s1中存在,s2、s3中不存在的元素集合。
-
时间复杂度:O(n),n是所有集合的基数之和。
- redis的
SDIFF计算思路是:先求出s2...sn的并集;再求s1和并集的差集:遍历s1中的元素,每遍历一个元素,检查并集中是否也存在该元素。???
- redis的
-
Example:
127.0.0.1:6379> sadd s1 1 2 3 4 5 (integer) 5 127.0.0.1:6379> sadd s2 2 5 6 (integer) 3 127.0.0.1:6379> sadd s3 3 7 (integer) 2 127.0.0.1:6379> sdiff s1 s2 s3 1) "1" 2) "4" -
应用场景
- 记录文章点赞数:key为文章id,set中记录每一个点赞用户的id,利用set元素的不可重复特性实现去重。最后通过
SCARD返回点赞数。 - 计算共同关注:通过
SINTER计算用户的共同关注。
Sorted Set
简介
- 有序集合。集合中每个元素关联一个分数score,基于score进行排序。
- 特点:
- 有序。基于score进行升序排列。
- 元素不可重复。
- 支持集合运算:并、交、差集。
常用命令
-
ZADD:向有序集合中写入元素和对应的分数。
- 语法:
ZADD key [NX | XX] [GT | LT] [CH] [INCR] score member [score member...]。- NX:元素不存在时执行。相当于新增。
- XX:元素已存在时执行。相当于修改。
- LT:元素已存在,且新score<旧score时执行。
- GT:元素已存在,且新score>旧score时执行。
- score:member对应的分数。
- member:写入的元素值。
- 时间复杂度:O(logn),n表示有序集合的元素总数。
- 底层数据结构跳表,每次插入元素的时间复杂度为O(logn)。
- Example:
127.0.0.1:6379> zadd z1 10 rose (integer) 1 127.0.0.1:6379> zadd z1 30 lily (integer) 1 127.0.0.1:6379> zrange z1 0 -1 1) "rose" 2) "lily" - 语法:
-
ZREM:从有序集合中移除元素。
- 语法:
ZREM key member [member ...]。 - 时间复杂度:O(logn),n表示有序集合的元素总数。(若批量移除多个元素,则O(m*logn),m是移除的元素个数。)
- Example:
127.0.0.1:6379> zrange z1 0 -1 1) "rose" 2) "lily" 127.0.0.1:6379> zrem z1 rose (integer) 1 127.0.0.1:6379> zrange z1 0 -1 1) "lily" - 语法:
-
ZSCORE:查询有序集合中某元素的分数。
- 语法:
ZSCORE key member。 - 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> zscore z1 lily "30" - 语法:
-
ZCARD:查询有序集合的元素总数。
- 语法:
ZCARD key。 - 时间复杂度:O(1)。
- Example:
127.0.0.1:6379> zadd z2 1 one 2 two 5 five (integer) 3 127.0.0.1:6379> zcard z2 (integer) 3 - 语法:
-
ZCOUNT:返回指定分数区间内的元素数目。
- 语法:
ZCOUNT key min max。 - 时间复杂度:O(logn),n表示有序集合的元素总数。
- Example:
127.0.0.1:6379> zadd z2 1 one 2 two 5 five (integer) 3 127.0.0.1:6379> zcount z2 2 5 (integer) 2 127.0.0.1:6379> zcount z2 -inf +inf (integer) 3 - 语法:
-
ZINCRBY:增加某元素的分数。
- 语法:
ZINCRBY key increment member。 - 时间复杂度:O(logn),n表示有序集合的元素总数。
- Example:
127.0.0.1:6379> zadd z1 1 one 2 two 3 three (integer) 3 127.0.0.1:6379> zincrby z1 3 one "4" 127.0.0.1:6379> zrange z1 0 -1 withscores 1) "two" 2) "2" 3) "three" 4) "3" 5) "one" 6) "4" - 语法:
-
ZRANGE:按照下标区间返回元素。
- 语法:
ZRANGE key start stop [BYSCORE | BYLEX] [REV] [LIMIT offset count] [WITHSCORES]。- BYSCORE:按照分数区间返回元素。
- REV:逆序。
- WITHSCORES:返回值携带分数。
- 时间复杂度:O(logn+m),n表示有序集合的元素总数,m表示返回的元素个数。
- Example:
127.0.0.1:6379> zadd z1 1 one 2 two 3 three 4 four 5 five (integer) 5 127.0.0.1:6379> zrange z1 0 -1 1) "one" 2) "two" 3) "three" 4) "four" 5) "five" 127.0.0.1:6379> zrange z1 0 -1 rev 1) "five" 2) "four" 3) "three" 4) "two" 5) "one" 127.0.0.1:6379> zrange z1 0 1 rev 1) "five" 2) "four" 127.0.0.1:6379> zrange z1 3 5 byscore 1) "three" 2) "four" 3) "five" - 语法:
-
ZUNION/ZINTER/ZDIFF:并、交、差集。
应用场景
- 排行榜:排列对象作为member,排列依据作为score。
- 范围查询。
- 唯一性约束+排序。

浙公网安备 33010602011771号