时间复杂度: O(1)

将一个或多个值 value 插入到列表 key 的表头。如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表头: 比如说,对空列表 mylist 执行命令 LPUSH mylist a b c ,列表的值将是 c b a ,这等同于原子性地执行 LPUSH mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三个命令。如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。当 key 存在但不是列表类型时,返回一个错误。正常返回列表的长度。

# 加入单个元素redis> LPUSH languages python(integer) 1# 加入重复元素redis> LPUSH languages python(integer) 2redis> LRANGE languages 0 -1     # 列表允许重复元素1) "python"2) "python"# 加入多个元素redis> LPUSH mylist a b c(integer) 3redis> LRANGE mylist 0 -11) "c"2) "b"3) "a"

2.RPUSH

RPUSH key value [value …]

时间复杂度: O(1)

将一个或多个值 value 插入到列表 key 的表尾(最右边)。如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表尾:比如对一个空列表 mylist 执行 RPUSH mylist a b c ,得出的结果列表为 a b c ,等同于执行命令 RPUSH mylist a 、 RPUSH mylist b 、 RPUSH mylist c 。如果 key 不存在,一个空列表会被创建并执行 RPUSH 操作。当 key 存在但不是列表类型时,返回一个错误。正常返回列表的长度。

# 添加单个元素redis> RPUSH languages c(integer) 1# 添加重复元素redis> RPUSH languages c(integer) 2redis> LRANGE languages 0 -1 # 列表允许重复元素1) "c"2) "c"# 添加多个元素redis> RPUSH mylist a b c(integer) 3redis> LRANGE mylist 0 -11) "a"2) "b"3) "c"

3.LINSERT

LINSERT key BEFORE|AFTER pivot value

时间复杂度: O(N), N 为寻找 pivot 过程中经过的元素数量。

将值 value 插入到列表 key 当中,位于值 pivot 之前或之后。当 pivot 不存在于列表 key 时,不执行任何操作。当 key 不存在时, key 被视为空列表,不执行任何操作。如果 key 不是列表类型,返回一个错误。如果命令执行成功,返回插入操作完成之后,列表的长度。 如果没有找到 pivot ,返回 -1 。 如果 key 不存在或为空列表,返回 0 。

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

4.LPOP

LPOP key

时间复杂度: O(1)

移除并返回列表 key 的头元素。返回列表的头元素。 当 key 不存在时,返回 nil 。

redis> LLEN course(integer) 0redis> RPUSH course algorithm001(integer) 1redis> RPUSH course c++101(integer) 2redis> LPOP course  # 移除头元素"algorithm001"

5.RPOP

RPOP key

时间复杂度: O(1)

移除并返回列表 key 的尾元素。返回列表的尾元素。 当 key 不存在时,返回 nil 。

redis> RPUSH mylist "one"(integer) 1redis> RPUSH mylist "two"(integer) 2redis> RPUSH mylist "three"(integer) 3redis> RPOP mylist           # 返回被弹出的元素"three"redis> LRANGE mylist 0 -1    # 列表剩下的元素1) "one"2) "two"

6.LREM

LREM key count value

时间复杂度: O(N), N 为列表的长度。

根据参数 count 的值,移除列表中与参数 value 相等的元素。

count 的值可以是以下几种:

count > 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。

count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。

count = 0 : 移除表中所有与 value 相等的值。

返回值被移除元素的数量。 因为不存在的 key 被视作空表(empty list),所以当 key 不存在时, LREM 命令总是返回 0 。

# 先创建一个表,内容排列是# morning hello morning helllo morningredis> LPUSH greet "morning"(integer) 1redis> LPUSH greet "hello"(integer) 2redis> LPUSH greet "morning"(integer) 3redis> LPUSH greet "hello"(integer) 4redis> LPUSH greet "morning"(integer) 5redis> LRANGE greet 0 4         # 查看所有元素1) "morning"2) "hello"3) "morning"4) "hello"5) "morning"redis> LREM greet 2 morning     # 移除从表头到表尾,最先发现的两个 morning(integer) 2                     # 两个元素被移除redis> LLEN greet               # 还剩 3 个元素(integer) 3redis> LRANGE greet 0 21) "hello"2) "hello"3) "morning"redis> LREM greet -1 morning    # 移除从表尾到表头,第一个 morning(integer) 1redis> LLEN greet               # 剩下两个元素(integer) 2redis> LRANGE greet 0 11) "hello"2) "hello"redis> LREM greet 0 hello      # 移除表中所有 hello(integer) 2                    # 两个 hello 被移除redis> LLEN greet(integer) 0

