Redis 五种数据类型的简单介绍和使用

1.Redis 特性

  1. 速度快

    正常情况下,Redis 读写性能可以达到 10 万/秒 ;Redis 所有数据是存放在内存中的、Redis 是用 C 语言实现的、Redis 使用了单线程架构。

  2. 基于键值对的数据结构

    Redis 的全称是 REmote Dictionary Server,主要提供了 5 种数据结构:字符串(String)哈希(Hash)列表(List)集合(Set)有序集合(ZSet)

    在字符串的基础上演变出了位图(Bitmaps)HyperLogLog两种数据机构,在 Redis3.2 版本中加入有关GEO(地理信息定位)的功能。

  3. 丰富的功能

    • 提供了键过期功能,可以用来实现缓存
    • 提供了发布订阅功能,可以用来实现消息系统
    • 支持Lua脚本功能,可以利用Lua创造出新的Redis命令
    • 提供了简单的事务功能,能在一定程度上保证事务特性
    • 提供了(Pipeline)功能,这样客户点能将一批命令一次性传到 Redis ,减少了网络的开销
  4. 简单稳定

  5. 客户端语言多

  6. 持久化

    将数据放在内存中是不安全的,一旦发生断电或者机器故障,重要的数据可能就会丢失,因此,Redis 提供了两种持久化方式:RDBAOF,即可以用两种策略将内存的数据保存到硬盘中。

  7. 主从复制

    Redis 提供了复制功能,实现了多个相同数据的 Redis 副本。

  8. 高可用和分布式

    Redis 从2.8版本正式提供了高可用实现 Redis Sentinel,它能够保证 Redis 节点的故障发现和故障自动转移。Redis 从3.0版本正式提供了分布式实现 Redis Cluster,它是 Redis 真正的分布式实现,提供了高可用、读写和容量的扩展性。

2.Redis API的理解与使用

1.全局命令

  • 查看所有键

    keys * 会将所有的键输出

  • 键总数

    dbsize 返回当前数据库中键的总数。 dbsize 命令在计算键总数时不会遍历所有键,而是直接获取Redis 内置的键总数变量,所以dbsize命令的时间复杂度是o(1)。而keys命令会遍历所有键,所以它的时间复杂度是o(n),当Redis中保存了大量键时,线上环境禁止使用

  • 检查键是否存在

    exists key 如果存在则返回1,不存在则返回0。

  • 删除键

    del key [key ...] 返回结果为成功删除键的个数,假设删除一个不存在的键,就会返回0

  • 键过期

    expire key seconds Redis 支持对键添加过期时间,当超过期时间后,会自动删除键。

    ttl key 返回键的剩余过期时间,有3中返回值

    • 大于等于0的整数:键剩余的过期时间
    • -1:键没设置过期时间
    • -2:键不存在
  • 键的数据结构类型

    type key 例如键是字符串类型,返回结果为string,键是列表类型,返回结果为list,如果键不存在,返回 none

2.数据结构和内部编码

type 命令实际返回的是当前键的数据结构类型(5种数据类型),但这些只是Redis对外的数据结构。

实际上每种数据结构都有自己底层的内部编码实现,而且是多种实现,这样Redis会在合适的场景选择合适的内部编码

我们可以通过object encoding key查询内部编码。

Redis 这样设计有2个好处:

  • 可以改进内部编码,而对外的数据结构和命令没有影响,这样一旦开发出更优秀的内部编码,无需改动外部数据结构和命令
  • 多种内部编码实现可以不同场景下发挥各自的优势,例如ziplist比较节省内存,但是在列表元素比较多的情况下,性能会有所下降,这时候Redis会根据配置选项将列表类型的内部实现转换为linkedlist
1.字符串

字符串类型是Redis最基础的数据结构。字符串的值最大不能超过512MB

