目录
1.1 发布订阅
1.1.1 什么是发布订阅
Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis客户端可以订阅任意数量的频道
当有新的消息通过 PUBLISH 命令发送给频道 channel1 时,这个消息就会被发送给订阅的三个客户端
1.1.2 常用命令
命令语法 | 描述 |
PSUBSCRIBE pattern [pattern......] | 订阅一个或多个符合给定模式的频道 |
PUBSUB subcommand [argument [argument...]] | 查看订阅与发布系统的状态 |
PUBLISH channel message | 将信息发送到指定的频道 |
PUNSUBSCRIBE [pattern [pattern......]] | 退订所有给定模式的频道 |
SUBSCRIBE channel [channel......] | 订阅给定的一个或者多个频道信息 |
UNSUBSCRIBE [channel [channel......]] | 退订给定的频道 |
1.1.3 示例演示
创建四个客户端Cli_1~Cli4
#cli1 创建订阅的频道redisChat
127.0.0.1:6379> SUBSCRIBE redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1
#cli2 在同一频道redisChat 发布消息
127.0.0.1:6379> PUBLISH redisChat "SendMessage_1"
(integer) 1
#此处可切换到 cli1内查看是否读取到cli2发布的消息
#cli3 在同一频道redisChat 发布消息
127.0.0.1:6379> PUBLISH redisChat "SendMessage_2"
(integer) 1
#此处可切换到 cli1内查看是否读取到cli3发布的消息
#cli4 创建订阅的频道redisChat
127.0.0.1:6379> SUBSCRIBE redisChat
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChat"
3) (integer) 1
#cli3 在同一频道redisChat 发布消息
127.0.0.1:6379> PUBLISH redisChat "SendMessage_2"
(integer) 1
#此处可切换到 cli1及cli4内查看是否读取到cli3发布的消息
cli1收到3条信息 分别来自于 cli2一次 以及 cli3两次
cli4收到1条信息 cli3一次
1.2 事务管理
1.2.1 事务定义
Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断
Redis 事务的主要作用就是串联多个命令防止别的命令插队
1.2.2 Multi、Exec、discard
从输入Multi命令开始,后面输入的数量命令都会一次进入到命令队列当中,但是不会执行,直到输入Exec后,Redis会将之前的命令队列中的命令依次执行
组队过程中,可以通过 discard 来放弃组队
Redis的事务可以一次执行多条命令
批量操作在发送 Exec 命令前被放入队列缓存
收到 Exec 命令后,进入事务执行,如果事务中有任意命令执行失败,其余的命令依旧会执行
在事务的执行过程中,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求,不会插入到事务执行的命令序列中
1.2.3 示例
#组队阶段成功、提交成功的情况
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
#组队阶段报错、提交必然报错(所有数据全部回滚)
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> set k4
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)> set k5 v5
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
#组队阶段成功、提交时发现组队命令有异常
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> incr k3
QUEUED
127.0.0.1:6379(TX)> set k4 v4
QUEUED
127.0.0.1:6379(TX)> get k3
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK
4) "v3"
1.2.4 事务的错误处理
组队时某个命令出现了错误报告,执行时整个的队列都会被取消
执行时某个命令报错,则只有报错的命令不会被执行,而其他命令都会执行,不会回滚
1.2.5 事务的冲突问题
1.2.5.1 事务场景
有一账户余额为10000元,现在出现三个请求,第一个请求想给金额-8000元,第二个请求想给金额-5000元,第三个请求想给金额-1000元
如果没有事务管理,则有可能出现如下场景
1.2.5.2 悲观锁
悲观锁(Pessimistic Lock)顾名思义,就是很悲观。每次去拿数据时都认为别人会修改,所以在每次拿数据时都会上锁,这样别人想拿到这个数据就会停顿,直到它拿到锁为止。在传统的关系型数据库内就会用到这种锁机制,比如 行锁 表锁 读锁 写锁,都是在操作之前先进行上锁处理
1.2.5.3 乐观锁
乐观锁(Optimistic Lock)顾名思义,就是很乐观。每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的
1.2.5.4 事务解决冲突(WATCH)
在执行multi之前,先执行 watch key1 [key2 ....] 用于指定key的监视,如果在事务执行前这些key被其他命令锁改动,那么事务将被打断
#cli1
set money 10000
#cli2
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 8000
QUEUED
#cli3
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> decrby money 3000
QUEUED
#cli2
exec
#cli3
exec
1.2.5.5 unwatch
用于取消命令对所有key的监视
如果在执行 watch 命令之后,Exec 或 DisCard 命令先被执行的话,那么就不需要再次执行 unwatch
1.2.6 Redis事务的三个特征
单独的隔离操作 | 事务中所有命令都会序列化,按顺序执行。事务在执行过程中,不会被其他客户端发来的请求所打断 |
没有隔离级别的概念 | 队列中的命令没有提交前都不会被实际执行,因为事务提交前,所有指令都是处于等待状态 |
不保证原子性 | 事务中如果有一条命令执行失败,其后命令以及会执行,并且不会回滚 |