7.LTRIMLTRIM key start stop时间复杂度: O(N), N 为被移除的元素的数量。对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除。

这个从字面意思不容易理解 ,我们图解一下:

运行命令

Itrim listkey 1 4

结果

上面的图能一下子让你看懂,它是做什么的了,下面演示一下

# 情况 1: 常见情况, start 和 stop 都在列表的索引范围之内redis> LRANGE alpha 0 -1       # alpha 是一个包含 5 个字符串的列表1) "h"2) "e"3) "l"4) "l"5) "o"redis> LTRIM alpha 1 -1        # 删除 alpha 列表索引为 0 的元素OKredis> LRANGE alpha 0 -1       # "h" 被删除了1) "e"2) "l"3) "l"4) "o"# 情况 2: stop 比列表的最大下标还要大redis> LTRIM alpha 1 10086     # 保留 alpha 列表索引 1 至索引 10086 上的元素OKredis> LRANGE alpha 0 -1       # 只有索引 0 上的元素 "e" 被删除了,其他元素还在1) "l"2) "l"3) "o"# 情况 3: start 和 stop 都比列表的最大下标要大,并且 start < stopredis> LTRIM alpha 10086 123321OKredis> LRANGE alpha 0 -1        # 列表被清空(empty list or set)# 情况 4: start 和 stop 都比列表的最大下标要大,并且 start > stopredis> RPUSH new-alpha "h" "e" "l" "l" "o"     # 重新建立一个新列表(integer) 5redis> LRANGE new-alpha 0 -11) "h"2) "e"3) "l"4) "l"5) "o"redis> LTRIM new-alpha 123321 10086    # 执行 LTRIMOKredis> LRANGE new-alpha 0 -1           # 同样被清空(empty list or set)

8.LINDEX

LINDEX key index

时间复杂度:O(N), N 为到达下标 index 过程中经过的元素数量。因此,对列表的头元素和尾元素执行 LINDEX 命令,复杂度为O(1)。

返回列表 key 中,下标为 index 的元素。下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。如果 key 不是列表类型,返回一个错误。返回列表中下标为 index 的元素。 如果 index 参数的值不在列表的区间范围内(out of range),返回 nil 。

redis> LPUSH mylist "World"(integer) 1redis> LPUSH mylist "Hello"(integer) 2redis> LINDEX mylist 0"Hello"redis> LINDEX mylist -1"World"redis> LINDEX mylist 3        # index不在 mylist 的区间范围内(nil)

9.LLEN

LLEN key

时间复杂度: O(1)

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

# 空列表redis> LLEN job(integer) 0# 非空列表redis> LPUSH job "cook food"(integer) 1redis> LPUSH job "have lunch"(integer) 2redis> LLEN job(integer) 2

10.LSET

LSET key index value

时间复杂度:对头元素或尾元素进行 LSET 操作,复杂度为 O(1)。其他情况下,为 O(N), N 为列表的长度。

将列表 key 下标为 index 的元素的值设置为 value 。当 index 参数超出范围,或对一个空列表( key 不存在)进行 LSET 时,返回一个错误。操作成功返回 ok ,否则返回错误信息。

# 对空列表(key 不存在)进行 LSETredis> EXISTS list(integer) 0redis> LSET list 0 item(error) ERR no such key# 对非空列表进行 LSETredis> LPUSH job "cook food"(integer) 1redis> LRANGE job 0 01) "cook food"redis> LSET job 0 "play game"OKredis> LRANGE job  0 01) "play game"# index 超出范围redis> LLEN list                    # 列表长度为 1(integer) 1redis> LSET list 3 'out of range'(error) ERR index out of range

下面我们看一下它的应用:

最典型的就是时间轴

以CSDN APP的bink推荐为例,

当有一个bink发表的时候,要将这个blink插入时间轴第一个位置。可以是LPUSH的操作。这样子每次你就能从列表中,看到最新的blink,越往下时间越远。

11. BLPOP

BLPOP key [key …] timeout

时间复杂度: O(1)