命令

  • 设置值

    set key value [ex seconds] [px milliseconds] [nx|xx]

    • ex seconds:为键设置秒级过期时间
    • px milliseconds:为键设置毫秒级过期时间
    • nx:键必须不存在,才可以设置成功,用于添加
    • xx:与nx相反,键必须存在,才可以设置成功,用于更新

    除了 set 选项,Redis 还提供了 setexsetnx 两个命令,它们的作用和 ex 和 nx 选项是一样的:

    • setex key seconds value
    • setnx key value
  • 获取值

    get key 如果获取的键不存在,则返回nil(空)

  • 批量设置值

    mset key value [key value ...]

  • 批量获取值

    mget key [key ...] 如果有些键不存在,那么它的值为nil(空),结果是按照传入键的顺序返回

  • 计数

    incr key incr命令用于对值做自增的操作,返回结果分为3种情况:

    • 值不是整数,返回错误
    • 值是整数,返回自增后的结果
    • 键不存在,按照值为0自增,返回结果为1

    除了incr命令,Redis提供了decr(自减)incrby(自增指定数字)decrby(自减指定数字)incrbyfloat(自增浮点数)

    • decr key
    • incrby key increment
    • decrby key decrement
    • incrbyfloat key increment
  • 追加值

    append key value append可以向字符串尾部追加值

  • 字符串长度

    strlen key eg:当前值为redisworld,所以返回值为10,当前值为世界,返回值为6(每个中文占用3个字节)

  • 设置并返回原值

    getset key value getset和set一样会设置值,但是不同的是,它同时会返回键原来的值

  • 设置指定位置的字符

    setrange key offset value

    • 下面操作将值由pest变为了best

      127.0.0.1:6379> set redis pest
      OK
      127.0.0.1:6379> setrange redis 0 b
      (integer) 4
      127.0.0.1:6379> get redis
      "best"
      127.0.0.1:6379> setrange redis 2  a
      (integer) 4
      127.0.0.1:6379> get redis
      "beat"
      127.0.0.1:6379> setrange redis 6  c
      (integer) 7
      127.0.0.1:6379> get redis
      "beat\x00\x00c"
      127.0.0.1:6379> 
      
  • 获取部分字符串

    getrange key start end

    start 和 end 分别是开始和结束的偏移量,偏移量从0开始计算

    127.0.0.1:6379> getrange redis 0 1
    "be"
    127.0.0.1:6379> getrange redis 9 10
    ""
    127.0.0.1:6379> getrange redis 4 10
    "\x00\x00c"
    127.0.0.1:6379> getrange redis 3 10
    "t\x00\x00c"
    127.0.0.1:6379> 
    
    命令时间复杂度
    set key valueo(1)
    get keyo(1)
    del key [key …]o(k),k是键的个数
    mset key value [key value …]o(k),k是键的个数
    mget key [key …]o(k),k是键的个数
    incr keyo(1)
    decr keyo(1)
    incrby key incremento(1)
    decrby key incremento(1)
    incrbyfloat key incremento(1)
    append key valueo(1)
    strlen keyo(1)
    setrange key offset valueo(1)
    getrange key start endo(n),n是字符串长度,由于获取字符串非常快,所以如果字符串不是很长,可以视同为o(1)
2.哈希

在 Redis 中,哈希类型是指键值本身又是一个键值对结构。

