Redis以K-V的形式存储数据,使用Redis Key有以下几点注意事项:

  • Redis Key不宜过长。Redis的Key是二进制安全的,意味着可以使用任何二进制序列作为Redis的Key,当Redis Key过长时,会增加查询代价、消耗带宽、占用内存空间等缺点。
  • Redis key也不宜过短,Redis Key的命名要符合场景,良好的命名能提升可读性,虽然Redis的短Key会减少内存、带宽消耗,但往往我们要取之均衡的。
  • 当存储复杂的Key我们可以用特殊的符号分割。例如:user:100,又或者id&1,通过这种特殊符号的分割,使得Key能存储更多有用的信息。
  • Redis Key允许的最大密钥大小为512 MB。

    0.Key相关命令

    | command(命令) | explain(说明) | 时间复杂度 | | —- | —- | —- | | set key value [EX seconds|PX milliseconds|KEEPTTL] [NX|XX] | set命令设置key对应的value值,EX为过期时间(单位秒),PX为过期时间(单位毫秒),NX表示仅当key不存在时,set才会生效,XX表示仅当key存在时,set才会生效。[]中的参数是可选的,像EX、PX、NX、XX这些参数是忽略大小写的,比如EX可以写成ex。 | O(1) | | del key [key…] | 删除一个或多个key,操作成功返回1,否则返回0 | O(n) | | exists key [key…] | 判断一个或多个key是否存在,若存在则返回1,否则返回0 | O(n) | | expire key seconds | 给key设置过期时间(单位秒),若key存在操作成功返回1,若key不存在或操作失败返回0 | O(1) | | pexpire key milliseconds | 给key设置过期时间(单位毫秒),与expire命令类似 | O(1) | | expireat key timestamp | 给key设置过期时间,参数是一个unix时间戳,与expire命令类似 | O(1) | | pexpireat key milliseconds-timestamp | 给key设置过期时间 | O(1) | | keys pattern | 查找所有符合给定模式( pattern)的 key,号匹配以xx开头的所有key,例如keys user表示查询以user为前缀的key, | O(1) | | move key db | 将当前数据库的 key 移动到给定的数据库 db 当中 | O(1) | | persist key | 移除key的过期时间,key将持久保持,操作成功返回1,否则返回0 | O(1) | | pttl key | 以毫秒单位返回key的剩余过期时间,如果key不存在或已被删除返回-2,如果key无过期时间则返回-1 | O(1) | | ttl key | 以秒单位返回key的过期时间,类似pttl命名 | O(1) | | randomkey | 当前数据库中随机返回一个 key | O(1) | | rename key newKey | 修改key的名称,操作成功返回1,失败返回0,如果修改的key不存在则会报错 | O(1) | | renamenx key newKey | 仅当 newkey 不存在时,将 key改名为 newkey 。 | O(1) | | type key | 返回key所对应value的类型 | O(1) |
  1. ######### set命令
  2. #set语法,key为键名,value为存储的对应值,EX为过期时间(单位秒),PX为过期时间(单位毫秒),NX表示仅当key不存在时,set才会生效,XX表示仅当key存在时,set才会生效。[]中的参数是可选的,像EX、PX、NX、XX这些参数是忽略大小写的,比如EX可以写成ex。
  3. set key value [EX seconds|PX milliseconds|KEEPTTL] [NX|XX]
  4. #例子1:存储指定key所有对应的value,如果不设置过期时间则永不过期,设置成功redis-cli会打印OK
  5. set name "zxp"
  6. #例子2:存储指定key所有对应的value,使用EX参数指定key的过期时间(单位秒),当超过过期时间时key会自动被清理,过期后获取key的值为nil。下面表示设置key名sex对应的value值为"man"过期时间是3秒
  7. set sex "man" EX 3
  8. #例子3:设置key名为like对应设置为"woman"过期时间为3000毫秒(ms)
  9. set like "woman" px 3000
  10. #例子4:nx参数表示只有key不存在时set命令才会生效
  11. set level "leader" nx #打印OK
  12. set level "manager" nx #打印nil,因为已有相同的key,set命令不生效
  13. #例子5:xx表示只有key存在时,set命令才会生效
  14. set address "shenzheng"
  15. set userNo "u10010" xx #打印nil,因为没有key名为userNo的Key不存在,set命令不生效
  16. set address "dongguan" xx #打印OK
  17. ######### get命令
  18. #get语法
  19. get key
  20. #例子
  21. set name "zfc"
  22. get name #打印zfc
  23. get userName #打印nil,key不存在
  24. ######### del命令
  25. #del语法,del命令用于删除一个或多个key,操作成功返回1,否则返回0
  26. del key [key...]
  27. #例子
  28. set name "zxp"
  29. set address "dongguan"
  30. set like "woman"
  31. #删除一个key
  32. del name
  33. #删除多个key
  34. del address like #打印OK
  35. ######### exists命令
  36. #exists语法,exists命令用于判断key是否存在
  37. exists zxp111 #打印nil
  38. set zxp111 '哈哈哈'
  39. exists zxp111 #打印1
  40. ######### expire命令
  41. #expire语法,seconds为过期时间,单位秒
  42. expire key seconds
  43. #例子为不存在的key设置过期时间
  44. expire x 5 #打印0
  45. #例子为已有key设置过期时间
  46. set y 'y'
  47. expire y 3
  48. ######### pttl命令
  49. #pttl语法,pttl命名用于以毫秒单位返回指定key的剩余过期时间
  50. pttl tt #打印-2,因为不存在这个key
  51. set tt 123 ex 1
  52. pttl tt #这条命令在上条命令执行后1s后执行,打印-1,因为名为tt的key存在但已过期被删除
  53. set yy 123 ex 10
  54. pttl yy #这条命令在上条命令执行后5s后执行,打印5000
  55. ######### rename命令
  56. #rename语法,rename用于修改指定key
  57. rename y1 y2 #error,ERR no such key,没有y1这个key
  58. set y1 123 #OK
  59. rename y1 y2 #OK
  60. get y2 #123