BLPOP 是列表的阻塞式(blocking)弹出原语。它是 LPOP key 命令的阻塞版本,当给定列表内没有任何元素可供弹出的时候,连接将被 BLPOP 命令阻塞,直到等待超时或发现可弹出元素为止。当给定多个 key 参数时,按参数 key 的先后顺序依次检查各个列表,弹出第一个非空列表的头元素。

12.BRPOP

BRPOP key [key …] timeout

时间复杂度: O(1)

BRPOP 是列表的阻塞式(blocking)弹出原语。它是 RPOP key 命令的阻塞版本,当给定列表内没有任何元素可供弹出的时候,连接将被 BRPOP 命令阻塞,直到等待超时或发现可弹出元素为止。当给定多个 key 参数时,按参数 key 的先后顺序依次检查各个列表,弹出第一个非空列表的尾部元素。

下面再看一个Redis的应用:简易的消息队列

Redis 的简易的消息队列不是专业的消息队列,它没有⾮常多的⾼级特性,没有 ack 保证,如果对消息的可靠性有着极致的追求,那么它就不适合使⽤。但是对于那些只有⼀组消费者的消息队列,使⽤ Redis 就可以⾮常轻松的搞定。

后面会谈到Redis的高级特性–发布订阅。这个也是消息队列

异步消息队列

Redis 的 list(列表) 数据结构常⽤来作为异步消息队列使⽤,使⽤rpush/lpush操作⼊队列,使⽤lpop 和 rpop来出队列。

客户端是通过队列的 pop 操作来获取消息,然后进⾏处理。处理完了再接着获取消息,再进⾏处理。如此循环往复。

但是如果队列空了,客户端就会陷⼊ pop 的死循环,不停地 pop。这样不但拉⾼了客户端的 CPU,redis 的 QPS(每秒执行次数) 也会被拉⾼,如果这样不断轮询的客户端有⼏⼗来个,资源被大量无效占用。通常我们使⽤ sleep 来解决这个问题,让线程睡⼀会,睡个 1s 钟就可以了。不但客户端的 CPU 能降下来,Redis 的 QPS 也降下来了。不过这样也并不是很好的手段,

延时队列

运用blpop/brpop构建延时队列是一个非常好的方式。这两个指令的前缀字符b代表的是blocking,也就是阻塞读。

阻塞读在队列没有数据的时候,会⽴即进⼊休眠状态,⼀旦数据到来,则⽴刻醒过来。消息的延迟⼏乎为零。不过这也带来一个问题:空闲连接。如果线程⼀直阻塞在哪⾥,Redis 的客户端连接就成了闲置连接,闲置过久,服务器⼀般会主动断开连接,减少闲置资源占⽤。这个时候blpop/brpop会抛出异常来。编写客户端消费者的时候要⼩⼼,注意捕获异常,还要重试。

在上面简单说明分布式锁的时候,没有提到客户端在处理请求时加锁没加成功怎么办。

对于这种情况,有 3 种策略来处理加锁失败:

直接抛出异常,通知⽤户稍后重试;

sleep ⼀会再重试;

将请求转移⾄延时队列,过⼀会再试;

(七)Set集合

Redis 的集合相当于 Java 语⾔⾥⾯的 HashSet,它内部的键值对是⽆序的唯⼀的。它的内部实现相当于⼀个特殊的字典,字典中所有的value 都是⼀个值NULL。当集合中最后⼀个元素移除之后,数据结构⾃动删除,内存被回收。

插入之后,元素的先后位置是不固定的,遍历的时候无序。

下面我们看一下它的API

1.SADD

SADD key member [member …]

时间复杂度: O(N), N 是被添加的元素的数量。

将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。假如 key 不存在,则创建一个只包含 member 元素作成员的集合。当 key 不是集合类型时,返回一个错误。正常返回被添加到集合中的新元素的数量,不包括被忽略的元素。

# 添加单个元素redis> SADD bbs "discuz.net"(integer) 1# 添加重复元素redis> SADD bbs "discuz.net"(integer) 0# 添加多个元素redis> SADD bbs "tianya.cn" "groups.google.com"(integer) 2redis> SMEMBERS bbs1) "discuz.net"2) "groups.google.com"3) "tianya.cn"

2.SCARD

SCARD key

时间复杂度: O(1)

返回集合 key 的基数(集合中元素的数量)。当 key 不存在时,返回 0 。

redis> SADD tool pc printer phone(integer) 3redis> SCARD tool   # 非空集合(integer) 3redis> DEL tool(integer) 1redis> SCARD tool   # 空集合(integer) 0