命令

  • 设置值

    hset key field value

    下面为user:1 添加一对 field-value

    127.0.0.1:6379> hset user:1 name tom
    (integer) 1
    

    如果field已经存在,执行上述命令返回 0,但实际的值发生改变

    127.0.0.1:6379> hset user:1 name ddddd
    (integer) 0
    

    此外,Redis 提供了hsetnx 命令,它们的关系就像set和setnx命令一样,只不过作用域由键变为field

  • 获取值

    hget key field

    下面的操作获取user:1的name域(属性)对应的值,如果键或field不存在,会返回nil

    127.0.0.1:6379> hget user:1  name
    "tom"
    127.0.0.1:6379> hget user:1  namea
    (nil)
    
  • 删除field

    hdel key field [field ...]

    hedl 会删除一个或多个field,返回结果为成功删除field的个数

  • 计算field个数

    hlen key

    例如:user:1 有3个field

    127.0.0.1:6379> hset user:1 name gy
    (integer) 1
    127.0.0.1:6379> hset user:1 age 26
    (integer) 1
    127.0.0.1:6379> hset user:1 city hz
    (integer) 1
    127.0.0.1:6379> hlen user1:1
    (integer) 0  #key不存在返回值
    127.0.0.1:6379> hlen user:1
    (integer) 3
    
  • 批量设置或获取field-value

    hmset key field value [field value ...]

    hmget key field [field...]

    hmset和hmget分别是设置和获取field-value,hmset需要的参数是key和多对field-value,hmget需要的参数是key和多个field。

    127.0.0.1:6379> HMSET user:1 name huang age 12 city xian
    OK
    127.0.0.1:6379> hmget user:1 name age citu city aa
    1) "huang"
    2) "12"
    3) (nil) #field不存在
    4) "xian"
    5) (nil) #field不存在
    
  • 判断field是否存在

    hexists key field

    例如,user:1包含name域,所以返回结果为1,不包含时返回0

    127.0.0.1:6379> HEXISTS user:1 name
    (integer) 1
    127.0.0.1:6379> HEXISTS user:1 name22
    (integer) 0
    127.0.0.1:6379> 
    
  • 获取所有field

    hkeys key

    hkeys命令应该叫hfields更为恰当,他返回指定哈希键所有的field,例如

    127.0.0.1:6379> hkeys user:1
    1) "name"
    2) "age"
    3) "city"
    127.0.0.1:6379> hkeys user:11  #键不存在
    (empty list or set)
    127.0.0.1:6379> 
    
    
  • 获取所有value

    hvals key

    获取 user:1全部value

    127.0.0.1:6379> hvals user:1
    1) "huang"
    2) "12"
    3) "xian"
    127.0.0.1:6379> hvals user:12
    (empty list or set)
    
  • 获取所有的field-value

    hgetall key

    获取user:1所有的field-value

    127.0.0.1:6379> hgetall uset:1 #key不存在的情况
    (empty list or set)
    127.0.0.1:6379> hgetall user:1
    1) "name"
    2) "huang"
    3) "age"
    4) "12"
    5) "city"
    6) "xian"
    127.0.0.1:6379> 
    
    

    在使用 hgetall时,如果哈希元素个数比较多,会存在阻塞 Redis 的可能。如果开发人员只需要获取部分field,可以使用hmget,如果一定要获取全部field-value,可以使用hscan命令,该命令会渐进式遍历哈希类型

  • hincrby hincrbyfloat

    hincrby key field

    hincrbyfloat key field

    就像incrby、incrbyfloat命令一样,但是它们的作用域是field

  • 计算value的字符串长度(需要Redis 3.2以上)

    hstrlen key field

    例如:hget user:1 name 的 value 是 tom,那么hstrlen 的返回结果就是3

    命令时间复杂度
    hset key field valueo(1)
    hget key fieldo(1)
    hdel key field [field …]o(k),k是field个数
    hlen keyo(1)
    hgetall keyo(n),n是field总数
    hmget field [field …]o(k),k是field的个数
    hmset field value [field value]o(k),k是field的个数
    hexists key fieldo(1)
    hkeys keyo(n),n是field总数
    hvals keyo(n),n是field总数
    hsetnx key field valueo(1)
    hincrby key field incremento(1)
    hincrbyfloat key field incremento(1)
    hstrlen key fieldo(1)
3.列表

列表(list)类型是用来存储多个有序的字符串。列表的每个字符串称为元素(element),一个列表最多可以存储2^32-1个元素。