1.String(字符串)

command(命令) explain(说明) 时间复杂度
set key value 为key设置值,操作成功返回1,否则返回0 O(1)
get key 获取key对应的value,如果key不存在则返回nil O(1)
getrange key start end 返回key对应value从start到end范围的字符 O(1)
getset key value 设置key的value并返回key的旧值 O(1)
mget key1 [key2…] 获取一个或多个key的value O(n)
strlen key 返回key所存储字符串的长度 O(1)
mset key value[key value…] 同时设置一个和多个key value对 O(n)
msetnx key value(key value…) 同时设置一个或多个key value对,并且仅当给定的key都不存在 O(n)
setex key seconds value 为key设置对应为value,且key的过期时间为seconds(单位秒) O(1)
psetex key milliseconds value 为key设置对应为value,且key的过期时间为milliseconds(单位毫秒) O(1)
incr key 将key存储的数字值增一 O(1)
incrby key increment 将key存储的数字值增加给定的增量值(increment) O(1)
incrbyfloat key increment 将key存储的数字值增加给定的浮点增量值(increment) O(1)
decr key 将key存储的数字值减一 O(1)
decrby key decrement 将key存储的数字值减去给定的减量值(increment) O(1)
append key value 如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。 O(1)
######getrange命令
#语法:getrange key start end
#作用:返回key对应value从start到end范围的字符
#例子:
set name 'zxp123456'
getrange name 2 5 #打印:"p125",返回'zxp123456'从下标到下标5的字符



#####getset命令
#语法:getset key value
#作用:为key设置值并返回旧值
#例子:
set name "zxp111"
getset name "zxp222" #打印:"zxp111"
get name #打印:"zxp222"


#####mget命令
#语法:mget key1 [key2...]
#作用:获取一个或多个key对应的value
#例子:
set name "zxp666"
set sex "man"
mget name sex #打印:1) "zxp666"        2) "man"



######mset命令
#语法:mset key value[key value...]
#作用:同时设置一个或多个key value对,如果设置key存在那么会覆盖key对应的值
#例子:
mset name "zxp999" sex "woman" #打印:OK
get name #打印:"zxp999"
get sex #打印:"woman"


#######msetnx命令
#语法:msetnx key value(key value...)
#作用:同时设置一个或多个key value对,并且设置的key都不存在
#例子1:设置多个key value,且设置的key不存在
msetnx x 10 y 5  #打印:1
#例子:设置一个或多个key value,且设置的key已经存在
msetnx x 10  #打印:0,说明操作失败


######setex命令
#语法:setex key seconds  value
#作用:为key设置对应的value值,且为key设置过期时间为seconds(单位秒)
#例子:
setex love 10 'zyt' #打印:OK,10秒后love会过期



#####incr命令
#语法:incr key
#作用:为key所存储的数值递增加一,返回递增后的值。
#例子1:key存储的是数值类型,在执行incr命令会将数值做隐式转换
set num 1
incr num #打印:2
get num #打印:"2"

#例子2:key存储的不是数值类型则会执行出错
set num "zz"
incr num #打印:ERR value is not an integer or out of range


######incrby命令
#语法:incrby key increment
#作用:为key所存储的数值增加给定的增量(increment),如果key所存储的value不可以转换为数值,那么执行出错。
#例子:
set num 2 
incrby num 3 #打印:5
get num #打印:"5"


###### decr命令
#语法:decr key
#作用:将key所存储的数值递减一,如果key所存储的value不可以转换为数值,那么执行出错。
#例子:
set num 5
decr num #打印:4
get num #打印:"4"

######decrby命令
#语法:decrby key decrement
#作用:为key所存储的数值减去给定的减量(decrement),如果key所存储的value不可以转换为数值,那么执行出错。
#例子:
set num 5 
decrby num 3 #打印:2
get num #打印:"2"


######append命令
#语法:append key value
#作用:如果key存在且存储是一个字符串值,append命令可以将value追加到key原来值的末尾,并返回追加后内容的长度
#例子:对于已存在的key
set content "zxp111"
append content "zxp222" #打印:12
get content #打印:"zxp111zxp222"

#例子:对于不存在的key使用append命令会先创建一个key对应值为"",然后将value追加到该key对应值的末尾。
append context "zxp" #打印:3
get context #打印:"zxp"

相关命令的应用:
(1).incr、incrby、decr、decrby等命令可以实现计数器。
(2).append可以实现内容追加,例如日志文件内容的追加。

2.Lists(列表)