3.SMEMBERS

SMEMBERS key

时间复杂度: O(N), N 为集合的基数。返回集合 key 中的所有成员。不存在的 key 被视为空集合。

# key 不存在或集合为空redis> EXISTS not_exists_key(integer) 0redis> SMEMBERS not_exists_key(empty list or set)# 非空集合redis> SADD language Ruby Python Clojure(integer) 3redis> SMEMBERS language1) "Python"2) "Ruby"3) "Clojure"

可以看出来,插入顺序,与返回顺序不同。要小心使用

4.srandmember和spop

SRANDMEMBER key [count]

时间复杂度: 只提供 key 参数时为 O(1) 。如果提供了 count 参数,那么为 O(N) ,N 为返回数组的元素个数。

如果命令执行时,只提供了 key 参数,那么返回集合中的一个随机元素。

从 Redis 2.6 版本开始, SRANDMEMBER 命令接受可选的 count 参数:

如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。

如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。

# 添加元素redis> SADD fruit apple banana cherry(integer) 3# 只给定 key 参数,返回一个随机元素redis> SRANDMEMBER fruit"cherry"redis> SRANDMEMBER fruit"apple"# 给定 3 为 count 参数,返回 3 个随机元素# 每个随机元素都不相同redis> SRANDMEMBER fruit 31) "apple"2) "banana"3) "cherry"# 给定 -3 为 count 参数,返回 3 个随机元素# 元素可能会重复出现多次redis> SRANDMEMBER fruit -31) "banana"2) "cherry"3) "apple"redis> SRANDMEMBER fruit -31) "apple"2) "apple"3) "cherry"# 如果 count 是整数,且大于等于集合基数,那么返回整个集合redis> SRANDMEMBER fruit 101) "apple"2) "banana"3) "cherry"# 如果 count 是负数,且 count 的绝对值大于集合的基数# 那么返回的数组的长度为 count 的绝对值redis> SRANDMEMBER fruit -101) "banana"2) "apple"3) "banana"4) "cherry"5) "apple"6) "apple"7) "cherry"8) "apple"9) "apple"10) "banana"# SRANDMEMBER 并不会修改集合内容redis> SMEMBERS fruit1) "apple"2) "cherry"3) "banana"# 集合为空时返回 nil 或者空数组redis> SRANDMEMBER not-exists(nil)redis> SRANDMEMBER not-eixsts 10(empty list or set)讨论 

SPOP key

时间复杂度: O(1)

移除并返回集合中的一个随机元素。如果只想获取一个随机元素,但不想该元素从集合中被移除的话,可以使用 SRANDMEMBER key [count] 命令。

redis> SMEMBERS db1) "MySQL"2) "MongoDB"3) "Redis"redis> SPOP db"Redis"redis> SMEMBERS db1) "MySQL"2) "MongoDB"redis> SPOP db"MySQL"redis> SMEMBERS db1) "MongoDB"

spop从集合弹出 srandmembe不会破坏集合

下面我们看看应用:CSDN的点赞状态就可以用set集合进行处理。类似于点赞、踩这种场景,状态不重复,就可以set集合。

还有CSDN发表博文的时候,给文章打标签,标签就可以存储在set集合中

除此之外,set 结构可以⽤来存储活动中奖的⽤户 ID,因为有去重功能,可以保证同⼀个⽤户不会中奖两次。

下面看看集合间的API

5.sdiff sinter sunion

分别是差集 交集 并集。

这个玩法就比较多了。

比如微信上,将每个人拥有的群id都存储在每个人的set集合中

我们只要对两个人的集合取交集,就可以得出 我和他的公共群聊的个数。

(八)zset (有序集合)

zset 类似于 Java 的 SortedSet 和HashMap的结合体,

⼀⽅⾯它是⼀个 set,保证了内部 value 的唯⼀性,另⼀⽅⾯它可以给每个 value 赋予⼀个 score,代表这个 value 的排序权重。它的内部实现⽤的是⼀种叫做「跳跃列表」的数据结构。zset 中最后⼀个 value 被移除后,数据结构⾃动删除,内存被回收。

有序集合结构:

key: user

集合 VS 有序集合

集合:无重复元素、无序、element

有序集合 : 无重复元素、有序、element + score

有序集合相比集合时间复杂度较高

1.ZADD

ZADD key score member [[score member] [score member] …]