在 Redis 中,可以对列表两端插入(push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。

列表的四种操作类型

操作类型操作
添加rpush lpush linsert
查询lrange lindex llen
删除lpop rpop lrem ltrim
修改lset
阻塞操作bloop brpop
  • 添加操作

    • 从右边插入元素

      rpush key value [value ...]

      下面代码从右向左插入元素c、b、a:

      127.0.0.1:6379> rpush listkey c b a
      (integer) 3
      

      lrange 0 -1命令可以从左到右获取列表所有元素

      127.0.0.1:6379> rpush listkey c b a 
      (integer) 3
      127.0.0.1:6379> lpush listkey e f g #左边插入
      (integer) 6
      127.0.0.1:6379> lrange listkey 0 -1
      1) "g"
      2) "f"
      3) "e"
      4) "c"
      5) "b"
      6) "a"
      127.0.0.1:6379> rrange listkey 0 -1
      (error) ERR unknown command `rrange`, with args beginning with: `listkey`, `0`, `-1`, 
      
    • 从左边插入元素

      lpush key value [value ...]

      使用方法和 rpush 相同,只不过从左侧插入

    • 向某个元素前或者后插入元素

      linsert key before|after pivot value

      linsert 命令会从列表中找到等于 pivot(中枢) 的元素,在其前(before)或者后(after)插入一个 新的元素value。

      下面操作将会在列表的元素b前插入java,返回结果为4,代表当前命令的长度

      127.0.0.1:6379> rpush mylist c b a
      (integer) 3
      127.0.0.1:6379> LRANGE mylist 0 -1
      1) "c"
      2) "b"
      3) "a"
      127.0.0.1:6379> linser mylist before b java
      (error) ERR unknown command `linser`, with args beginning with: `mylist`, `before`, `b`, `java`, 
      127.0.0.1:6379> linsert mylist before b java
      (integer) 4
      127.0.0.1:6379> LRANGE mylist 0 -1
      1) "c"
      2) "java"
      3) "b"
      4) "a"
      
  • 查找

    • 获取指定范围内的元素列表

      lrange key start end

      lrange 操作会获取列表指定索引范围所有的元素。索引下标有两个特点:

      • 索引下标从左到右分别是0到N-1,但是从右到左分别是-1到-N

      • lrange中的 end 选项包含了自身,这个和很多编程语言不包含 end 不太相同,例如像获取列表的第 2 到 第 4 个元素,可以执行如下操作:

        127.0.0.1:6379> lrange mylist 1 3
        1) "java"
        2) "b"
        3) "a"
        127.0.0.1:6379> 
        
        127.0.0.1:6379> lrange mylist 0 1
        1) "c"
        2) "java"
        127.0.0.1:6379> lrange mylist 0 7
        1) "c"
        2) "java"
        3) "b"
        4) "a"
        127.0.0.1:6379> lrange mylist -1 -3
        (empty list or set)
        127.0.0.1:6379> lrange mylist -4 -1
        1) "c"
        2) "java"
        3) "b"
        4) "a"
        127.0.0.1:6379> lrange mylist -5 -1
        1) "c"
        2) "java"
        3) "b"
        4) "a"
        
        
    • 获取列表指定索引下标的元素

      lindex key index

      例如,当前列表最后一个元素为a:

      127.0.0.1:6379> lindex mylist -1
      "a"
      127.0.0.1:6379> lindex mylist 0
      "c"
      127.0.0.1:6379> 
      
    • 获取列表长度

      llen key

      例如,下面表示当前列表长度为4

      127.0.0.1:6379> llen mylist
      (integer) 4
      127.0.0.1:6379> llen mylist2
      (integer) 0  #key值不存在返回的0
      127.0.0.1:6379> 
      
  • 删除

    • 从列表左侧弹出元素

      lpop key

      如下操作将列表最左侧的元素c会被弹出(弹出后,元素被删除),弹出后列表变为 java、b、a:

      127.0.0.1:6379> lrange mylist 0 -1
      1) "c"
      2) "java"
      3) "b"
      4) "a"
      127.0.0.1:6379> lpop mylist
      "c"  #弹出的元素
      127.0.0.1:6379> lrange mylist 0 -1
      1) "java"
      2) "b"
      3) "a"
      
      
    • 从列表右侧弹出

      rpop key

      它的使用方法和lpop是一样的,只不过从列表右侧弹出。

      127.0.0.1:6379> lrange mylist 0 -1
      1) "java"
      2) "b"
      3) "a"
      127.0.0.1:6379> RPOP mylist
      "a"
      
    • 删除指定元素

      lrem key count value

      lrem 命令会从列表中找到等于value的元素进行删除,根据count的不同分为三种情况:

      • count>0,从左到右,删除最多count个元素

      • count<0,从右到左,删除最多count绝对值个元素

      • count=0,删除所有

        例如,向列表从左向右插入5个a,下面操作将从列表左边开始删除4个为a的元素

        127.0.0.1:6379> lpush mylist a a a a a java a 
        (integer) 7
        127.0.0.1:6379> lrange mylist 0 -1
        1) "a"
        2) "java"
        3) "a"
        4) "a"
        5) "a"
        6) "a"
        7) "a"
        127.0.0.1:6379> lrem list 4 a
        (integer) 0
        127.0.0.1:6379> lrem mylist 4 a
        (integer) 4
        127.0.0.1:6379> lrange mylist 0 -1
        1) "java"
        2) "a"
        3) "a"
        
    • 按照索引范围修建列表

      ltrim key start end

      例如,下面操作会只保留列表mylist第2个到第4个元素

      127.0.0.1:6379> lpush mylist a a a a a java a 
      (integer) 7
      127.0.0.1:6379> lrange mylist 0 -1
      1) "a"
      2) "java"
      3) "a"
      4) "a"
      5) "a"
      6) "a"
      7) "a"
      127.0.0.1:6379> ltrim mylist 1 3
      OK
      127.0.0.1:6379> lrange mylist 0 -1
      1) "java"
      2) "a"
      3) "a"
      
  • 修改

    • 修改指定索引下标的元素

      lset key index newValue

      下面操作会将列表listkey中的第3个元素设置为python:

      127.0.0.1:6379> lrange mylist 0 -1
      1) "java"
      2) "a"
      3) "a"
      127.0.0.1:6379> lset mylist 2 python
      OK
      127.0.0.1:6379> lrange mylist 0 -1
      1) "java"
      2) "a"
      3) "python"
      
  • 阻塞操作

    阻塞式弹出如下:

    blpop key [key ...](多个列表的键) timeout(阻塞时间>=0)

    brpop key [key ...] (多个列表的键)timeout(阻塞时间>=0)

    blpop和brpop 是 lpop 和 rpop 的阻塞版本

    • 列表为空:如果timeout=3,那么客服端要等到3秒后返回,如果timeout=0,那么客户端一直阻塞等待下去

      127.0.0.1:6379> brpop list:test 3
      (nil)
      (3.05s)
      127.0.0.1:6379> brpop list:test 0  #命令执行完成后去客户端新增该键值对数据,客户端立即返回
      1) "list:test"
      2) "ggggg"
      (34.77s)
      
      

      列表命令时间复杂度

      操作类型命令时间复杂度
      添加rpush key value [value …]o(k),k是元素的个数
      lpush key value [value …]o(k),k是元素的个数
      linsert key before|after pivot valueo(n),n是pivot距离列表头或尾的距离
      查找lrange key start endo(s+n),s是start偏移量,n是start到end的范围
      lindex key indexo(n),n是索引的偏移量
      llen keyo(1)
      删除lpop keyo(1)
      rpop keyo(1)
      lrem count valueo(n),n是列表的长度
      ltrim key start endo(n),n是要裁剪的元素总数
      修改lset key index valueo(n),n是索引的偏移量
      阻塞操作blpop brpopo(1)
