Redis学习笔记:核心概念
Redis学习笔记系列文章共六篇:
- Redis学习笔记:快速入门
- Redis学习笔记:核心概念
- Redis学习笔记:性能优化
- Redis学习笔记:分布式方案
- Redis学习笔记:springboot实战(附封装完成代码)
- Redis学习笔记:常见面试题及答案
写这个系列文章一是为了查漏补缺,二是帮助更多小伙伴快速掌握Redis核心知识,本文是第二篇,现在开始吧。
在上一篇快速入门中,我们了解了Redis 中五种数据结构的基本操作。需要了解更多关于Redis的命令,或者工作时需要需要查询,可以看下面这个文档。
本篇从主要讲述以下几个核心概念。
一、发布/订阅(Pub/Sub)
二、排序
三、Redis基本事务
四、过期密钥
一、发布/订阅(Pub/Sub)
就像一个广播电台。发布者在广播电台发送消息,订阅者可以收听广播电台。发布者可以从任何广播电台发布,而订阅者也可以同时收听多个广播电台。
发布/订阅的特点:监听者订阅频道,发布者向频道发消息。任何收听订阅频道的人都会在连接和收听时收到发送到该频道的所有消息。
常用命令:
命令 | 简单使用和描述 |
---|---|
SUBSCRIBE(订阅) | SUBSCRIBE channel [channel …]订阅给定的频道 |
UNSUBSCRIBE(退订) | UNSUBSCRIBE [channel [channel …]] - 取消订阅提供的频道,或者如果没有给定频道,则取消订阅所有频道 |
PUBLISH(发布) | PUBLISH 频道消息 — 将消息发布到给定频道 |
PSUBSCRIBE(订阅) | PSUBSCRIBE pattern [pattern ...] - 订阅广播到符合给定模式的频道的信息。 |
PUNSUBSCRIBE(取消订阅) | PUNSUBSCRIBE [pattern [pattern ...]] - 取消订阅提供的模式,或者取消订阅所有订阅的模式,如果没有给出 |
示例:
创建一个订阅频道名为 runoobChat:
redis 127.0.0.1:6379> SUBSCRIBE runoobChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "runoobChat"
3) (integer) 1
重新开启一个 redis 客户端,然后在同一个频道 runoobChat 发布两次消息,订阅者就能接收到消息。
redis 127.0.0.1:6379> PUBLISH runoobChat "Redis PUBLISH test"
(integer) 1
redis 127.0.0.1:6379> PUBLISH runoobChat "Learn redis by runoob.com"
(integer) 1
# 订阅者的客户端会显示如下消息
1) "message"
2) "runoobChat"
3) "Redis PUBLISH test"
1) "message"
2) "runoobChat"
3) "Learn redis by runoob.com"
缺点:
1.在旧版本的 Redis 中,订阅了频道但没有足够快地读取已发送消息的客户端,可能会导致 Redis 本身保持较大的缓冲区。
如果这个缓冲区变得太大,可能会导致 Redis 急剧减速或崩溃,可能导致操作系统杀死 Redis,甚至可能导致操作系统崩溃。
而较新版本的 Redis 没有这个问题,并且会及时断开无法跟上的订阅客户端。
2.数据传输可靠性差。在任何类型的网络系统中,都必须考虑到连接失败的情况。通常,这是由一侧或另一侧连接错误后,重新进行连接。
Python Redis 客户端通常会通过在失败时自动重新连接、自动处理连接池等方式很好地处理连接问题。
但是对于已经订阅的客户端,如果客户端断开连接并且在重新连接之前发送了一条消息,客户端将永远看不到该消息,也就说会丢失一些数据。
二、排序
Redis 中的排序类似于其他语言中的排序。我们使用sort进行排序操作。
命令 | 描述 |
---|---|
sort | SORT source-key [BY pattern] [LIMIT offset count] [GET pattern [GET pattern ...]]。[ASC \ DESC] [ALPHA] [STORE dest-key] - 根据提供的选项对输入的LIST、SET或ZSET进行排序,并返回或存储结果。 |
简单的示例如下:
>>> conn.rpush('sort-input', 23, 15, 110, 7)
4
>>> conn.sort('sort-input')
['7', '15', '23', '110']
#可以对项目进行数字排序。
>>> conn.sort('sort-input', alpha=True)
['110', '15', '23', '7']
#按字母顺序对项目进行排序
>>> conn.hset('d-7', 'field', 5)
1L
>>> conn.hset('d-15', 'field', 1)
1L
>>> conn.hset('d-23', 'field', 9)
1L
>>> conn.hset('d-110', 'field', 3)
1L
#增加了一些额外的数据,用于排序和获取
>>> conn.sort('sort-input', by='d-*->field')
['15', '110', '7', '23']
#可以按HASH字段对数据进行排序。
>>> conn.sort('sort-input', by='d-*->field', get='d-*->field')
['1', '3', '5', '9']
三、Redis基本事务
在 Redis 中,一个基本事务就是为一个客户端提供执行多个命令 A、B、C ……而其他客户端无法中断它们的机会。这和关系数据库事务不同,关系数据库事务可以部分执行,然后回滚或提交。
在 Redis 中,每个命令都作为基本命令的一部分传递多/执行事务一个接一个地执行,直到它们完成。完成后,其他客户端可以执行他们的命令。
MULTI
、 EXEC
、 DISCARD
、WATCH
和 UNWATCH
是 Redis 事务相关的命令。事务可以一次执行多个命令, 并且带有以下两个重要的保证:
- 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
- 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。
命令 | 描述 |
---|---|
MULTI | 标记一个事务块的开始。 |
EXEC | 执行所有事务块内的命令。 |
DISCARD | 取消事务,放弃执行事务块内的所有命令。 |
WATCH | 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。 |
UNWATCH | 取消 WATCH 命令对所有 key 的监视。 |
MULTI、EXEC示例:
redis 127.0.0.1:6379> MULTI
OK
redis 127.0.0.1:6379> SET book-name "Mastering C++ in 21 days"
QUEUED
redis 127.0.0.1:6379> GET book-name
QUEUED
redis 127.0.0.1:6379> SADD tag "C++" "Programming" "Mastering Series"
QUEUED
redis 127.0.0.1:6379> SMEMBERS tag
QUEUED
redis 127.0.0.1:6379> EXEC
1) OK
2) "Mastering C++ in 21 days"
3) (integer) 3
4) 1) "Mastering Series"
2) "C++"
3) "Programming"
关于WATCH与UNWATCH
WATCH 使得 EXEC 命令需要有条件地执行: 事务只能在所有被监视键都没有被修改的前提下执行, 如果这个前提不能满足的话,事务就不会被执行。
WATCH 命令可以被调用多次。 对键的监视从 WATCH 执行之后开始生效, 直到调用 EXEC 为止。
用户还可以在单个 WATCH 命令中监视任意多个键, 就像这样:
redis> WATCH key1 key2 key3 OK
当 EXEC 被调用时, 不管事务是否成功执行, 对所有键的监视都会被取消。
另外, 当客户端断开连接时, 该客户端对键的监视也会被取消。
使用无参数的 UNWATCH 命令可以手动取消对所有键的监视。 对于一些需要改动多个键的事务, 有时候程序需要同时对多个键进行加锁, 然后检查这些键的当前值是否符合程序的要求。 当值达不到要求时, 就可以使用 UNWATCH 命令来取消目前对键的监视, 中途放弃这个事务, 并等待事务的下次尝试。
四、过期密钥
在将数据写入 Redis 时,可能需要数据在一定时间内失效,如token等。如果我们需要在指定的时间超时后删除整个key,我们可以使用expire。当我们说一个 key 有time to live或者它会在给定时间过期时,Redis 会在 key 过期时自动删除它。
过期密钥对于处理缓存数据的清理非常好用。
命令 | 描述 |
---|---|
PERSIST | PERSIST key-name — 删除密钥的过期时间 |
TTL | TTL key-name - 返回钥匙过期前的剩余时间。 |
EXPIRE | EXPIRE key-name seconds - 设置钥匙在给定的秒数内过期。 |
EXPIREAT | EXPIREAT key-name timestamp - 将过期时间设置为给定的Unix时间戳。 |
PTTL | PTTL key-name - 返回密钥过期前的毫秒数(在Redis 2.6及以后版本中可用)。 |
PEXPIRE | PEXPIRE key-name milliseconds - 设置密钥在给定的毫秒数内过期(在Redis 2.6及以后版本中可用)。 |
PEXPIREAT | PEXPIREAT key-name timestamp-milliseconds - 将过期时间设置为以毫秒为单位的给定Unix时间戳(在Redis 2.6及以后版本中可用)。 |
简单示例如下:
>>> conn.set('key', 'value')
True
>>> conn.get('key')
'value'
>>> conn.expire('key', 2)
True
>>> time.sleep(2)
>>> conn.get('key')
>>> conn.set('key', 'value2')
True
>>> conn.expire('key', 100); conn.ttl('key')
True
100
转载自:https://juejin.cn/post/7081439451901067295