时间复杂度: O(M*log(N)), N 是有序集的基数, M 为成功添加的新成员的数量。

将一个或多个 member 元素及其 score 值加入到有序集 key 当中。如果某个 member 已经是有序集的成员,那么更新这个 member 的 score 值,并通过重新插入这个 member 元素,来保证该 member 在正确的位置上。score 值可以是整数值或双精度浮点数。如果 key 不存在,则创建一个空的有序集并执行 ZADD 操作。当 key 存在但不是有序集类型时,返回一个错误。正常返回被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员。

# 添加单个元素redis> ZADD page_rank 10 google.com(integer) 1# 添加多个元素redis> ZADD page_rank 9 baidu.com 8 bing.com(integer) 2redis> ZRANGE page_rank 0 -1 WITHSCORES1) "bing.com"2) "8"3) "baidu.com"4) "9"5) "google.com"6) "10"# 添加已存在元素,且 score 值不变redis> ZADD page_rank 10 google.com(integer) 0redis> ZRANGE page_rank 0 -1 WITHSCORES  # 没有改变1) "bing.com"2) "8"3) "baidu.com"4) "9"5) "google.com"6) "10"# 添加已存在元素,但是改变 score 值redis> ZADD page_rank 6 bing.com(integer) 0redis> ZRANGE page_rank 0 -1 WITHSCORES  # bing.com 元素的 score 值被改变1) "bing.com"2) "6"3) "baidu.com"4) "9"5) "google.com"6) "10"

2.ZREM

ZREM key member [member …]

时间复杂度: O(M*log(N)), N 为有序集的基数, M 为被成功移除的成员的数量。

移除有序集 key 中的一个或多个成员,不存在的成员将被忽略。当 key 存在但不是有序集类型时,返回一个错误。正常返回值

被成功移除的成员的数量,不包括被忽略的成员。

# 测试数据redis> ZRANGE page_rank 0 -1 WITHSCORES1) "bing.com"2) "8"3) "baidu.com"4) "9"5) "google.com"6) "10"# 移除单个元素redis> ZREM page_rank google.com(integer) 1redis> ZRANGE page_rank 0 -1 WITHSCORES1) "bing.com"2) "8"3) "baidu.com"4) "9"# 移除多个元素redis> ZREM page_rank baidu.com bing.com(integer) 2redis> ZRANGE page_rank 0 -1 WITHSCORES(empty list or set)# 移除不存在元素redis> ZREM page_rank non-exists-element(integer) 0

3.zscore

ZSCORE key member

时间复杂度: O(1)

返回有序集 key 中,成员 member 的 score 值(member 成员的 score 值,以字符串形式表示)。如果 member 元素不是有序集 key 的成员,或 key 不存在,返回 nil 。

1) "tom"2) "2000"3) "peter"4) "3500"5) "jack"6) "5000"redis> ZSCORE salary peter              # 注意返回值是字符串"3500"

4.ZINCRBY

ZINCRBY key increment member

时间复杂度: O(log(N))

为有序集 key 的成员 member 的 score 值加上增量 increment 。可以通过传递一个负数值 increment ,让 score 减去相应的值,比如 ZINCRBY key -5 member ,就是让 member 的 score 值减去 5 。当 key 不存在,或 member 不是 key 的成员时, ZINCRBY key increment member 等同于 ZADD key increment member 。当 key 不是有序集类型时,返回一个错误。score 值可以是整数值或双精度浮点数。正常返回值为member 成员的新 score 值,以字符串形式表示。

redis> ZSCORE salary tom"2000"redis> ZINCRBY salary 2000 tom   # tom 加薪啦!"4000"

5.zcard

ZCARD key

时间复杂度: O(1)

当 key 存在且是有序集类型时,返回有序集的基数。 当 key 不存在时,返回 0 。

redis > ZADD salary 2000 tom    # 添加一个成员(integer) 1redis > ZCARD salary(integer) 1redis > ZADD salary 5000 jack   # 再添加一个成员(integer) 1redis > ZCARD salary(integer) 2redis > EXISTS non_exists_key   # 对不存在的 key 进行 ZCARD 操作(integer) 0redis > ZCARD non_exists_key(integer) 0

6.ZRANGE

ZRANGE key start stop [WITHSCORES]

时间复杂度: O(log(N)+M), N 为有序集的基数,而 M 为结果集的基数。