4.集合

集合(set)类型也是用来保存多个的字符串元素,但和列表类型不一样的是,集合中不允许有重复元素,并且集合中的元素是无序的,不能通过索引下标获取元素。一个集合最多可以存储2^32-1个元素。

Redis除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。

命令

  • 集合内操作

    • 添加元素

      sadd key member [member ...] 返回结果为添加成功的元素个数。

      127.0.0.1:6379> EXISTS myset
      (integer) 0
      127.0.0.1:6379> sadd myset a b c 
      (integer) 3
      127.0.0.1:6379> sadd myset a b
      (integer) 0
      
    • 删除元素

      srem key member [member ...] 返回结果为成功删除元素的个数

      127.0.0.1:6379> srem myset a b c
      (integer) 3
      127.0.0.1:6379> srem myset hello
      (integer) 0
      
    • 计算元素个数

      scard key scard 的时间复查度为O(1),它不会遍历集合所有元素,而是直接使用 Redis 内部的变量

      127.0.0.1:6379> scard myset
      (integer) 1
      
    • 判断元素是否在集合中

      sismember key element 如果给定元素element在集合内返回1,反之返回0

      127.0.0.1:6379> sismember myset a #不存在
      (integer) 0
      127.0.0.1:6379> sismember myset c
      (integer) 1
      127.0.0.1:6379> sismember myset1 c #不存在
      (integer) 0
      
    • 随机从集合返回指定个数元素

      srandmember key [count] [count]是可选参数,如果不写默认为1

      127.0.0.1:6379> sadd myset a b c 
      (integer) 3
      127.0.0.1:6379> srandmember myset 2
      1) "c"
      2) "a"
      127.0.0.1:6379> srandmember myset 2
      1) "c"
      2) "b"
      127.0.0.1:6379> srandmember myset 2
      1) "a"
      2) "b"
      
    • 从集合随机弹出元素

      spop key [count] spop操作可以从集合中随机弹出一个元素

      srandmember 和 spop 都是随机从集合中选出元素,两者不同的是spop命令执行后,元素会从集合中删除,而srandmember不会

    • 获取所有元素

      smembers key

      127.0.0.1:6379> SMEMBERS myset
      1) "c"
      2) "b"
      

      smembers、lrange、hgetall都属于比较重的命令,如果元素过多存在阻塞Redis的可能性,这时候可以使用sscan来完成。

  • 集合间操作

    • 求多个集合的交集

      sinter key [key ...]

      127.0.0.1:6379> sadd user:1:follow it music his sports
      (integer) 4
      127.0.0.1:6379> sadd user:2:follow it news ent sprots
      (integer) 4
      127.0.0.1:6379> sinter user:1:follow user:2:follow
      1) "it"
      
    • 求多个集合的并集

      sunion key [key ...]

      127.0.0.1:6379> SUNION user:1:follow user:2:follow
      1) "sports"
      2) "it"
      3) "his"
      4) "news"
      5) "ent"
      6) "music"
      7) "sprots"
      
    • 求多个集合的差集

      sdiff key [key ...]

      127.0.0.1:6379> sdiff user:1:follow user:2:follow
      1) "music"
      2) "his"
      3) "sports"
      
    • 将交集、并集、差集的结果保存

      sinterstore destination key [key ...]

      sunionstore destination key [key ...]

      sdiffstore destination key [key ...]

      127.0.0.1:6379> SINTERSTORE user:1_2:inter user:1:follow user:2:follow
      (integer) 1
      127.0.0.1:6379> type user:1_2:inter
      set
      127.0.0.1:6379> SMEMBERS user:1_2:inter
      1) "it"
      

    集合常用命令时间复杂度

    命令时间复杂度
    sadd key member [member …]O(k),k是元素个数
    srem key member [member …]O(k),k是元素个数
    scard keyO(1)
    sismember key memberO(1)
    srandmember key [count]O(count)
    spop keyO(1)
    smembers keyO(n),n是元素总数
    sinter key [key …] || sinterstoreO(m*k),k是多个集合中元素最少的个数,m是键个数
    sunion key [key …] || sunionstoreO(k),k是多个集合元素个数和
    sdiff key [key …] || sdiffstoreO(k),k是多个集合元素个数和