Redis的Lists是简单字符串的列表,按照插入顺序排序,底层由表链实现,通过Lists数据结构可以实现队列先进先出的存储方式。 | command(命令) | explain(说明) | 时间复杂度 | | —- | —- | —- | | lpush key value1 [value2…] | 将一个或多个值插入到列表的头部,若没有队列则会先创建队列然后再往列表中添加元素,返回列表的长度。 | O(N),N取决于插入值的数量 | | lpushx key value1 [value2…] | 将一个或多个值插入到已存在列表的头部,若没有对应列表执行该命令返回0 | O(N),N取决于插入值的数量 | | rpush key value1 [value2] | 将一个或多个值插入到列表的尾部 | O(N),N取决于插入值的数量 | | rpushx key value1 [value2…] | 将一个或多个值插入到已存在列表的尾部 | O(N),N取决于插入值的数量 | | llen key | 获取列表的长度 | O(1) | | lpop key | 移除并获取列表中的第一个元素 | O(1) | | rpop key | 移除并获取列表中的最后一个元素 | O(1) | | lindex key index | 通过索引获取列表中的元素 | O(1) | | lrange key start stop | 获取列表中从start到stop范围的元素 | O(1) | | lset key index value | 通过索引设置列表中对应元素的值 | O(1) | | linsert key before|after pivot value | 在列表元素前或后添加元素 | O(1) | | ltrim key start stop | 对列表进行裁剪,只保留从start到stop区间范围的元素,不在start到stop区间范围内的元素的都会被删除 | O(1) | | blpop key1 [key2] timeout | 移除一个或多个列表的第一个元素,如果列表中没有元素会阻塞列表直到等待超时时间或发现有可弹出元素为止。 | O(N),N取决于key的数量 | | brpop key1 [key2] timeout | 移除一个或多个列表的最后一个元素,如果列表中没有元素会阻塞列表直到等待超时时间或发现有可弹出元素为止。 | O(N),N取决于key的数量 | | rpoplpush source destination | 移除列表中最后一个元素,并将该元素添加到另一个列表中并返回 | O(1) | | rpoplpush source destination timeout | 从列表弹出一个元素,将弹出的元素插入到另外一个列表中并返回它;如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 | O(1) | | lrem key count value | 移除列表元素 | O(1) |

###### lpush命令
#语法:lpush key value1 [value2...]
#作用:将一个或多个值插入到列表的头部
#例子:
set key list1
lpush list1 v1 v2
#查看列表从下标0到10的数据
lrange list1 0 10
#结果:
#1) "v2"
#2) "v1"

##### lpushx命令 
#语法:lpushx key value1 [value2...]
#作用:将一个或多个值插入到已存在的列表头部,若列表不存在执行此命令返回0
#例子1:插入已存在列表
lpush list1 v1 #打印:1
lpushx list1 2 #打印:2
#查看列表从下标0到10的数据
lrange list1 0 10
#结果:
#1) "v2"
#2) "v1"

#例子2:插入不存在的列表
lpushx list2 v1 #打印:0
lrange list2 0 10 #(empty array)
get list2 #打印:nil

列表的应用:
(1).实现轻量级队列。队列遵循先进先出,后进后出的规则,lpush命令可以实现入列,rpop命令可以实现出列。blpop命令可以实现阻塞出列。

3.Sets(集合)

Redis的Sets类型是一组元素的无须集合,集合成员都是唯一的。 | command(命令) | explain(说明) | 时间复杂度 | | —- | —- | —- | | sadd key value1 [value2…] | 向集合添加一个或多个元素 | O(N) | | scard key | 返回集合中的成员数 | O(1) | | sdiff key1 [key2…] | 返回给定所有集合的差集 | O(N) | | sdiifstore destination key1 [key2…] | 返回给定所有集合的差集并将差集存储到destination中 | O(N) | | sinter key1 [key2…] | 返回给定所有集合的交集 | O(N) | | sinterstore destination key1 [key2…] | 返回给定所有集合的交集并将交集存储到destination中 | O(N) | | sunion key1 [key2…] | 返回给定所有集合的并集 | O(N) | | sunionstore destination key1 [key2…] | 返回给定所有集合的并集并存储到destination中 | O(N) | | sismember key member | 判断member是否是是集合中的元素 | O(1) | | smembers key | 返回集合中的所有元素 | O(1) | | smove source destination member | 将member元素从source集合移动到destination集合 | O(1) | | spop key | 移除并返回集合中的一个随机元素 | O(1) | | srandmember key [count] | 返回集合中的一个或多个随机元素 | | | srem key member1 [member2…] | 移除集合中一个或多个元素 | O(N) | | sscan key cursor [MATCH pattern] [COUNT count] | 迭代集合中的元素 | |

##### sadd命令
#语法:sadd key value1 [value2...]
#作用:向集合中添加一个或多个元素,如果key不存在则会先创建key然后再往集合中添加元素。
sadd set1 v1 v2 #打印:2
sadd set1 v2 v3 #打印:1,因为集合不允许有重复元素,所以v2没有添加上,只添加一个元素到集合所以返回1



##### scard命令
#语法:scard key
#作用:返回集合的成员数
#例子:
sadd set1 v1 v2
scard set1 #打印:2
sadd set1 v3 v4 #打印:4

#### sdiff
#语法:sdiff key1 [key2...]
#作用:返回指定集合的差集
#例子
sadd set1 v1 v2 v3 v4
sadd set2 v3 v4 v5 v6
sdiff set1 set2
#打印结果如下:
#1) "v1"
#2) "v2"