返回有序集 key 中,指定区间内的成员。其中成员的位置按 score 值递增(从小到大)来排序。具有相同 score 值的成员按字典序(lexicographical order )来排列。如果你需要成员按 score 值递减(从大到小)来排列,请使用 ZREVRANGE key start stop [WITHSCORES] 命令。下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。 你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。超出范围的下标并不会引起错误。 比如说,当 start 的值比有序集的最大下标还要大,或是 start > stop 时, ZRANGE 命令只是简单地返回一个空列表。 另一方面,假如 stop 参数的值比有序集的最大下标还要大,那么 Redis 将 stop 当作最大下标来处理。可以通过使用 WITHSCORES 选项,来让成员和它的 score 值一并返回,返回列表以 value1,score1, …, valueN,scoreN 的格式表示。 客户端库可能会返回一些更复杂的数据类型,比如数组、元组等。返回为指定区间内,带有 score 值(可选)的有序集成员的列表。

redis > ZRANGE salary 0 -1 WITHSCORES             # 显示整个有序集成员1) "jack"2) "3500"3) "tom"4) "5000"5) "boss"6) "10086"redis > ZRANGE salary 1 2 WITHSCORES              # 显示有序集下标区间 1 至 2 的成员1) "tom"2) "5000"3) "boss"4) "10086"redis > ZRANGE salary 0 200000 WITHSCORES         # 测试 end 下标超出最大下标时的情况1) "jack"2) "3500"3) "tom"4) "5000"5) "boss"6) "10086"redis > ZRANGE salary 200000 3000000 WITHSCORES   # 测试当给定区间不存在于有序集时的情况(empty list or set)

7.ZRANGEBYSCOR

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

时间复杂度: O(log(N)+M), N 为有序集的基数, M 为被结果集的基数。

返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。具有相同 score 值的成员按字典序(lexicographical order)来排列(该属性是有序集提供的,不需要额外的计算)。

可选的 LIMIT 参数指定返回结果的数量及区间(就像SQL中的 SELECT LIMIT offset, count ),注意当 offset 很大时,定位 offset 的操作可能需要遍历整个有序集,此过程最坏复杂度为 O(N) 时间。

可选的 WITHSCORES 参数决定结果集是单单返回有序集的成员,还是将有序集成员及其 score 值一起返回。 该选项自 Redis 2.0 版本起可用。

区间及无限

min 和 max 可以是 -inf 和 +inf ,这样一来,你就可以在不知道有序集的最低和最高 score 值的情况下,使用ZRANGEBYSCORE 这类命令。默认情况下,区间的取值使用闭区间 (小于等于或大于等于),你也可以通过给参数前增加 ( 符号来使用可选的开区间 (小于或大于)。

(integer) 0redis> ZADD salary 5000 tom(integer) 0redis> ZADD salary 12000 peter(integer) 0redis> ZRANGEBYSCORE salary -inf +inf               # 显示整个有序集1) "jack"2) "tom"3) "peter"redis> ZRANGEBYSCORE salary -inf +inf WITHSCORES    # 显示整个有序集及成员的 score 值1) "jack"2) "2500"3) "tom"4) "5000"5) "peter"6) "12000"redis> ZRANGEBYSCORE salary -inf 5000 WITHSCORES    # 显示工资 <=5000 的所有成员1) "jack"2) "2500"3) "tom"4) "5000"redis> ZRANGEBYSCORE salary (5000 400000            # 显示工资大于 5000 小于等于 400000 的成员1) "peter"

8.zcount

ZCOUNT key min max

时间复杂度: O(log(N)), N 为有序集的基数。

返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量。关于参数 min 和 max 的详细使用方法,请参考 ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] 命令。返回值为score 值在 min 和 max 之间的成员的数量。

redis> ZRANGE salary 0 -1 WITHSCORES    # 测试数据1) "jack"2) "2000"3) "peter"4) "3500"5) "tom"6) "5000"redis> ZCOUNT salary 2000 5000          # 计算薪水在 2000-5000 之间的人数(integer) 3redis> ZCOUNT salary 3000 5000          # 计算薪水在 3000-5000 之间的人数(integer) 2

9.zremrangebyrank

ZREMRANGEBYRANK key start stop

时间复杂度: O(log(N)+M), N 为有序集的基数,而 M 为被移除成员的数量。

移除有序集 key 中,指定排名(rank)区间内的所有成员。区间分别以下标参数 start 和 stop 指出,包含 start 和 stop 在内。