5.有序集合

它保留了集合不能有重复成员的特性,增加了有序集合的元素可以排序。但是它和列表使用索引下标作为排序依据不同的是,它给每个元素设置一个分数(score)作为培训的依据。

列表、集合、有序集合三者的异同点

数据结构是否允许重复元素是否有序有序实现方式应用场景
列表索引下标时间轴、消息队列等
集合标签、社交等
有序集合分值(score)排行榜系统、社交等

命令

  • 集合内

    • 添加成员

      zadd key score member [score member ...]

      127.0.0.1:6379> zadd user:ranking 251 tom
      (integer) 1
      127.0.0.1:6379> zadd user:ranking 251 tom
      (integer) 0 #返回结果代表成功添加成员的个数
      

      有关zadd命令有2点需要注意:

      Redis 3.2 为 zadd 命令添加了nx、xx、ch、incr四个选项

      • nx:member必须不存在,才可以设置成功,用于添加
      • xx:member必须存在,才可以设置成功,用于更新
      • ch:返回此次操作后,有序集合元素和分数发生变化的个数
      • incr:对score做增加,相当于后面介绍的zincrby

      有序集合相比集合提供了排序字段,但是也产生了代价,zadd的时间复杂度为O(log(n)),sadd的时间复杂度为O(1)。

    • 计算成员个数

      zcard key

    • 计算某个成员的分数

      zscore key member

      127.0.0.1:6379> ZSCORE user:ranking tom
      "252"
      127.0.0.1:6379> ZSCORE user:ranking tomss
      (nil)  #如果成员不存在返回nil
      
    • 计算成员的排名

      zrank key member 分数低到高返回排名(排序从0开始计算)

      zrevrank key member 分数从高到低返回排名(排序从0开始计算)

    • 删除成员

      zrem key member [member...]

      127.0.0.1:6379> zrem user:ranking mike
      (integer) 1 #返回结果为成功删除的个数
      
    • 增加成员的分数

      zincrby key increment member

      127.0.0.1:6379> zscore user:ranking tom
      "252"  #当前数据库中的分数
      127.0.0.1:6379> zincrby user:ranking 8 tom
      "260" #增加8分后返回的结果
      
    • 返回指定排名范围的成员

      zrange key start end [withscores]

      zrevrange key start end [withscores]

      有序集合是按照分值排名的,zrange是从低到高返回,zrevrange反之。

      如果加上 withscores选项,同时会返回成员的分数:

      127.0.0.1:6379> ZRANGE  user:ranking 0 2   #返回排名最低的3个成员
      1) "kris"
      2) "frank"
      3) "tim"
      127.0.0.1:6379> ZRANGE  user:ranking 0 2 withscores
      1) "kris"
      2) "1"
      3) "frank"
      4) "200"
      5) "tim"
      6) "220"
      127.0.0.1:6379> ZREVRANGE  user:ranking 0 2 withscores
      1) "tom"
      2) "260"
      3) "tom3"
      4) "252"
      5) "martin"
      6) "250"
      
    • 返回指定分数范围的成员

      zrangebyscore key min max [withscores] [limit offset count]

      zrevrangebyscore key max min [withscores] [limit offset count]

      zrangebyscore 按照分数从低到高返回,zrevrangebyscore反之。

      withscores 会同时返回每个成员的分数

      limit offset count 选项可以限制输出的起始位置和个数

      min和max 支持开区间(小括号)和闭区间(中括号),-inf 和 +inf 分别代表无限小和无限大

      127.0.0.1:6379> ZRANGEBYSCORE user:ranking 200 +inf withscores
       1) "frank"
       2) "200"
       3) "tim"
       4) "220"
       5) "martin"
       6) "250"
       7) "tom3"
       8) "252"
       9) "tom"
      10) "260"
      127.0.0.1:6379> ZRANGEBYSCORE user:ranking 200 +inf withscores limit 2 4
      1) "martin"
      2) "250"
      3) "tom3"
      4) "252"
      5) "tom"
      6) "260"
      
    • 返回指定分数范围成员个数

      zcount key min max

    • 删除指定排名内的升序元素

      zremrangebyrank key start end

      127.0.0.1:6379> ZREMRANGEBYRANK user:ranking 0 2
      (integer) 3  #删除前3个元素
      
    • 删除指定分数范围的成员

      zremrangebyscore key min max

      127.0.0.1:6379> ZREMRANGEBYSCORE user:ranking (250 +inf  #将250分以上的成员全部删除,返回结果为成功删除的个数
      (integer) 2
      
  • 集合间的操作

    • 交集

      zinterstore destination numkeys key [key ...] [weights weight] [aggregate sum|min|max]

      • destination:交集计算结果保存到这个键
      • numkeys:需要做交集计算键的个数
      • key[key…]:需要做交集计算的键
      • weights weight:每个键的权重,在做交集计算时,每个键中的每个member会将自己分数乘以这个权重,每个键的权重默认是1。
      • aggregate sum|min|max:计算成员交集后,分值按照sum(和)、min(最小值)、max(最大值)做汇总,默认值是sum。

      下面将对user:ranking:1和user:ranking:2做交集,weights和aggregate使用了默认值,可以看到目标键user:ranking:1_inter_2对分值做了sum操作

      127.0.0.1:6379> zadd user:ranking:1 1 kris 91 mike 200 frank 220 tim 250 martin 251 tom
      (integer) 6
      127.0.0.1:6379> zadd user:ranking:2 8 james 77 mike 625 martin 888 tom
      (integer) 4
      127.0.0.1:6379> ZINTERSTORE user:ranking:1_inter_2 2 user:ranking:1 user:ranking:2 
      (integer) 3
      127.0.0.1:6379> zrange user:ranking:1_inter_2 0 -1 withscores
      1) "mike"
      2) "168"
      3) "martin"
      4) "875"
      5) "tom"
      6) "1139"
      

      如果想让user:ranking:2的权重变为0.5,并且聚合效果使用max,可以执行如下操作:

      127.0.0.1:6379> ZINTERSTORE user:ranking:1_inter_2 2 user:ranking:1 user:ranking:2 weights 1 0.5 aggregate max
      (integer) 3
      127.0.0.1:6379> zrange user:ranking:1_inter_2 0 -1 withscores
      1) "mike"
      2) "91"
      3) "martin"
      4) "312.5"
      5) "tom"
      6) "444"
      
    • 并集

      zunionstore destination numkeys key [key ...] [weights weight] [aggregate sum|min|max]

    有序集合命令的时间复杂度

    命令时间复杂度
    zadd key score member [score member …]O(kxlog(n)),k是添加成员的个数,n是当前有序集合成员个数
    zcard keyO(1)
    zscore key memberO(1)
    zrank/zrevrank key memberO(log(n)),n是当前有序集合成员个数
    zrem key member [member …]O(k*log(n)),k是删除成员的个数,n是当前有序集合成员个数
    zincrby key increment memberO(log(n)),n是当前有序集合成员个数
    zrange/zrevrange key start end [withscores]O(log(n)+k),k是要获取的成员个数,n是当前有序集合成员个数
    zrangebyscore/zrevrangebyscore key min/max max/min [withscores]O(log(n)+k),k是要获取的成员个数,n是当前有序集合成员个数
    zcount key min maxO(log(n)),n是当前有序集合成员个数
    zremrangebyrank key start endO(log(n)+k),k是要删除的成员个数,n是当前有序集合成员个数
    zremrangebyscore key min maxO(log(n)+k),k是要删除的成员个数,n是当前有序集合成员个数
    zinterstore destination numkeys key [key …]O(nxk)+O(mxlog(m)),n是成员数量最小的有序集合成员个数,k是有序集合的个数,m是结果集中成员个数
    zunionstore destination numkeys key [key …]O(n)+O(mxlog(m)),n是所有有序集合成员个数和,m是结果集中成员个数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值