sdiff set2 set1
#打印结果如下:
#1) "v5"
#2) "v6"

###### sdiffstore
#语法:sdiffstore destination key1 [key2...]
#作用:返回给定所有集合的差集并将差集存储到destination中
#例子
sdiffstore set3 set1 set2
scard set3 #打印:4


##### sinter命令
#语法:sinter key1 [key2...]
#作用:返回一个或多个集合的交集
#例子
sadd set1 v1 v2 v3 v4
sadd set2 v3 v4 v5 v6
sinter set1 set2
#打印结果:
#1) "v4"
#2) "v3"

#### sinterstore命令
#语法:sinterstore destination key1 [key2...]
#作用:将一个或多个集合的交集存储到destination中
#例子:
sadd set1 v1 v2 v3 v4
sadd set2 v3 v4 v5 v6
sinterstore set3 set1 set2    #打印:2
smembers set3
#打印结果:
#1) "v4"
#2) "v3"


#### sunion命令
#语法:sunion key1 [key2...]
#作用:返回给定所有集合的并集
#例子
sadd set1 v1
sadd set2 v2
sunion set1 set2
#打印结果:
#1) "v1"
#2) "v2"

#### sunionstore命令
#语法:sunionstore destination key1 [key2...]
#作用:返回给定所有集合的并集并存储到destination中
#例子
sadd set1 v1
sadd set2 v2
sunionstore set3 set1 set2 #打印:2
smembers set3
#执行结果 
#1) "v1"
#2) "v2"

#### sismember
#语法:sismember key member 
#作用:判断member是否是集合中的元素,如果存在就返回1,否则返回0
#例子
sadd set1 v1 v2 v3 v4
sismember set1 v1 #打印:1
sismember set1 v5 #打印:0

### smembers命令
#语法:smembers key
#作用:返回集合中所有成员
#例子
sadd set1 v1 v2 v3 v4
smembers set1
#打印结果:
#1) "v1"
#2) "v2"
#3) "v3"
#4) "v4"

#### smove
#语法:smove source destination member
#作用:将member元素从source集合移动到destination集合
#例子:
sadd set1 v1 v2 v3
sadd set2 v4 v5
smove set1 set2 v1 #打印:1
smembers set2
#打印结果:
#1) "v1"
#2) "v4"
#3) "v5"
smembers set1
#打印结果
#1) "v3"
#2) "v2"


##### spop命令
#语法:spop key
#例子:
sadd set1 v1 v2 v3 v4 v5
spop set1 #打印:"v4"
smembers set1
#打印结果:
#1) "v1"
#2) "v2"
#3) "v3"
#4) "v5"


#### srandmember命令
#语法:srandmember key [count]
#作用:随机返回集合中一个或多个元素
#例子:
srandmember set1 1
#打印结果:
#1) "v1"
srandmember set1 2
#打印结果:
#1) "v1"
#2) "v5"


#### srem命令
#语法:srem key member1 [member2...]
#作用:移除集合中一个或多个元素
#例子:
sadd set1 v1 v2 v3 v4 v5
srem set1 v1 #打印:1
srem set1 v2 #打印:1
srem set1 v3 v4 #打印:1
smembers set1
#执行结果:
#1) "v5"

集合的应用:
(1).set可以实现计数器。例如要根据ip地址计算用户的访问量,
(2).set可以实现点赞。通常评论场景中都有点赞、踩、转发等功能,可以通过集合来存储已经对评论点过赞的用户,当用户再次点赞时只要判断集合中是否存在改用户,若有该用户点赞则变为取消点赞,从而确保每个用户只能对评论点一次赞。命令实现:

#用set存储已点过赞的用户,comment:1 为key可以帮助区分业务,这里为了好理解存储用户名,实际可以存储用户id,这样可以存储空间。
sadd comment:1 '张三' '李四' '王五'

#用户点赞时首先判断集合中是否存在已点赞的用户
sismember key '张三'   #打印1,进入取消点赞逻辑

(3).set实现投票,通过set的命令可以实现投票、取消投票、统计投票数量、获取已投票名单。
(4).set实现社交关系。在社交软件中一般有关注功能,用户可以查看已关注用户及其人数,通过set存储已关注用户就可以实现该功能。

4.Sorted Sets(有序集合)

有序集合相比较集合是有序的,在有序集合中有一个score概念,有序集合中每个成员都与一个score关联,有序集合可以根据score进行排序。 | command(命令) | explain(说明) | 时间复杂度 | | —- | —- | —- | | zadd key score1 member1 [score2 member2…] | 向有序集合添加一个或多个成员,或更新已存在成员的分数 | O(N) | | zcard key | 返回有序集合中的成员数 | O(1) | | zcount key min max | 计算有序集合中指定区间分数的成员数 | O(N) | | zincrby key increment member | 为有序集合中指定成员的分数加上增量increment | O(1) | | zrange key start stop [WITHSCORES] | 根据索引空间返回有序集合中指定区间的成员,withscores表示是否显示成员对应的score | O(N) | | zinterstore destination numkeys key [key…] | 计算一个或多个有序集合的交集,并将交集存储在新的有序集合destination中 | | | zunionstore destination numkeys key [key…] | 计算一个或多个有序集合的并集,并将并集存储在新的有序集合destination中 | | | zrank key member | 返回有序集合中指定成员所在的索引 | O(1) | | zrevrank key member | 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序 | O(1) | | zscore key member | 返回有序集合中指定成员的分数 | O(1) | | zrem key member [member…] | 移除有序集合中一个或多个成员 | O(N) | | zrevrangebyscore key min max [WITHSCORES] | 返回有序集中指定分数区间内的成员,分数从高到低排序 | | | zscan key cursor [MATCH pattern] [COUNT count] | 用于迭代有序集合中的元素(包括元素成员和元素分值)
- cursor - 游标。
- pattern - 匹配的模式。
- count - 指定从数据集里返回多少元素,默认值为 10 。
| | | zpopmax key [count] | 移除集合中score值最大的N个元素 | O(log(N)M) | | zpop key [count] | 移除集合中score值最小的N个元素 | O(log(N)M) |