下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。 你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。返回值为被移除成员的数量。

redis> ZADD salary 2000 jack(integer) 1redis> ZADD salary 5000 tom(integer) 1redis> ZADD salary 3500 peter(integer) 1redis> ZREMRANGEBYRANK salary 0 1       # 移除下标 0 至 1 区间内的成员(integer) 2redis> ZRANGE salary 0 -1 WITHSCORES    # 有序集只剩下一个成员1) "tom"2) "5000"

10.zremrangebyscore

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

时间复杂度: O(log(N)+M), N 为有序集的基数, M 为结果集的基数。

返回有序集 key 中, score 值介于 max 和 min 之间(默认包括等于 max 或 min )的所有的成员。有序集成员按 score 值递减(从大到小)的次序排列。具有相同 score 值的成员按字典序的逆序(reverse lexicographical order )排列。

除了成员按 score 值递减的次序排列这一点外, ZREVRANGEBYSCORE 命令的其他方面和 ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count] 命令一样。

返回值为指定区间内,带有 score 值(可选)的有序集成员的列表。

redis > ZADD salary 10086 jack(integer) 1redis > ZADD salary 5000 tom(integer) 1redis > ZADD salary 7500 peter(integer) 1redis > ZADD salary 3500 joe(integer) 1redis > ZREVRANGEBYSCORE salary +inf -inf   # 逆序排列所有成员1) "jack"2) "peter"3) "tom"4) "joe"redis > ZREVRANGEBYSCORE salary 10000 2000  # 逆序排列薪水介于 10000 和 2000 之间的成员1) "peter"2) "tom"3) "joe"

我们看一下它具体的应用:首先最容易想到的就是排行榜了。(博主在long long ago 也曾第一过)

类似的,zset 还可以⽤来存储学⽣的成绩,value 值是学⽣的 ID,score 是他的考试成绩。我们可以对成绩按分数进行排序就可以得到他的名次。

除此之外,zset 可以⽤来存粉丝列表,value 值是粉丝的⽤户 ID,score 是关注时间。我们可以对粉丝列表按关注时间进行排序。

不太常见API有这些,文章上面已经给大家推荐查看API的网站了,用到的时候查一查哈

◆ zrevrank

◆ zrevrange

◆ zrevrangebyscore

◆ interstore

◆ zunionstore

上面的API可以分成这三类

三、Redis 客户端操作

带大家过一遍Redis 的API之后,这部分非常非常简单了。

所有语言的操作,其实都是对Redis API的封装,封装前的东西你都知道了,封装后的不是易如反掌?

以Java为例吧,基于Java语言的客户端比较热的是Jedis

在连接方面有两种方式,一种是直连、一种是线程池(一般都要用到线程池)

直连方式

// 1.生成一个 Jedis对象,这个对象负责和指定Reds节点进行通信Jedis jedis = new Jedis("localhost", 6379);// Sting  set get 操作jedis.set("Jedis", "hello jedis!");jedis.get("Jedis");// 对结果进行自增jedis.incr("counter")

构造方法最多有四个参数

hash操作

jedis hset("myhash",f1",v1);jedis hset("myhash",f2,v2);// 输出结果:{1=v1,f2=V2}jedis.hgetAll(myhash");

是不是很熟悉,其他的类似。

Jedis连接池直连的弊端很明显:消耗资源。如果在不同方面,频繁用到Redis,编写程序也很麻烦。

所以,连接池是非常重要的的。

方案对比

// 初始化 Jedis连接池,通常来讲 Jedis Pool是单例的。 GenericObjectPoolConf poolConfig new GenericObjectPoolConfigO Jedis Pool jedis Pool new JedisPool(poolConfig, 127.0.0. 1",6379);

简单使用:

Jedis jedis = null;try{//1.从连接池获取 jedis对象jedis = jedisPool.getResource();//2.执行操作jedis set(hello","world");} catch(Exception e){eprintStackTrace();}finally {if (jedis != null)//如果使用 JedisPool,cose操作不是关闭连接,代表归还连接池jedis closedjedis.close();}}

go redis 清空所有值_【大厂面试】面试官看了赞不绝口的Redis笔记二相关推荐

  1. 【大厂面试】面试官看了赞不绝口的Redis笔记

    文章目录 一.Redis简介 二.Redis API的使用和理解 (一)通用命令 (二)单线程架构 (三)数据结构和内部编码 (四)字符串 (五)hash (字典) (六)列表 (七)Set集合 (八 ...

  2. 【大厂面试】面试官看了赞不绝口的Redis笔记(二)

    文章目录 说明 四.Redis的其他功能 (一)慢查询 (二)pipeline (三)发布订阅 (四)Bitmap (五)HyperLogLog (六)GEO 五.Redis持久化的取舍和选择 (一) ...

  3. 红黑树 键值_大厂面试官:说一下JDK1.8 HashMap有哪些亮点?

    上篇我们介绍了JDK1.7版的HashMap,今天我们来讲解下JDK1.8版的HashMap. JDK1.7的实现大家看出有没有需要优化的地方? 其实一个很明显的地方就是:当 Hash 冲突严重时,在 ...

  4. java 实体类包含list 怎么取值_舅舅是面试官,偷偷告诉你们面试官最爱问的Java面试题...

    2015 年,因为工作岗位的变动,舅舅开始负责给集团招聘一些技术人员,出于对公司的负责,也为了更好的胜任技术经理的职位,在面试的这件事上,舅舅做了大量的"功课",首先研究了几乎所有 ...

  5. redis 清空db下_如何清空redis中的数据

    Redis Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key ). 语法 redis Flushall 命令基本语法如下:redis 127.0.0.1:63 ...

  6. JAVA窗口sin值_大厂经典笔试题—LeetCode03无重复字符的最长子串(滑动窗口)

    题目描述 原创作者:bigsai,长期维护不易,如有收获还请点赞.收藏支持! 题目描述: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabc ...

  7. python亲和性分析法推荐电影论文_关于《Python数据挖掘入门与实战》读书笔记二(亲和性分析)...

    #原文的代码比较零散,网上的代码大多数互抄,先基于个人的理解对代码进行了归纳整理,并添加了注释importnumpyasnpfromcollectionsimportdefaultdictfromop ...

  8. java如何实现redis分片存储_面试官:你说一下Redis吧,怎么实现高可用,还有持久化怎么做的?...

    前言 作为Java程序员,在面试过程中,缓存相关的问题是躲不掉的,肯定会问,例如缓存一致性问题,缓存雪崩.击穿.穿透等.说到缓存,那肯定少不了Redis,我在面试的时候也是被问了很多关于Redis相关 ...

  9. redis删除过期key的算法_面试官别再问我Redis内存满了该怎么办了

    概述 Redis的文章,我之前写过一篇关于「Redis的缓存的三大问题」,累计阅读也快800了,对于还只有3k左右的粉丝量,能够达到这个阅读量,已经是比较难了. 这说明那篇文章写的还过得去,收到很多人 ...

最新文章

  1. 用Leangoo管理你的项目
  2. WCF中常见的几种Host,承载WCF服务的方法详解
  3. 这是我见过最蛋疼的注册中心与API网关实践!
  4. day07 数据类型的内置方法(列表的内置方法)
  5. 设置elf文件链接库的路径
  6. 【转】SAP开关账期后台任务
  7. Android Bitmap面面观
  8. 区别 和esc 打印指令tsc_复印机和打印机仅仅是功能上的区别?
  9. 数字化时代的新职业教育行业洞察
  10. 七、gradle依赖管理
  11. linux 关闭rsync服务器,linux下配置rsync服务器和实时同步
  12. C++进阶教程之预存处理器
  13. 2.5亿!华为成立新公司!
  14. 马哥Linux培训第二周课程作业
  15. 帆软报表多行多条数据写入表_超多种类的报表模板,填上数据就能用,全拿走!...
  16. 超酷的屏幕抠图转场技巧
  17. android 自定义圆点,Android自定义带圆点的半圆形进度条
  18. 0045-一个Dashbord页面监控多个消费者
  19. 初始化NC用友的表结构数据文件
  20. 边缘云市场份额,百度智能云领先!

热门文章

  1. 让visual连接sqlserver数据库
  2. 格式 数组的基本使用 0912
  3. dj鲜生-17-改造激活用户的代码-解决安全隐患
  4. dj电商-模型类设计-1.x-模型类抽象基类
  5. Laravel Eloquent关联模型查询设置查询条件与指定字段
  6. slider改变对话框颜色
  7. MetaMask以太坊钱包插件
  8. 打印iphone支持的所有字体
  9. freemarker判断是否为空
  10. Java RMI 介绍