########### zadd
#语法:zadd key score1 member1 [score2 member2...]
#作用:向有序集合中添加一个或多个成员,并更新已存在成员对应的score(分数)
#例子:zadd zset01 1 a1 a2   #打印2

########## zcard
#语法:zcard key
#作用:返回有序集合中的所有成员数
#例子:
localhost:6379> zcard zset01    #打印2

########## zcount
#语法:zcount key min max
#作用:计算有序集合中指定区间的成员数
#例子:
localhost:6379> zadd zset02 10 a10 20 a20 30 a30 40 a40
localhost:6379> zcount zset02 20 40 #打印3

########## zincrby
#语法:zincrby key increment member
#作用:为有序集合中指定成员的分数加上增量increment
#例子:
localhost:6379> zincrby zset02 1 a10 #打印11
localhost:6379> zrange zset02 0 4 withscores
1) "a10"
2) "11"
3) "a20"
4) "20"
5) "a30"
6) "30"
7) "a40"
8) "40"

######### zrange 
#语法:zrange start stop [withscores]
#作用:根据索引区间返回有序集合指定区间的成员,如不指定withscores参数则不会显示score
#例子:
localhost:6379> zrange zset02 0 4 withscores
1) "a10"
2) "11"
3) "a20"
4) "20"
5) "a30"
6) "30"
7) "a40"
8) "40"

######### zinterstore 
#语法:zinterstore destination numkeys key [key...]
#作用:将一个或多个有序集合的交集结果存储在新的有序集合destination中,numkeys为集合的数量
#例子:
localhost:6379> zadd test01 70 'xxx01' 80 'xxx02' 90 'xxx03'
localhost:6379> zadd test02 70 'xxx01' 72 'xxx02' 81 'xxx03' 94 'xxx04'
localhost:6379> zinterstore test03 2 test01 test02 #打印3
localhost:6379> zrange test03 0 -1
1) "xxx01"
2) "xxx02"
3) "xxx03"


######## zunionstore
#语法:zunionstore destination numkeys key [key...]
#作用:将一个或多个有序集合的进行合并,并将合并的结果集存储在新的有序集合destination中,若两个集合具有一样的成员,则最终只保留一个成员,但成员的分数是相加的
#例子:
localhost:6379> zadd test01 70 'xxx01' 80 'xxx02' 90 'xxx03'
localhost:6379> zadd test02 71 'xxx01' 80 'yyy02' 90 'xxx03'
localhost:6379> zrange test03 0 -1
localhost:6379> zrange test03 0 -1 withscores
1) "xxx02"
2) "80"
3) "yyy02"
4) "80"
5) "xxx01"
6) "141"
7) "xxx03"
8) "180"


######## zrank
#语法:zrank key member
#作用:返回有序集合中指定成员所在的索引
#例子:
localhost:6379> zrank test03 xxx02 #打印0
localhost:6379> zrank test03 xxx03 #打印3


######## zscore
#语法:zscore key member
#作用:返回指定成员的对应的分数
#例子:
localhost:6379> zscore test03 xxx02 #打印"80"


######## zrem
#语法:zrem key member [member...]
#作用:移除有序集合中一个或多个成员
#例子:
localhost:6379> zadd t 80 'a1' 90 'a2' 100 'a3'
localhost:6379> zrem t 'a1' 'a2'
localhost:6379> zrange t 0 -1
1) "a3"

######## zrevrank 
#语法:zrevrank key member
#作用:返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
#例子:
localhost:6379> zadd t1 80 'a1' 110 'a2' 100 'a3' 3 'a4'
localhost:6379> zrevrank t1 a2 #打印0,表示排名第一
localhost:6379> zrevrank t1 'a1' #打印2


####### zscan
#语法:zscan key cursor [MATCH pattern] [COUNT count]
#作用:用于迭代有序集合中的元素(包括元素成员和元素分值),cursor - 游标。pattern - 匹配的模式。
count - 指定从数据集里返回多少元素,默认值为 10 
#例子:
localhost:6379> ZADD site 1 "Google" 2 "Runoob" 3 "Taobao" 4 "Weibo"
localhost:6379> zscan site 0 match 'R*'
1) "0"
2) 1) "Runoob"
   2) "2"

有序集合的应用:
(1).有序集合实现排行榜。排行榜基本上是各个软件的常见功能,例如音乐排行榜根据播放量、搜索量、收藏量来排序,而zset非常容易实现排行榜,zset中有一个score的概念,我们只需将排序的数据传入即可,使用对应的命令为:
zrevrank key member。
(2).使用zset实现自动补全的排序。在网页搜索中当搜索关键字时浏览器会进行自动补全,并根据权重信息将匹配的数据排序,权重越大的排在越前面,在zset中我们可以把权重看作为score,这样就能轻松的对匹配结果进行排序。

5.HashMaps

6.HyperLogLog(超级日志)

基数是什么?
比如数据集 {1, 3, 5, 7, 5, 7, 8},那么这个数据集的基数集为 {1, 3, 5 ,7, 8},基数(不重复元素)为5。基数估计就是在误差可接受的范围内,快速计算基数。

HyperLogLog是一种概率数据结构,对于一个给定的集合,HyperLogLog可以计算出这个集合的近似基数:近似基数并非集合的实际基数,它可能会比实际的基数小一点或者大一点,但是估算基数和实际基数之间的误差会处于一个合理的范围之内,因此那些不需要知道实际基数或者因为条件限制而无法计算出实际基数的程序就可以把这个近似基数当作集合的基数来使用。

HyperLogLog优点在于它计算的近似基数所需的内存并不会因为集合的大小而改变,无论集合包含的元素有多少个,HyerLogLog进行计算所需的内存总数固定的,并且是非常少。具体到实现上,Redis的每个HyperLogLog只需要使用12kb内存空间,就可以对2的64次方个元素进行计数,而算法的标准误差率仅为0.81%,因此它计算出的近似基数是相当可信的。

假设有这么一个场景,某网站需要访问用户的浏览次数,通过Set结构很轻易就能实现这个功能,我们可以把访问ip存储到Set结构中进行统计,保证访问IP只能被计数一次,存储一个IPV4格式的IP地址最多需要15个字节(例如”127.234.122.101”),根据网站的规模不同,每天出现唯一的访问IP可能有10万或者更多,如果持续1个月或更久,这样会造成Set占用大量的内存,而HyperLogLog可以解决计数时造成占用大量内存问题。

command(命令) explain(说明) 时间复杂度
pfadd key element [element…] 添加一个或多个元素到HyperLogLog中进行计数。pfadd命令可能返回0或1,如果给定元素都已进行过计数则返回0,否则返回1 O(N)
pfcount key [key…] 返回一个或多个 HyperLogLog 并集的基数估算值 O(N)
pfmerge desitination key [key…] 计算多个HyperLogLog的并集,并将结果存储到新的HyperLogLog (desitination)中 O(N)
########### pfadd
#语法:pfadd key element [element...]
#作用:将一个或多个元素添加到hyperloglog中进行计算
#例子:
localhost:6379> pfadd hyper01 a b c d
(integer) 1
localhost:6379> pfadd hyper01 a  #由于a被计算过了所以打印0
(integer) 0


########## pfcount
#语法:pfcount key [key...]
#作用:返回一个或多个hyperloglog并集的基数估算值
#例子:
localhost:6379> pfadd hyper01 a b c d
(integer) 1
localhost:6379> pfadd hyper02 d e f g
(integer) 1
localhost:6379> pfcount hyper01 hyper02
(integer) 7  #因为hyper01的d与hyper02的d是重复的


######### pfmerge 
#语法:pfmerge destination key [key...]
#作用:计算多个HyperLogLog的并集,并将结果存储到新的HyperLogLog (desitination)中
#例子:
localhost:6379> pfadd hyper01 111
(integer) 1
localhost:6379> pfadd hyper02 222
(integer) 1
localhost:6379> pfadd hyper03 333
(integer) 1
localhost:6379> pfmerge unihyper hyper01 hyper02 hyper03
OK
localhost:6379> pfcount unihyper
(integer) 3

应用场景:
(1).HyperLogLog可以实现访问量的统计。

7.Bitmaps(位图)

位图是由多个二进制位组成的数组,数组中的每个二进制位都有与之对应的偏移量(也叫索引),用户通过对偏移量可以对指定一个或多个二进制位进行操作。位图的最大优点之一是,在存储信息时,它们通常可以节省大量空间。 | command(命令) | explain(说明) | 时间复杂度 | | —- | —- | —- | | setbit ket offset value | 为位图中指定偏移量设置值,偏移量只能为正数, | O(N) | | getbit key offset | 返回位图指定偏移量的值 | O(N) | | bitcount key [start end] | 根据偏移量范围统计位图中值为1的二进制位数量 | O(N) | | bitpos key value [start end] | 返回value第一次出现在位图的二进制位的偏移量 | O(N) | | bitop operation result_key key [key…] | 对一个或多个位图执行指定的二进制运算符,并将结果存储到一个新key(result_key)中。operation可以是and、or、xor、not | O(N) |

########### setbit
localhost:6379> setbit bitmap 0 1
(integer) 0
localhost:6379> setbit bitmap 3 1 #如果不显示指定偏移量的值,那么会使用0进行补位,偏移量2的值就是0
(integer) 0  
localhost:6379> setbit bitmap 5 1
(integer) 0
localhost:6379> setbit bitmap002 10 1 #如果设置的位图不存在或位图的大小无法满足指定偏移量,这时Redis会对位图进行扩容,Redis对位图的扩容是以字节为单位进行的,一个字节等于8个二进制数,扩展时还会将未被设置的二进制位设置为0。bitmap002最终不会被扩展成11个二进制位,而是扩展成2个字节16个二进制位。
(integer) 0

########## getbit
localhost:6391> setbit bitmap 0 1
(integer) 0
localhost:6391> getbit bitmap 0
(integer) 1
localhost:6391> getbit bitmap 3 #gitbit会把超出位图大小的偏移量都看做是0
(integer) 0

#########  bitcount
localhost:6379> setbit bitmap 0 1
(integer) 0
localhost:6379> setbit bitmap 3 1
(integer) 0
localhost:6379> setbit bitmap 5 1
(integer) 0
localhost:6379> setbit bitmap 8 0
(integer) 0
localhost:6379> bitcount bitmap 
(integer) 3
localhost:6379> set name "goods"
OK
localhost:6379> bitcount name
(integer) 25
localhost:6379> bitcount name 3 25 #end参数为-1表示访问倒数第一个,-2表示访问倒数第2个
(integer) 8

########### bitop
localhost:6379> setbit b1 0 1
(integer) 0
localhost:6379> setbit b1 3 1
(integer) 0
localhost:6379> bitpos b1 1
(integer) 0

应用场景:
(1).用户行为记录器。为了对用户的行为进行分析从而改善服务质量,一般很多网站都会对用户的操作进行记录,例如:哪些用户登录了,哪些用户发表了新的文章,哪些用户进行了消费等等。对于这种我们可以通过SET结构来记录用户行为,但使用SET结构随着用户的数量的增多而变大,从而消耗大量内存。而HyperLogLog虽然能节省大量内存,但HyperLogLog只能计算出估算值,无法精确地记录数据而无法记录更多的信息。位图对于这种场景既能节省大量内存,又能精确的记录更多信息,比如以用户的12345ID为偏移量,其对应值为1,0表示未购买了商品,1表示已购买了商品。

8.Geospatial indexes(地理空间索引)

Redis GEO是Redis3.2版本新添加的数据结构,通过GEO用户可以将经纬度格式的地理坐标存在到Redis中,并对这些坐标执行距离计算、范围查找。 | command(命令) | explain(说明) | 时间复杂度 | | —- | —- | —- | | geoadd key longitude latitude name[longitude latitude name…] | 给定一个或多个经纬度坐标存储到位置集合中,并为这些坐标设置相应的名称。返回坐标的长度 | O(N) | | geopos key name [name…] | 根据一个或多个坐标名称或经纬度 | O(N) | | geodist key name1 name2 [unit] | 计算两个坐标之间的直线距离,unit表示为单位,可选值为m(米)、km(千米)、ft(英尺)、mi(英里),默认为m | O(N) | | georadius key longitude latitude radius unit [withcoord] [withdist] [asc | desc] [COUNT count] | 指定一个经纬度作为中心点,并从个位置集合中找出位于中心点指定半径范围内的其他位置。
key为位置集合
longitude和latitude为指定中心的经度和纬度
radius用于指定查找半径
unit用于查找半径的单位,可选值为m、km、ft、mi。
withcoord表示查询结果是否显示经纬度信息。
withdist表示查看结果是否显示直线距离
asc可以对返回结果的各个坐标进行从近到院的排列,而desc相反。
count用于控制查询结果显示个数 | O(1) | | georadiusbymember key name radius unit [withcoord] [withdist] [asc | desc] [COUNT count] | georadiusbymember命令与georadius类似,只不过是根据位置集合中的坐标名称作为中心店 | O(1) | | geohash key name [name…] | 获取一个或多个坐标的geohash值 | O(N) |

#查看经纬度网站:https://www.jingweizuobiao.com/results/jruzNOv41Or56w8WAtvW

############### geoadd
localhost:6379> geoadd city 113.7465512 23.0444712 dongguan  114.054555 22.546327 shenzhen
(integer) 2

############## geopos
localhost:6379> geopos city dongguan
1) 1) "113.74654859304428101"
   2) "23.04447191663499694"


############## geodist
localhost:6379> geodist city dongguan shenzhen m
"63775.9223" #东莞到深圳的直线距离是63775.9223m
localhost:6379> geodist city dongguan shenzhen km
"63.7759" #东莞到深圳的直线距离是63.7759千米

############# georadius
localhost:6379> geoadd china_city 113.7465512 23.0444712 dongguan  114.054555 22.546327 shenzhen 113.253914 23.218034 guangzhou  121.469645 31.231781 shanghai  116.391433 39.901843 beijing
(integer) 5
localhost:6379> georadius china_city 113.7465512 23.0444712 80 km #查找位置集合中距离东莞坐标80km半径的其他位置坐标
1) "guangzhou"
2) "dongguan"
3) "shenzhen"
localhost:6379> georadius china_city 113.7465512 23.0444712 80 km withcoord
1) 1) "guangzhou"
   2) 1) "113.25391262769699097"
      2) "23.21803441329956996"
2) 1) "dongguan"
   2) 1) "113.74654859304428101"
      2) "23.04447191663499694"
3) 1) "shenzhen"
   2) 1) "114.05455738306045532"
      2) "22.54632823663243357"
localhost:6379> georadius china_city 113.7465512 23.0444712 80 km withdist
1) 1) "guangzhou"
   2) "53.9606"
2) 1) "dongguan"
   2) "0.0003"
3) 1) "shenzhen"
   2) "63.7757"

############ georadiusbymember
localhost:6379> georadiusbymember china_city dongguan 80 km asc
1) "dongguan"
2) "guangzhou"
3) "shenzhen"

############# geohash
localhost:6379> geohash china_city dongguan shenzhen
1) "ws0gh75ey80"
2) "ws10727vzu0"

9.Streams(流)

Streams是Redis5.0新增的数据结构,流的出现是解决列表、有序集合、发布于订阅而出现的。流是一个包含0个或多个流元素的有序队列,队列中的每个元素都包含一个ID和任意多个键值对,这些元素会根据ID的大小在流中有序的进行排列。 | command(命令) | explain(说明) | 时间复杂度 | | —- | —- | —- | | xadd key id field value [field value…] | 将一个带有指定ID以及包含键值对的元素追加到流的末尾并返回流的ID。流的ID由毫秒和顺序编号两部分组成,接收流或输入流时会使用-号分割。添加元素时不能使用相同的ID,而且后添加的ID必须要比先添加的ID大 | | | xrange key start-id end-id [COUNT n] | 根据一个起始ID、和结束ID访问流中任意元素,其中n为限制访问个数。start-id和end-id除了是id外,也可以是-和+,-号表示流中最小的id,+号表示流中最大的id | | | xrevrange key end-id start-id [COUNT n] | xrevrange是xrange命令逆序版本,xrange是根据id以从小到大访问流元素,而xrerange与xrange相反。注意xrevrange先接收结束id,后接收起始id | | | xtrim key maxlen len | 将流修剪至指定长度,返回被移除元素的数量作为结果 | O(log(N)+M),N为执行修剪操作前流包含的元素数量,M则被移除元素的数量 | | xdel key [id id…] | 接收一个或多个元素ID并移除流中ID对应的元素,返回移除成功的元素数量 | O(log(N)+M) | | xlen key | 返回流中元素的数量 | O(1) | | | | |

########### xadd
localhost:6379> xadd stream01 1111111111-01 k1 zxp k2 zchengfeng
"1111111111-1"
localhost:6379> xadd stream01 1111111111-01 k3 zxp k4 zchengfeng    #id已存在不能添加
(error) ERR The ID specified in XADD is equal or smaller than the target stream top item
localhost:6379> xadd stream01 1111111000-01 k3 zxp k4 zchengfeng #后添加的id必须要比先添加的id大
(error) ERR The ID specified in XADD is equal or smaller than the target stream top item
localhost:6379> xadd stream01 1111111222-01 k3 zxp k4 zchengfeng
"1111111222-1"
localhost:6379> xadd stream01 * k3 zxp k4 zchengfeng  #*号表示自动生成id
"1618681341836-0"
localhost:6379> xadd stream01 maxlen 1 * k3 zxp k4 zchengfeng #限制流的长度为1,之前添加的元素都会被移除掉,遵循先进先出原则
"1618681448832-0"

#################### xrange
localhost:6379> xadd sm01 1111111111-01 k1 v1
"1111111111-1"
localhost:6379> xadd sm01 1111111111-02 k2 v2
"1111111111-2"
localhost:6379> xadd sm01 1111111111-03 k3 v3
"1111111111-3"
localhost:6379> xrange sm01 1111111111-01 1111111111-03
1) 1) "1111111111-1"
   2) 1) "k1"
      2) "v1"
2) 1) "1111111111-2"
   2) 1) "k2"
      2) "v2"
3) 1) "1111111111-3"
   2) 1) "k3"
      2) "v3"
localhost:6379> xrange sm01 1111111111-01 1111111111-03 count 2 #限制访问2个
1) 1) "1111111111-1"
   2) 1) "k1"
      2) "v1"
2) 1) "1111111111-2"
   2) 1) "k2"
      2) "v2"
localhost:6379> xrange sm01 - +       #使用-和+,-表示流中最小的id,+为流中最大的id
1) 1) "1111111111-1"
   2) 1) "k1"
      2) "v1"
2) 1) "1111111111-2"
   2) 1) "k2"
      2) "v2"
3) 1) "1111111111-3"
   2) 1) "k3"
      2) "v3"

################ xrevrange
localhost:6379> xrevrange sm01 1111111111-03 1111111111-01 
1) 1) "1111111111-3"
   2) 1) "k3"
      2) "v3"
2) 1) "1111111111-2"
   2) 1) "k2"
      2) "v2"
3) 1) "1111111111-1"
   2) 1) "k1"
      2) "v1"
localhost:6379> xrevrange sm01 1111111111-03 1111111111-01 COUNT 2
1) 1) "1111111111-3"
   2) 1) "k3"
      2) "v3"
2) 1) "1111111111-2"
   2) 1) "k2"
      2) "v2"
localhost:6379> xrevrange sm01 + 1111111111-01 COUNT 2
1) 1) "1111111111-3"
   2) 1) "k3"
      2) "v3"
2) 1) "1111111111-2"
   2) 1) "k2"
      2) "v2"


################# xtrim
localhost:6379> xtrim sm01 maxlen 1    #根据先进先出原则淘汰元素
(integer) 2
localhost:6379> xrange sm01 - +
1) 1) "1111111111-3"
   2) 1) "k3"
      2) "v3"

######### xdel
localhost:6379> xdel sm01 1111111111-3 
(integer) 1
localhost:6379> xrange sm01 - +
(empty array)


######## xlen
localhost:6379> xadd sm02 1111111111-01 k1 v1
"1111111111-1"
localhost:6379> xadd sm02 1111111111-02 k2 v2
"1111111111-2"
localhost:6379> xlen sm02
(integer) 2